refactor: fav and workspace (#3837)

* refactor: workspace

* chore: update collab rev

* test: add data migration test

* fix: test

* fix: tauri build

* test: fix bloc test

* test: fix bloc test

* test: fix bloc test

* chore: restore magic codde
This commit is contained in:
Nathan.fooo 2023-11-01 11:45:35 +08:00 committed by GitHub
parent 54dbcb7c5e
commit 3e088d48ac
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
79 changed files with 646 additions and 661 deletions

View File

@ -53,7 +53,7 @@ void main() {
await tester.favoriteViewByName(names[1]);
expect(
tester.findFavoritePageName(names[1]),
findsNWidgets(2),
findsNWidgets(1),
);
await tester.unfavoriteViewByName(gettingStarted);
@ -131,7 +131,7 @@ void main() {
widget.view.isFavorite &&
widget.categoryType == FolderCategoryType.favorite,
),
findsNWidgets(6),
findsNWidgets(3),
);
await tester.hoverOnPageName(
@ -150,7 +150,7 @@ void main() {
widget.view.isFavorite &&
widget.categoryType == FolderCategoryType.favorite,
),
findsNWidgets(3),
findsNWidgets(2),
);
await tester.hoverOnPageName(

View File

@ -29,7 +29,7 @@ class MobileFavoritePageFolder extends StatelessWidget {
BlocProvider(
create: (_) => MenuBloc(
user: userProfile,
workspace: workspaceSetting.workspace,
workspaceId: workspaceSetting.workspaceId,
)..add(const MenuEvent.initial()),
),
BlocProvider(

View File

@ -19,7 +19,7 @@ class MobileFavoriteScreen extends StatelessWidget {
Widget build(BuildContext context) {
return FutureBuilder(
future: Future.wait([
FolderEventGetCurrentWorkspace().send(),
FolderEventGetCurrentWorkspaceSetting().send(),
getIt<AuthService>().getUser(),
]),
builder: (context, snapshots) {

View File

@ -29,7 +29,7 @@ class MobileFolders extends StatelessWidget {
BlocProvider(
create: (_) => MenuBloc(
user: user,
workspace: workspaceSetting.workspace,
workspaceId: workspaceSetting.workspaceId,
)..add(const MenuEvent.initial()),
),
BlocProvider(

View File

@ -24,7 +24,7 @@ class MobileHomeScreen extends StatelessWidget {
Widget build(BuildContext context) {
return FutureBuilder(
future: Future.wait([
FolderEventGetCurrentWorkspace().send(),
FolderEventGetCurrentWorkspaceSetting().send(),
getIt<AuthService>().getUser(),
]),
builder: (context, snapshots) {

View File

@ -90,14 +90,14 @@ class UserBackendService {
}
Future<Either<List<WorkspacePB>, FlowyError>> getWorkspaces() {
final request = WorkspaceIdPB.create();
return FolderEventReadAllWorkspaces(request).send().then((result) {
return result.fold(
(workspaces) => left(workspaces.items),
(error) => right(error),
);
});
// final request = WorkspaceIdPB.create();
// return FolderEventReadAllWorkspaces(request).send().then((result) {
// return result.fold(
// (workspaces) => left(workspaces.items),
// (error) => right(error),
// );
// });
return Future.value(left([]));
}
Future<Either<WorkspacePB, FlowyError>> openWorkspace(String workspaceId) {
@ -110,6 +110,15 @@ class UserBackendService {
});
}
Future<Either<WorkspacePB, FlowyError>> getCurrentWorkspace() {
return FolderEventReadCurrentWorkspace().send().then((result) {
return result.fold(
(workspace) => left(workspace),
(error) => right(error),
);
});
}
Future<Either<WorkspacePB, FlowyError>> createWorkspace(
String name,
String desc,

View File

@ -42,7 +42,7 @@ class AuthRouter {
BuildContext context,
UserProfilePB userProfile,
) async {
final result = await FolderEventGetCurrentWorkspace().send();
final result = await FolderEventGetCurrentWorkspaceSetting().send();
result.fold(
(workspaceSetting) {
// Replace SignInScreen or SkipLogInScreen as root page.
@ -104,7 +104,7 @@ class SplashRouter {
},
);
FolderEventGetCurrentWorkspace().send().then((result) {
FolderEventGetCurrentWorkspaceSetting().send().then((result) {
result.fold(
(workspaceSettingPB) => pushHomeScreen(context),
(r) => null,

View File

@ -75,7 +75,7 @@ class SplashScreen extends StatelessWidget {
if (check.requireSecret) {
getIt<AuthRouter>().pushEncryptionScreen(context, userProfile);
} else {
final result = await FolderEventGetCurrentWorkspace().send();
final result = await FolderEventGetCurrentWorkspaceSetting().send();
result.fold(
(workspaceSetting) {
// After login, replace Splash screen by corresponding home screen

View File

@ -41,8 +41,8 @@ class HomeBloc extends Bloc<HomeEvent, HomeState> {
emit(state.copyWith(isLoading: e.isLoading));
},
didReceiveWorkspaceSetting: (_DidReceiveWorkspaceSetting value) {
final latestView = workspaceSetting.hasLatestView()
? workspaceSetting.latestView
final latestView = value.setting.hasLatestView()
? value.setting.latestView
: state.latestView;
emit(

View File

@ -5,7 +5,6 @@ import 'package:appflowy/workspace/application/workspace/workspace_service.dart'
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
@ -17,17 +16,17 @@ class MenuBloc extends Bloc<MenuEvent, MenuState> {
final WorkspaceService _workspaceService;
final WorkspaceListener _listener;
final UserProfilePB user;
final WorkspacePB workspace;
final String workspaceId;
MenuBloc({
required this.user,
required this.workspace,
}) : _workspaceService = WorkspaceService(workspaceId: workspace.id),
required this.workspaceId,
}) : _workspaceService = WorkspaceService(workspaceId: workspaceId),
_listener = WorkspaceListener(
user: user,
workspaceId: workspace.id,
workspaceId: workspaceId,
),
super(MenuState.initial(workspace)) {
super(MenuState.initial()) {
on<MenuEvent>((event, emit) async {
await event.map(
initial: (e) async {
@ -122,8 +121,8 @@ class MenuState with _$MenuState {
ViewPB? lastCreatedView,
}) = _MenuState;
factory MenuState.initial(WorkspacePB workspace) => MenuState(
views: workspace.views,
factory MenuState.initial() => MenuState(
views: [],
successOrFailure: left(unit),
lastCreatedView: null,
);

View File

@ -200,10 +200,10 @@ class ViewBackendService {
Future<List<ViewPB>> fetchViews() async {
final result = <ViewPB>[];
return FolderEventGetCurrentWorkspace().send().then((value) async {
final workspaces = value.getLeftOrNull<WorkspaceSettingPB>();
if (workspaces != null) {
final views = workspaces.workspace.views;
return FolderEventReadCurrentWorkspace().send().then((value) async {
final workspace = value.getLeftOrNull<WorkspacePB>();
if (workspace != null) {
final views = workspace.views;
for (final view in views) {
result.add(view);
final childViews = await getAllViews(view);

View File

@ -1,15 +1,12 @@
import 'dart:async';
import 'package:dartz/dartz.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:appflowy_backend/dispatch/dispatch.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-folder2/view.pb.dart'
show CreateViewPayloadPB, MoveViewPayloadPB, ViewLayoutPB, ViewPB;
import 'package:appflowy_backend/protobuf/flowy-folder2/workspace.pb.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
class WorkspaceService {
final String workspaceId;
WorkspaceService({
@ -38,24 +35,7 @@ class WorkspaceService {
}
Future<Either<WorkspacePB, FlowyError>> getWorkspace() {
final payload = WorkspaceIdPB.create()..value = workspaceId;
return FolderEventReadAllWorkspaces(payload).send().then((result) {
return result.fold(
(workspaces) {
assert(workspaces.items.length == 1);
if (workspaces.items.isEmpty) {
return right(
FlowyError.create()
..msg = LocaleKeys.workspace_notFoundError.tr(),
);
} else {
return left(workspaces.items[0]);
}
},
(error) => right(error),
);
});
return FolderEventReadCurrentWorkspace().send();
}
Future<Either<List<ViewPB>, FlowyError>> getViews() {

View File

@ -39,7 +39,7 @@ class DesktopHomeScreen extends StatelessWidget {
Widget build(BuildContext context) {
return FutureBuilder(
future: Future.wait([
FolderEventGetCurrentWorkspace().send(),
FolderEventGetCurrentWorkspaceSetting().send(),
getIt<AuthService>().getUser(),
]),
builder: (context, snapshots) {

View File

@ -46,7 +46,7 @@ class HomeSideBar extends StatelessWidget {
BlocProvider(
create: (_) => MenuBloc(
user: user,
workspace: workspaceSetting.workspace,
workspaceId: workspaceSetting.workspaceId,
)..add(const MenuEvent.initial()),
),
BlocProvider(

View File

@ -33,14 +33,14 @@ class _FileExporterWidgetState extends State<FileExporterWidget> {
@override
Widget build(BuildContext context) {
return FutureBuilder<dartz.Either<WorkspaceSettingPB, FlowyError>>(
future: FolderEventGetCurrentWorkspace().send(),
return FutureBuilder<dartz.Either<WorkspacePB, FlowyError>>(
future: FolderEventReadCurrentWorkspace().send(),
builder: (context, snapshot) {
if (snapshot.hasData &&
snapshot.connectionState == ConnectionState.done) {
final workspaces = snapshot.data?.getLeftOrNull<WorkspaceSettingPB>();
if (workspaces != null) {
final views = workspaces.workspace.views;
final workspace = snapshot.data?.getLeftOrNull<WorkspacePB>();
if (workspace != null) {
final views = workspace.views;
cubit ??= SettingsFileExporterCubit(views: views);
return BlocProvider<SettingsFileExporterCubit>.value(
value: cubit!,

View File

@ -126,7 +126,7 @@ void main() {
..add(const DocumentEvent.initial());
await blocResponseFuture();
final workspaceSetting = await FolderEventGetCurrentWorkspace()
final workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send()
.then((result) => result.fold((l) => l, (r) => throw Exception()));
workspaceSetting.latestView.id == document1.id;
@ -147,7 +147,7 @@ void main() {
final grid = bloc.state.latestCreatedView;
assert(grid!.name == "grid 2");
var workspaceSetting = await FolderEventGetCurrentWorkspace()
var workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send()
.then((result) => result.fold((l) => l, (r) => throw Exception()));
workspaceSetting.latestView.id == grid!.id;
@ -158,7 +158,7 @@ void main() {
..add(const DocumentEvent.initial());
await blocResponseFuture();
workspaceSetting = await FolderEventGetCurrentWorkspace()
workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send()
.then((result) => result.fold((l) => l, (r) => throw Exception()));
workspaceSetting.latestView.id == document.id;

View File

@ -14,7 +14,7 @@ void main() {
});
test('initi home screen', () async {
final workspaceSetting = await FolderEventGetCurrentWorkspace()
final workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send()
.then((result) => result.fold((l) => l, (r) => throw Exception()));
await blocResponseFuture();
@ -27,7 +27,7 @@ void main() {
});
test('open the document', () async {
final workspaceSetting = await FolderEventGetCurrentWorkspace()
final workspaceSetting = await FolderEventGetCurrentWorkspaceSetting()
.send()
.then((result) => result.fold((l) => l, (r) => throw Exception()));
await blocResponseFuture();
@ -52,6 +52,7 @@ void main() {
await FolderEventSetLatestView(ViewIdPB(value: latestView.id)).send();
await blocResponseFuture();
assert(homeBloc.state.workspaceSetting.latestView.id == latestView.id);
final actual = homeBloc.state.workspaceSetting.latestView.id;
assert(actual == latestView.id);
});
}

View File

@ -12,7 +12,7 @@ void main() {
test('assert initial apps is the build-in app', () async {
final menuBloc = MenuBloc(
user: testContext.userProfile,
workspace: testContext.currentWorkspace,
workspaceId: testContext.currentWorkspace.id,
)..add(const MenuEvent.initial());
await blocResponseFuture();
@ -22,7 +22,7 @@ void main() {
test('reorder apps', () async {
final menuBloc = MenuBloc(
user: testContext.userProfile,
workspace: testContext.currentWorkspace,
workspaceId: testContext.currentWorkspace.id,
)..add(const MenuEvent.initial());
await blocResponseFuture();
menuBloc.add(const MenuEvent.createApp("App 1"));

View File

@ -27,7 +27,7 @@ class AppFlowyUnitTest {
late UserProfilePB userProfile;
late UserBackendService userService;
late WorkspaceService workspaceService;
late List<WorkspacePB> workspaces;
late WorkspacePB workspace;
static Future<AppFlowyUnitTest> ensureInitialized() async {
TestWidgetsFlutterBinding.ensureInitialized();
@ -68,12 +68,12 @@ class AppFlowyUnitTest {
);
}
WorkspacePB get currentWorkspace => workspaces[0];
WorkspacePB get currentWorkspace => workspace;
Future<void> _loadWorkspace() async {
final result = await userService.getWorkspaces();
final result = await userService.getCurrentWorkspace();
result.fold(
(value) => workspaces = value,
(value) => workspace = value,
(error) {
throw Exception(error);
},

View File

@ -445,7 +445,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [
"borsh-derive",
"hashbrown 0.13.2",
"hashbrown 0.12.3",
]
[[package]]
@ -845,7 +845,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"async-trait",
@ -864,7 +864,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"async-trait",
@ -894,7 +894,7 @@ dependencies = [
[[package]]
name = "collab-derive"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"proc-macro2",
"quote",
@ -906,7 +906,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"collab",
@ -926,7 +926,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"bytes",
@ -940,7 +940,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"chrono",
@ -982,7 +982,7 @@ dependencies = [
[[package]]
name = "collab-persistence"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"async-trait",
"bincode",
@ -1003,7 +1003,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"async-trait",
@ -1030,7 +1030,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"collab",

View File

@ -48,14 +48,14 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c87
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }

View File

@ -2,9 +2,9 @@ import { currentUserActions } from '../../stores/reducers/current-user/slice';
import { useAppDispatch, useAppSelector } from '../../stores/store';
import { UserProfilePB } from '../../../services/backend/events/flowy-user';
import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc';
import { FolderEventGetCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder2/workspace';
import { Log } from '../../utils/log';
import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder2';
export const useAuth = () => {
const dispatch = useAppDispatch();
@ -99,7 +99,7 @@ export const useAuth = () => {
}
async function _openWorkspace() {
return FolderEventGetCurrentWorkspace();
return FolderEventGetCurrentWorkspaceSetting();
}
return { currentUser, checkUser, register, login, logout };

View File

@ -6,7 +6,6 @@ import {
ViewPB,
WorkspaceSettingPB,
} from '../../../services/backend';
import { FolderEventGetCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
import { DatabaseController } from '../../stores/effects/database/database_controller';
import { RowInfo } from '../../stores/effects/database/row/row_cache';
import { RowController } from '../../stores/effects/database/row/row_controller';
@ -28,12 +27,15 @@ import { makeSingleSelectTypeOptionContext } from '../../stores/effects/database
import { SelectOptionBackendService } from '../../stores/effects/database/cell/select_option_bd_svc';
import { Log } from '$app/utils/log';
import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller';
import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder2';
// Create a database page for specific layout type
// Do not use it production code. Just for testing
export async function createTestDatabaseView(layout: ViewLayoutPB): Promise<ViewPB> {
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspace().then((result) => result.unwrap());
const wsSvc = new WorkspaceController(workspaceSetting.workspace.id);
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspaceSetting().then((result) =>
result.unwrap()
);
const wsSvc = new WorkspaceController(workspaceSetting.workspace_id);
const viewRes = await wsSvc.createView({ name: 'New Grid', layout });
return viewRes;

View File

@ -1,10 +1,12 @@
import { ViewLayoutPB, WorkspaceSettingPB } from '@/services/backend';
import { FolderEventGetCurrentWorkspace } from '@/services/backend/events/flowy-folder2';
import { WorkspaceController } from '../../stores/effects/workspace/workspace_controller';
import { FolderEventGetCurrentWorkspaceSetting } from '@/services/backend/events/flowy-folder2';
export async function createTestDocument() {
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspace().then((result) => result.unwrap());
const appService = new WorkspaceController(workspaceSetting.workspace.id);
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspaceSetting().then((result) =>
result.unwrap()
);
const appService = new WorkspaceController(workspaceSetting.workspace_id);
const result = await appService.createView({ name: 'New Document', layout: ViewLayoutPB.Document });
return result;

View File

@ -18,9 +18,8 @@ const testCreateFolder = async (userId?: number) => {
console.log('workspaces: ', workspaces.val.toObject());
}
const currentWorkspace = await userBackendService.getCurrentWorkspace();
const workspaceService = new WorkspaceController(currentWorkspace.workspace.id);
const currentWorkspaceSetting = await userBackendService.getCurrentWorkspaceSetting();
const workspaceService = new WorkspaceController(currentWorkspaceSetting.workspace_id);
const rootViews: ViewPB[] = [];
for (let i = 1; i <= 3; i++) {

View File

@ -25,8 +25,8 @@ import {
import {
FolderEventCreateWorkspace,
FolderEventOpenWorkspace,
FolderEventGetCurrentWorkspace,
FolderEventReadAllWorkspaces,
FolderEventGetCurrentWorkspaceSetting,
FolderEventReadCurrentWorkspace,
} from '@/services/backend/events/flowy-folder2';
export class UserBackendService {
@ -56,8 +56,8 @@ export class UserBackendService {
return UserEventUpdateUserProfile(payload);
};
getCurrentWorkspace = async (): Promise<WorkspaceSettingPB> => {
const result = await FolderEventGetCurrentWorkspace();
getCurrentWorkspaceSetting = async (): Promise<WorkspaceSettingPB> => {
const result = await FolderEventGetCurrentWorkspaceSetting();
if (result.ok) {
return result.val;
@ -67,14 +67,11 @@ export class UserBackendService {
};
getWorkspaces = () => {
const payload = WorkspaceIdPB.fromObject({});
return FolderEventReadAllWorkspaces(payload);
return FolderEventReadCurrentWorkspace();
};
openWorkspace = (workspaceId: string) => {
const payload = WorkspaceIdPB.fromObject({ value: workspaceId });
return FolderEventOpenWorkspace(payload);
};
@ -115,9 +112,14 @@ export class AuthBackendService {
return UserEventSignIn(payload);
};
signUp = (params: { name: string; email: string; password: string; }) => {
signUp = (params: { name: string; email: string; password: string }) => {
const deviceId = nanoid(8);
const payload = SignUpPayloadPB.fromObject({ name: params.name, email: params.email, password: params.password, device_id: deviceId });
const payload = SignUpPayloadPB.fromObject({
name: params.name,
email: params.email,
password: params.password,
device_id: deviceId,
});
return UserEventSignUp(payload);
};

View File

@ -1,12 +1,11 @@
import {
FolderEventCreateWorkspace,
FolderEventGetCurrentWorkspace,
CreateWorkspacePayloadPB,
FolderEventReadAllWorkspaces,
FolderEventOpenWorkspace,
FolderEventDeleteWorkspace,
WorkspaceIdPB,
FolderEventReadWorkspaceViews,
FolderEventReadCurrentWorkspace,
} from '@/services/backend/events/flowy-folder2';
export class WorkspaceBackendService {
@ -41,14 +40,11 @@ export class WorkspaceBackendService {
};
getWorkspaces = async () => {
// if workspaceId is not provided, it will return all workspaces
const workspaceId = new WorkspaceIdPB();
return FolderEventReadAllWorkspaces(workspaceId);
return FolderEventReadCurrentWorkspace();
};
getCurrentWorkspace = async () => {
return FolderEventGetCurrentWorkspace();
return FolderEventReadCurrentWorkspace();
};
getChildPages = async (workspaceId: string) => {

View File

@ -33,14 +33,14 @@ export class WorkspaceManagerController {
const result = await this.backendService.getWorkspaces();
if (result.ok) {
const items = result.val.items;
const item = result.val;
return items.map((item) => {
return {
return [
{
id: item.id,
name: item.name,
};
});
},
];
}
return [];
@ -50,8 +50,7 @@ export class WorkspaceManagerController {
const result = await this.backendService.getCurrentWorkspace();
if (result.ok) {
const workspace = result.val.workspace;
const workspace = result.val;
return {
id: workspace.id,
name: workspace.name,

View File

@ -452,7 +452,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4114279215a005bc675e386011e594e1d9b800918cea18fcadadcce864a2046b"
dependencies = [
"borsh-derive",
"hashbrown 0.13.2",
"hashbrown 0.12.3",
]
[[package]]
@ -712,7 +712,7 @@ dependencies = [
[[package]]
name = "collab"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"async-trait",
@ -731,7 +731,7 @@ dependencies = [
[[package]]
name = "collab-database"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"async-trait",
@ -761,7 +761,7 @@ dependencies = [
[[package]]
name = "collab-derive"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"proc-macro2",
"quote",
@ -773,7 +773,7 @@ dependencies = [
[[package]]
name = "collab-document"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"collab",
@ -793,7 +793,7 @@ dependencies = [
[[package]]
name = "collab-entity"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"bytes",
@ -807,7 +807,7 @@ dependencies = [
[[package]]
name = "collab-folder"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"chrono",
@ -849,7 +849,7 @@ dependencies = [
[[package]]
name = "collab-persistence"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"async-trait",
"bincode",
@ -870,7 +870,7 @@ dependencies = [
[[package]]
name = "collab-plugins"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"async-trait",
@ -897,7 +897,7 @@ dependencies = [
[[package]]
name = "collab-user"
version = "0.1.0"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=8861d7a#8861d7a45a2bda493f307483561d92e31fffff4c"
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=9b05aa7e#9b05aa7e8500b42fa56117052de6e658235d6325"
dependencies = [
"anyhow",
"collab",

View File

@ -92,11 +92,11 @@ client-api = { git = "https://github.com/AppFlowy-IO/AppFlowy-Cloud", rev = "c87
# To switch to the local path, run:
# scripts/tool/update_collab_source.sh
# ⚠️⚠️⚠️️
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "8861d7a" }
collab = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-folder = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-document = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-database = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-plugins = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-user = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-entity = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }
collab-persistence = { git = "https://github.com/AppFlowy-IO/AppFlowy-Collab", rev = "9b05aa7e" }

View File

@ -37,7 +37,7 @@ impl DocumentEventTest {
pub async fn create_document(&self) -> ViewPB {
let core = &self.inner;
let current_workspace = core.get_current_workspace().await.workspace;
let current_workspace = core.get_current_workspace().await;
let parent_id = current_workspace.id.clone();
let payload = CreateViewPayloadPB {

View File

@ -47,12 +47,12 @@ impl EventIntegrationTest {
.items
}
pub async fn get_current_workspace(&self) -> WorkspaceSettingPB {
pub async fn get_current_workspace(&self) -> WorkspacePB {
EventBuilder::new(self.clone())
.event(FolderEvent::GetCurrentWorkspace)
.event(FolderEvent::ReadCurrentWorkspace)
.async_send()
.await
.parse::<WorkspaceSettingPB>()
.parse::<WorkspacePB>()
}
pub async fn get_all_workspace_views(&self) -> Vec<ViewPB> {
@ -148,9 +148,9 @@ pub struct ViewTest {
impl ViewTest {
#[allow(dead_code)]
pub async fn new(sdk: &EventIntegrationTest, layout: ViewLayoutPB, data: Vec<u8>) -> Self {
let workspace = create_workspace(sdk, "Workspace", "").await;
let workspace = sdk.folder_manager.get_current_workspace().await.unwrap();
let payload = WorkspaceIdPB {
value: Some(workspace.id.clone()),
value: workspace.id.clone(),
};
let _ = EventBuilder::new(sdk.clone())
.event(OpenWorkspace)
@ -196,6 +196,7 @@ impl ViewTest {
}
}
#[allow(dead_code)]
async fn create_workspace(sdk: &EventIntegrationTest, name: &str, desc: &str) -> WorkspacePB {
let request = CreateWorkspacePayloadPB {
name: name.to_owned(),

View File

@ -14,7 +14,7 @@ use lib_infra::util::timestamp;
#[tokio::test]
async fn get_database_id_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -36,7 +36,7 @@ async fn get_database_id_event_test() {
#[tokio::test]
async fn get_database_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -50,7 +50,7 @@ async fn get_database_event_test() {
#[tokio::test]
async fn get_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -65,7 +65,7 @@ async fn get_field_event_test() {
#[tokio::test]
async fn create_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -79,7 +79,7 @@ async fn create_field_event_test() {
#[tokio::test]
async fn delete_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -100,7 +100,7 @@ async fn delete_field_event_test() {
#[tokio::test]
async fn delete_primary_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -115,7 +115,7 @@ async fn delete_primary_field_event_test() {
#[tokio::test]
async fn update_field_type_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -133,7 +133,7 @@ async fn update_field_type_event_test() {
#[tokio::test]
async fn update_primary_field_type_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -152,7 +152,7 @@ async fn update_primary_field_type_event_test() {
#[tokio::test]
async fn duplicate_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -170,7 +170,7 @@ async fn duplicate_field_event_test() {
#[tokio::test]
async fn duplicate_primary_field_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -184,7 +184,7 @@ async fn duplicate_primary_field_test() {
#[tokio::test]
async fn get_primary_field_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -197,7 +197,7 @@ async fn get_primary_field_event_test() {
#[tokio::test]
async fn create_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -210,7 +210,7 @@ async fn create_row_event_test() {
#[tokio::test]
async fn delete_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -233,7 +233,7 @@ async fn delete_row_event_test() {
#[tokio::test]
async fn get_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -249,7 +249,7 @@ async fn get_row_event_test() {
#[tokio::test]
async fn update_row_meta_event_with_url_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -277,7 +277,7 @@ async fn update_row_meta_event_with_url_test() {
#[tokio::test]
async fn update_row_meta_event_with_cover_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -305,7 +305,7 @@ async fn update_row_meta_event_with_cover_test() {
#[tokio::test]
async fn delete_row_event_with_invalid_row_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -318,7 +318,7 @@ async fn delete_row_event_with_invalid_row_id_test() {
#[tokio::test]
async fn duplicate_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -335,7 +335,7 @@ async fn duplicate_row_event_test() {
#[tokio::test]
async fn duplicate_row_event_with_invalid_row_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -352,7 +352,7 @@ async fn duplicate_row_event_with_invalid_row_id_test() {
#[tokio::test]
async fn move_row_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -372,7 +372,7 @@ async fn move_row_event_test() {
#[tokio::test]
async fn move_row_event_test2() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -392,7 +392,7 @@ async fn move_row_event_test2() {
#[tokio::test]
async fn move_row_event_with_invalid_row_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -419,7 +419,7 @@ async fn move_row_event_with_invalid_row_id_test() {
#[tokio::test]
async fn update_text_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -449,7 +449,7 @@ async fn update_text_cell_event_test() {
#[tokio::test]
async fn update_checkbox_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -480,7 +480,7 @@ async fn update_checkbox_cell_event_test() {
#[tokio::test]
async fn update_single_select_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -507,7 +507,7 @@ async fn update_single_select_cell_event_test() {
#[tokio::test]
async fn update_date_cell_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -544,7 +544,7 @@ async fn update_date_cell_event_test() {
#[tokio::test]
async fn update_date_cell_event_with_empty_time_str_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -580,7 +580,7 @@ async fn update_date_cell_event_with_empty_time_str_test() {
#[tokio::test]
async fn create_checklist_field_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -601,7 +601,7 @@ async fn create_checklist_field_test() {
#[tokio::test]
async fn update_checklist_cell_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -658,7 +658,7 @@ async fn update_checklist_cell_test() {
#[tokio::test]
async fn get_groups_event_with_grid_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
@ -670,7 +670,7 @@ async fn get_groups_event_with_grid_test() {
#[tokio::test]
async fn get_groups_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
@ -682,7 +682,7 @@ async fn get_groups_event_test() {
#[tokio::test]
async fn move_group_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
@ -716,7 +716,7 @@ async fn move_group_event_test() {
#[tokio::test]
async fn move_group_event_with_invalid_id_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
@ -738,7 +738,7 @@ async fn move_group_event_with_invalid_id_test() {
#[tokio::test]
async fn rename_group_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
@ -763,7 +763,7 @@ async fn rename_group_event_test() {
#[tokio::test]
async fn hide_group_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
@ -791,7 +791,7 @@ async fn hide_group_event_test() {
#[tokio::test]
async fn update_database_layout_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -813,7 +813,7 @@ async fn update_database_layout_event_test() {
#[tokio::test]
async fn update_database_layout_event_test2() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let grid_view = test
.create_grid(&current_workspace.id, "my grid view".to_owned(), vec![])
.await;
@ -845,7 +845,7 @@ async fn update_database_layout_event_test2() {
#[tokio::test]
async fn set_group_by_checkbox_field_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let board_view = test
.create_board(&current_workspace.id, "my board view".to_owned(), vec![])
.await;
@ -862,7 +862,7 @@ async fn set_group_by_checkbox_field_test() {
#[tokio::test]
async fn get_all_calendar_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let calendar_view = test
.create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![])
.await;
@ -875,7 +875,7 @@ async fn get_all_calendar_event_test() {
#[tokio::test]
async fn create_calendar_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let calendar_view = test
.create_calendar(&current_workspace.id, "my calendar view".to_owned(), vec![])
.await;

View File

@ -38,11 +38,7 @@ impl FlowySupabaseDatabaseTest {
let current_workspace = self.inner.get_current_workspace().await;
let view = self
.inner
.create_grid(
&current_workspace.workspace.id,
"my database".to_string(),
vec![],
)
.create_grid(&current_workspace.id, "my database".to_string(), vec![])
.await;
let database = self.inner.get_database(&view.id).await;
(view, database)

View File

@ -18,11 +18,7 @@ impl AFCloudDocumentTest {
let current_workspace = self.inner.get_current_workspace().await;
let view = self
.inner
.create_document(
&current_workspace.workspace.id,
"my document".to_string(),
vec![],
)
.create_document(&current_workspace.id, "my document".to_string(), vec![])
.await;
view.id
}

View File

@ -12,7 +12,7 @@ use crate::document::supabase_test::helper::FlowySupabaseDocumentTest;
#[tokio::test]
async fn supabase_document_upload_text_file_test() {
if let Some(test) = FlowySupabaseDocumentTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id;
let workspace_id = test.get_current_workspace().await.id;
let storage_service = test
.document_manager
.get_file_storage_service()
@ -43,7 +43,7 @@ async fn supabase_document_upload_text_file_test() {
#[tokio::test]
async fn supabase_document_upload_zip_file_test() {
if let Some(test) = FlowySupabaseDocumentTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id;
let workspace_id = test.get_current_workspace().await.id;
let storage_service = test
.document_manager
.get_file_storage_service()
@ -85,7 +85,7 @@ async fn supabase_document_upload_zip_file_test() {
#[tokio::test]
async fn supabase_document_upload_image_test() {
if let Some(test) = FlowySupabaseDocumentTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id;
let workspace_id = test.get_current_workspace().await.id;
let storage_service = test
.document_manager
.get_file_storage_service()

View File

@ -23,11 +23,7 @@ impl FlowySupabaseDocumentTest {
let current_workspace = self.inner.get_current_workspace().await;
self
.inner
.create_document(
&current_workspace.workspace.id,
"my document".to_string(),
vec![],
)
.create_document(&current_workspace.id, "my document".to_string(), vec![])
.await
}

View File

@ -1,53 +1,10 @@
use collab_folder::core::ViewLayout;
use collab_folder::ViewLayout;
use flowy_folder2::entities::icon::{ViewIconPB, ViewIconTypePB};
use crate::folder::local_test::script::FolderScript::*;
use crate::folder::local_test::script::FolderTest;
#[tokio::test]
async fn read_all_workspace_test() {
let mut test = FolderTest::new().await;
test.run_scripts(vec![ReadAllWorkspaces]).await;
assert!(!test.all_workspace.is_empty());
}
#[tokio::test]
async fn create_workspace_test() {
let mut test = FolderTest::new().await;
let name = "My new workspace".to_owned();
let desc = "Daily routines".to_owned();
test
.run_scripts(vec![CreateWorkspace {
name: name.clone(),
desc: desc.clone(),
}])
.await;
let workspace = test.workspace.clone();
assert_eq!(workspace.name, name);
test
.run_scripts(vec![
ReadWorkspace(Some(workspace.id.clone())),
AssertWorkspace(workspace),
])
.await;
}
#[tokio::test]
async fn get_workspace_test() {
let mut test = FolderTest::new().await;
let workspace = test.workspace.clone();
test
.run_scripts(vec![
ReadWorkspace(Some(workspace.id.clone())),
AssertWorkspace(workspace),
])
.await;
}
#[tokio::test]
async fn create_parent_view_test() {
let mut test = FolderTest::new().await;

View File

@ -1,4 +1,4 @@
use collab_folder::core::ViewLayout;
use collab_folder::ViewLayout;
use event_integration::event_builder::EventBuilder;
use event_integration::EventIntegrationTest;
@ -7,14 +7,15 @@ use flowy_folder2::entities::*;
use flowy_folder2::event_map::FolderEvent::*;
pub enum FolderScript {
// Workspace
ReadAllWorkspaces,
#[allow(dead_code)]
CreateWorkspace {
name: String,
desc: String,
},
#[allow(dead_code)]
AssertWorkspace(WorkspacePB),
ReadWorkspace(Option<String>),
#[allow(dead_code)]
ReadWorkspace(String),
// App
CreateParentView {
@ -65,7 +66,6 @@ pub enum FolderScript {
pub struct FolderTest {
pub sdk: EventIntegrationTest,
pub all_workspace: Vec<WorkspacePB>,
pub workspace: WorkspacePB,
pub parent_view: ViewPB,
pub child_view: ViewPB,
@ -77,8 +77,15 @@ impl FolderTest {
pub async fn new() -> Self {
let sdk = EventIntegrationTest::new().await;
let _ = sdk.init_anon_user().await;
let workspace = create_workspace(&sdk, "FolderWorkspace", "Folder test workspace").await;
let parent_view = create_app(&sdk, &workspace.id, "Folder App", "Folder test app").await;
let workspace = sdk.folder_manager.get_current_workspace().await.unwrap();
let parent_view = create_view(
&sdk,
&workspace.id,
"Folder App",
"Folder test app",
ViewLayout::Document,
)
.await;
let view = create_view(
&sdk,
&parent_view.id,
@ -89,7 +96,6 @@ impl FolderTest {
.await;
Self {
sdk,
all_workspace: vec![],
workspace,
parent_view,
child_view: view,
@ -107,10 +113,6 @@ impl FolderTest {
pub async fn run_script(&mut self, script: FolderScript) {
let sdk = &self.sdk;
match script {
FolderScript::ReadAllWorkspaces => {
let all_workspace = read_workspace(sdk, None).await;
self.all_workspace = all_workspace;
},
FolderScript::CreateWorkspace { name, desc } => {
let workspace = create_workspace(sdk, &name, &desc).await;
self.workspace = workspace;
@ -119,11 +121,11 @@ impl FolderTest {
assert_eq!(self.workspace, workspace, "Workspace not equal");
},
FolderScript::ReadWorkspace(workspace_id) => {
let workspace = read_workspace(sdk, workspace_id).await.pop().unwrap();
let workspace = read_workspace(sdk, workspace_id).await;
self.workspace = workspace;
},
FolderScript::CreateParentView { name, desc } => {
let app = create_app(sdk, &self.workspace.id, &name, &desc).await;
let app = create_view(sdk, &self.workspace.id, &name, &desc, ViewLayout::Document).await;
self.parent_view = app;
},
FolderScript::AssertParentView(app) => {
@ -215,70 +217,27 @@ pub async fn create_workspace(sdk: &EventIntegrationTest, name: &str, desc: &str
.parse::<WorkspacePB>()
}
pub async fn read_workspace(
sdk: &EventIntegrationTest,
workspace_id: Option<String>,
) -> Vec<WorkspacePB> {
pub async fn read_workspace(sdk: &EventIntegrationTest, workspace_id: String) -> WorkspacePB {
let request = WorkspaceIdPB {
value: workspace_id,
};
let repeated_workspace = EventBuilder::new(sdk.clone())
.event(ReadAllWorkspaces)
EventBuilder::new(sdk.clone())
.event(ReadCurrentWorkspace)
.payload(request.clone())
.async_send()
.await
.parse::<RepeatedWorkspacePB>();
let workspaces;
if let Some(workspace_id) = &request.value {
workspaces = repeated_workspace
.items
.into_iter()
.filter(|workspace| &workspace.id == workspace_id)
.collect::<Vec<WorkspacePB>>();
debug_assert_eq!(workspaces.len(), 1);
} else {
workspaces = repeated_workspace.items;
}
workspaces
}
pub async fn create_app(
sdk: &EventIntegrationTest,
workspace_id: &str,
name: &str,
desc: &str,
) -> ViewPB {
let create_view_request = CreateViewPayloadPB {
parent_view_id: workspace_id.to_owned(),
name: name.to_string(),
desc: desc.to_string(),
thumbnail: None,
layout: ViewLayout::Document.into(),
initial_data: vec![],
meta: Default::default(),
set_as_current: true,
index: None,
};
EventBuilder::new(sdk.clone())
.event(CreateView)
.payload(create_view_request)
.async_send()
.await
.parse::<ViewPB>()
.parse::<WorkspacePB>()
}
pub async fn create_view(
sdk: &EventIntegrationTest,
app_id: &str,
parent_view_id: &str,
name: &str,
desc: &str,
layout: ViewLayout,
) -> ViewPB {
let request = CreateViewPayloadPB {
parent_view_id: app_id.to_string(),
parent_view_id: parent_view_id.to_string(),
name: name.to_string(),
desc: desc.to_string(),
thumbnail: None,

View File

@ -17,7 +17,7 @@ use crate::util::receive_with_timeout;
/// 6. Ensure that the received views contain the newly created "test_view".
async fn create_child_view_in_workspace_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let workspace = test.get_current_workspace().await.workspace;
let workspace = test.get_current_workspace().await;
let rx = test
.notification_sender
.subscribe::<RepeatedViewPB>(&workspace.id, FolderNotification::DidUpdateWorkspaceViews);
@ -41,7 +41,7 @@ async fn create_child_view_in_workspace_subscription_test() {
#[tokio::test]
async fn create_child_view_in_view_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let mut workspace = test.get_current_workspace().await.workspace;
let mut workspace = test.get_current_workspace().await;
let workspace_child_view = workspace.views.pop().unwrap();
let rx = test.notification_sender.subscribe::<ChildViewUpdatePB>(
&workspace_child_view.id,
@ -73,7 +73,7 @@ async fn create_child_view_in_view_subscription_test() {
#[tokio::test]
async fn delete_view_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let workspace = test.get_current_workspace().await.workspace;
let workspace = test.get_current_workspace().await;
let rx = test
.notification_sender
.subscribe::<ChildViewUpdatePB>(&workspace.id, FolderNotification::DidUpdateChildViews);
@ -104,7 +104,7 @@ async fn delete_view_subscription_test() {
#[tokio::test]
async fn update_view_subscription_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let mut workspace = test.get_current_workspace().await.workspace;
let mut workspace = test.get_current_workspace().await;
let rx = test
.notification_sender
.subscribe::<ChildViewUpdatePB>(&workspace.id, FolderNotification::DidUpdateChildViews);

View File

@ -16,44 +16,45 @@ async fn create_workspace_event_test() {
.payload(request)
.async_send()
.await
.parse::<flowy_folder2::entities::WorkspacePB>();
assert_eq!(resp.name, "my second workspace");
.error()
.unwrap();
assert_eq!(resp.code, ErrorCode::NotSupportYet);
}
#[tokio::test]
async fn open_workspace_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let payload = CreateWorkspacePayloadPB {
name: "my second workspace".to_owned(),
desc: "".to_owned(),
};
// create a workspace
let resp_1 = EventBuilder::new(test.clone())
.event(flowy_folder2::event_map::FolderEvent::CreateWorkspace)
.payload(payload)
.async_send()
.await
.parse::<flowy_folder2::entities::WorkspacePB>();
// open the workspace
let payload = WorkspaceIdPB {
value: Some(resp_1.id.clone()),
};
let resp_2 = EventBuilder::new(test)
.event(flowy_folder2::event_map::FolderEvent::OpenWorkspace)
.payload(payload)
.async_send()
.await
.parse::<flowy_folder2::entities::WorkspacePB>();
assert_eq!(resp_1.id, resp_2.id);
assert_eq!(resp_1.name, resp_2.name);
}
// #[tokio::test]
// async fn open_workspace_event_test() {
// let test = EventIntegrationTest::new_with_guest_user().await;
// let payload = CreateWorkspacePayloadPB {
// name: "my second workspace".to_owned(),
// desc: "".to_owned(),
// };
// // create a workspace
// let resp_1 = EventBuilder::new(test.clone())
// .event(flowy_folder2::event_map::FolderEvent::CreateWorkspace)
// .payload(payload)
// .async_send()
// .await
// .parse::<flowy_folder2::entities::WorkspacePB>();
//
// // open the workspace
// let payload = WorkspaceIdPB {
// value: Some(resp_1.id.clone()),
// };
// let resp_2 = EventBuilder::new(test)
// .event(flowy_folder2::event_map::FolderEvent::OpenWorkspace)
// .payload(payload)
// .async_send()
// .await
// .parse::<flowy_folder2::entities::WorkspacePB>();
//
// assert_eq!(resp_1.id, resp_2.id);
// assert_eq!(resp_1.name, resp_2.name);
// }
#[tokio::test]
async fn create_view_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let view = test
.create_view(&current_workspace.id, "My first view".to_string())
.await;
@ -65,7 +66,7 @@ async fn create_view_event_test() {
#[tokio::test]
async fn update_view_event_with_name_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let view = test
.create_view(&current_workspace.id, "My first view".to_string())
.await;
@ -86,7 +87,7 @@ async fn update_view_event_with_name_test() {
#[tokio::test]
async fn update_view_icon_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let view = test
.create_view(&current_workspace.id, "My first view".to_string())
.await;
@ -110,7 +111,7 @@ async fn update_view_icon_event_test() {
#[tokio::test]
async fn delete_view_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let view = test
.create_view(&current_workspace.id, "My first view".to_string())
.await;
@ -133,7 +134,7 @@ async fn delete_view_event_test() {
#[tokio::test]
async fn put_back_trash_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let view = test
.create_view(&current_workspace.id, "My first view".to_string())
.await;
@ -176,7 +177,7 @@ async fn put_back_trash_event_test() {
#[tokio::test]
async fn delete_view_permanently_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let view = test
.create_view(&current_workspace.id, "My first view".to_string())
.await;
@ -225,7 +226,7 @@ async fn delete_view_permanently_event_test() {
#[tokio::test]
async fn delete_all_trash_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
for i in 0..3 {
let view = test
@ -269,7 +270,7 @@ async fn delete_all_trash_test() {
#[tokio::test]
async fn multiple_hierarchy_view_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
for i in 1..4 {
let parent = test
.create_view(&current_workspace.id, format!("My {} view", i))
@ -345,7 +346,7 @@ async fn multiple_hierarchy_view_test() {
#[tokio::test]
async fn move_view_event_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
for i in 1..4 {
let parent = test
.create_view(&current_workspace.id, format!("My {} view", i))
@ -383,7 +384,7 @@ async fn move_view_event_test() {
#[tokio::test]
async fn move_view_event_after_delete_view_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
for i in 1..6 {
let _ = test
.create_view(&current_workspace.id, format!("My {} view", i))
@ -425,7 +426,7 @@ async fn move_view_event_after_delete_view_test() {
#[tokio::test]
async fn move_view_event_after_delete_view_test2() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let parent = test
.create_view(&current_workspace.id, "My view".to_string())
.await;
@ -495,7 +496,7 @@ fn invalid_workspace_name_test_case() -> Vec<(String, ErrorCode)> {
#[tokio::test]
async fn move_view_across_parent_test() {
let test = EventIntegrationTest::new_with_guest_user().await;
let current_workspace = test.get_current_workspace().await.workspace;
let current_workspace = test.get_current_workspace().await;
let parent_1 = test
.create_view(&current_workspace.id, "My view 1".to_string())
.await;

View File

@ -5,7 +5,7 @@ use collab::core::collab::MutexCollab;
use collab::core::origin::CollabOrigin;
use collab::preclude::updates::decoder::Decode;
use collab::preclude::{merge_updates_v1, JsonValue, Update};
use collab_folder::core::FolderData;
use collab_folder::FolderData;
use event_integration::event_builder::EventBuilder;
use flowy_folder2::entities::{FolderSnapshotPB, RepeatedFolderSnapshotPB, WorkspaceIdPB};
@ -39,7 +39,7 @@ impl FlowySupabaseFolderTest {
EventBuilder::new(self.inner.deref().clone())
.event(GetFolderSnapshots)
.payload(WorkspaceIdPB {
value: Some(workspace_id.to_string()),
value: workspace_id.to_string(),
})
.async_send()
.await

View File

@ -12,11 +12,12 @@ use crate::util::{get_folder_data_from_server, receive_with_timeout};
#[tokio::test]
async fn supabase_encrypt_folder_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let secret = test.enable_encryption().await;
let local_folder_data = test.get_local_folder_data().await;
let workspace_id = test.get_current_workspace().await.workspace.id;
let remote_folder_data = get_folder_data_from_server(&workspace_id, Some(secret))
let workspace_id = test.get_current_workspace().await.id;
let remote_folder_data = get_folder_data_from_server(&uid, &workspace_id, Some(secret))
.await
.unwrap()
.unwrap();
@ -28,8 +29,9 @@ async fn supabase_encrypt_folder_test() {
#[tokio::test]
async fn supabase_decrypt_folder_data_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let secret = Some(test.enable_encryption().await);
let workspace_id = test.get_current_workspace().await.workspace.id;
let workspace_id = test.get_current_workspace().await.id;
test
.create_view(&workspace_id, "encrypt view".to_string())
.await;
@ -41,7 +43,7 @@ async fn supabase_decrypt_folder_data_test() {
receive_with_timeout(rx, Duration::from_secs(10))
.await
.unwrap();
let folder_data = get_folder_data_from_server(&workspace_id, secret)
let folder_data = get_folder_data_from_server(&uid, &workspace_id, secret)
.await
.unwrap()
.unwrap();
@ -54,8 +56,9 @@ async fn supabase_decrypt_folder_data_test() {
#[should_panic]
async fn supabase_decrypt_with_invalid_secret_folder_data_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let uid = test.user_manager.user_id().unwrap();
let _ = Some(test.enable_encryption().await);
let workspace_id = test.get_current_workspace().await.workspace.id;
let workspace_id = test.get_current_workspace().await.id;
test
.create_view(&workspace_id, "encrypt view".to_string())
.await;
@ -66,7 +69,7 @@ async fn supabase_decrypt_with_invalid_secret_folder_data_test() {
.await
.unwrap();
let _ = get_folder_data_from_server(&workspace_id, Some("invalid secret".to_string()))
let _ = get_folder_data_from_server(&uid, &workspace_id, Some("invalid secret".to_string()))
.await
.unwrap();
}
@ -74,7 +77,7 @@ async fn supabase_decrypt_with_invalid_secret_folder_data_test() {
#[tokio::test]
async fn supabase_folder_snapshot_test() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id;
let workspace_id = test.get_current_workspace().await.id;
let rx = test
.notification_sender
.subscribe::<FolderSnapshotStatePB>(&workspace_id, DidUpdateFolderSnapshotState);
@ -92,7 +95,7 @@ async fn supabase_folder_snapshot_test() {
#[tokio::test]
async fn supabase_initial_folder_snapshot_test2() {
if let Some(test) = FlowySupabaseFolderTest::new().await {
let workspace_id = test.get_current_workspace().await.workspace.id;
let workspace_id = test.get_current_workspace().await.id;
test
.create_view(&workspace_id, "supabase test view1".to_string())

View File

@ -38,3 +38,25 @@ async fn migrate_020_historical_empty_document_test() {
assert_eq!(database.rows.len(), 3);
drop(cleaner);
}
#[tokio::test]
async fn migrate_036_fav_v1_workspace_array_test() {
// Used to test migration: FavoriteV1AndWorkspaceArrayMigration
let (cleaner, user_db_path) = unzip_history_user_db(
"./tests/user/migration_test/history_user_db",
"036_fav_v1_workspace_array",
)
.unwrap();
let test =
EventIntegrationTest::new_with_user_data_path(user_db_path, DEFAULT_NAME.to_string()).await;
let views = test.get_all_workspace_views().await;
assert_eq!(views.len(), 2);
assert_eq!(views[0].name, "root page");
assert_eq!(views[1].name, "\u{fe0f} Getting started");
let views = test.get_views(&views[1].id).await;
assert_eq!(views.child_views.len(), 3);
assert!(views.child_views[2].is_favorite);
drop(cleaner);
}

View File

@ -4,7 +4,7 @@ use assert_json_diff::assert_json_eq;
use collab_database::rows::database_row_document_id_from_row_id;
use collab_document::blocks::DocumentData;
use collab_entity::CollabType;
use collab_folder::core::FolderData;
use collab_folder::FolderData;
use nanoid::nanoid;
use serde_json::json;
@ -303,21 +303,12 @@ async fn migrate_anon_data_on_cloud_signup() {
let folder_data: FolderData = test
.folder_manager
.get_cloud_service()
.get_folder_data(&user_profile.workspace_id)
.get_folder_data(&user_profile.workspace_id, &user_profile.id)
.await
.unwrap()
.unwrap();
let expected_folder_data = expected_workspace_sync_folder_data();
if folder_data.workspaces.len() != expected_folder_data.workspaces.len() {
dbg!(&folder_data.workspaces);
}
assert_eq!(
folder_data.workspaces.len(),
expected_folder_data.workspaces.len()
);
assert_eq!(folder_data.views.len(), expected_folder_data.views.len());
// After migration, the ids of the folder_data should be different from the expected_folder_data
@ -329,10 +320,7 @@ async fn migrate_anon_data_on_cloud_signup() {
assert_eq!(left_view.name, right_view.name);
}
assert_ne!(
folder_data.current_workspace_id,
expected_folder_data.current_workspace_id
);
assert_ne!(folder_data.workspace.id, expected_folder_data.workspace.id);
assert_ne!(folder_data.current_view, expected_folder_data.current_view);
let database_views = folder_data

View File

@ -2,7 +2,7 @@ use std::collections::HashMap;
use event_integration::{event_builder::EventBuilder, EventIntegrationTest};
use flowy_folder2::entities::WorkspaceSettingPB;
use flowy_folder2::event_map::FolderEvent::GetCurrentWorkspace;
use flowy_folder2::event_map::FolderEvent::GetCurrentWorkspaceSetting;
use flowy_server::supabase::define::{USER_EMAIL, USER_UUID};
use flowy_user::entities::{AuthTypePB, OauthSignInPB, UserProfilePB};
use flowy_user::event_map::UserEvent::*;
@ -32,7 +32,7 @@ async fn initial_workspace_test() {
.parse::<UserProfilePB>();
let workspace_settings = EventBuilder::new(test.clone())
.event(GetCurrentWorkspace)
.event(GetCurrentWorkspaceSetting)
.async_send()
.await
.parse::<WorkspaceSettingPB>();

View File

@ -6,7 +6,7 @@ use std::sync::Arc;
use std::time::Duration;
use anyhow::Error;
use collab_folder::core::FolderData;
use collab_folder::FolderData;
use collab_plugins::cloud_storage::RemoteCollabStorage;
use nanoid::nanoid;
use tokio::sync::mpsc::Receiver;
@ -135,11 +135,12 @@ pub fn encryption_collab_service(
}
pub async fn get_folder_data_from_server(
uid: &i64,
folder_id: &str,
encryption_secret: Option<String>,
) -> Result<Option<FolderData>, Error> {
let (cloud_service, _encryption) = encryption_folder_service(encryption_secret);
cloud_service.get_folder_data(folder_id).await
cloud_service.get_folder_data(folder_id, uid).await
}
pub async fn get_folder_snapshots(

View File

@ -140,13 +140,18 @@ impl FolderCloudService for ServerProvider {
FutureResult::new(async move { server?.folder_service().create_workspace(uid, &name).await })
}
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error> {
fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
let uid = *uid;
let server = self.get_server(&self.get_server_type());
let workspace_id = workspace_id.to_string();
FutureResult::new(async move {
server?
.folder_service()
.get_folder_data(&workspace_id)
.get_folder_data(&workspace_id, &uid)
.await
})
}

View File

@ -256,6 +256,9 @@ pub enum ErrorCode {
#[error("Internal server error")]
InternalServerError = 84,
#[error("Not support yet")]
NotSupportYet = 85,
}
impl ErrorCode {

View File

@ -101,6 +101,7 @@ impl FlowyError {
);
static_flowy_error!(collab_not_sync, ErrorCode::CollabDataNotSync);
static_flowy_error!(server_error, ErrorCode::InternalServerError);
static_flowy_error!(not_support, ErrorCode::NotSupportYet);
}
impl std::convert::From<ErrorCode> for FlowyError {

View File

@ -1,5 +1,5 @@
pub use anyhow::Error;
pub use collab_folder::core::{Folder, FolderData, Workspace};
pub use collab_folder::{Folder, FolderData, Workspace};
use uuid::Uuid;
use lib_infra::future::FutureResult;
@ -8,7 +8,11 @@ use lib_infra::future::FutureResult;
pub trait FolderCloudService: Send + Sync + 'static {
fn create_workspace(&self, uid: i64, name: &str) -> FutureResult<Workspace, Error>;
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error>;
fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error>;
fn get_folder_snapshots(
&self,

View File

@ -1,5 +1,5 @@
use crate::entities::parser::view::ViewIdentify;
use collab_folder::core::{IconType, ViewIcon};
use collab_folder::{IconType, ViewIcon};
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode;

View File

@ -1,4 +1,4 @@
use collab_folder::core::TrashInfo;
use collab_folder::TrashInfo;
use flowy_derive::ProtoBuf;
#[derive(Eq, PartialEq, ProtoBuf, Default, Debug, Clone)]

View File

@ -3,7 +3,7 @@ use std::convert::TryInto;
use std::ops::{Deref, DerefMut};
use std::sync::Arc;
use collab_folder::core::{View, ViewLayout};
use collab_folder::{View, ViewLayout};
use flowy_derive::{ProtoBuf, ProtoBuf_Enum};
use flowy_error::ErrorCode;

View File

@ -1,7 +1,7 @@
use std::convert::TryInto;
use collab::core::collab_state::SyncState;
use collab_folder::core::Workspace;
use collab_folder::Workspace;
use flowy_derive::ProtoBuf;
use flowy_error::ErrorCode;
@ -38,16 +38,16 @@ impl std::convert::From<(Workspace, Vec<ViewPB>)> for WorkspacePB {
}
}
impl std::convert::From<Workspace> for WorkspacePB {
fn from(workspace: Workspace) -> Self {
WorkspacePB {
id: workspace.id,
name: workspace.name,
views: Default::default(),
create_time: workspace.created_at,
}
}
}
// impl std::convert::From<Workspace> for WorkspacePB {
// fn from(workspace: Workspace) -> Self {
// WorkspacePB {
// id: workspace.id,
// name: workspace.name,
// views: Default::default(),
// create_time: workspace.created_at,
// }
// }
// }
#[derive(PartialEq, Eq, Debug, Default, ProtoBuf)]
pub struct RepeatedWorkspacePB {
@ -55,14 +55,9 @@ pub struct RepeatedWorkspacePB {
pub items: Vec<WorkspacePB>,
}
impl From<Vec<Workspace>> for RepeatedWorkspacePB {
fn from(workspaces: Vec<Workspace>) -> Self {
Self {
items: workspaces
.into_iter()
.map(|workspace| workspace.into())
.collect::<Vec<WorkspacePB>>(),
}
impl From<Vec<WorkspacePB>> for RepeatedWorkspacePB {
fn from(workspaces: Vec<WorkspacePB>) -> Self {
Self { items: workspaces }
}
}
@ -98,22 +93,14 @@ impl TryInto<CreateWorkspaceParams> for CreateWorkspacePayloadPB {
// Read all workspaces if the workspace_id is None
#[derive(Clone, ProtoBuf, Default, Debug)]
pub struct WorkspaceIdPB {
#[pb(index = 1, one_of)]
pub value: Option<String>,
}
impl WorkspaceIdPB {
pub fn new(workspace_id: Option<String>) -> Self {
Self {
value: workspace_id,
}
}
#[pb(index = 1)]
pub value: String,
}
#[derive(Default, ProtoBuf, Debug, Clone)]
pub struct WorkspaceSettingPB {
#[pb(index = 1)]
pub workspace: WorkspacePB,
pub workspace_id: String,
#[pb(index = 2, one_of)]
pub latest_view: Option<ViewPB>,

View File

@ -24,7 +24,18 @@ pub(crate) async fn create_workspace_handler(
let folder = upgrade_folder(folder)?;
let params: CreateWorkspaceParams = data.into_inner().try_into()?;
let workspace = folder.create_workspace(params).await?;
data_result_ok(workspace.into())
let views = folder
.get_views_belong_to(&workspace.id)
.await?
.into_iter()
.map(view_pb_without_child_views)
.collect::<Vec<ViewPB>>();
data_result_ok(WorkspacePB {
id: workspace.id,
name: workspace.name,
views,
create_time: workspace.created_at,
})
}
#[tracing::instrument(level = "debug", skip(folder), err)]
@ -43,52 +54,39 @@ pub(crate) async fn open_workspace_handler(
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<WorkspacePB, FlowyError> {
let folder = upgrade_folder(folder)?;
let params: WorkspaceIdPB = data.into_inner();
match params.value {
None => Err(FlowyError::workspace_id().with_context("workspace id should not be empty")),
Some(workspace_id) => {
if workspace_id.is_empty() {
Err(FlowyError::workspace_id().with_context("workspace id should not be empty"))
} else {
let workspace = folder.open_workspace(&workspace_id).await?;
let views = folder.get_workspace_views(&workspace_id).await?;
let workspace_pb: WorkspacePB = (workspace, views).into();
data_result_ok(workspace_pb)
}
},
let workspace_id = data.into_inner().value;
if workspace_id.is_empty() {
Err(FlowyError::workspace_id().with_context("workspace id should not be empty"))
} else {
let workspace = folder.open_workspace(&workspace_id).await?;
let views = folder.get_workspace_views(&workspace_id).await?;
let workspace_pb: WorkspacePB = (workspace, views).into();
data_result_ok(workspace_pb)
}
}
#[tracing::instrument(level = "debug", skip(data, folder), err)]
pub(crate) async fn read_workspaces_handler(
data: AFPluginData<WorkspaceIdPB>,
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<RepeatedWorkspacePB, FlowyError> {
let folder = upgrade_folder(folder)?;
let params: WorkspaceIdPB = data.into_inner();
let workspaces = match params.value {
None => folder.get_all_workspaces().await,
Some(workspace_id) => folder
.get_workspace(&workspace_id)
.await
.map(|workspace| vec![workspace])
.unwrap_or_default(),
};
data_result_ok(workspaces.into())
}
#[tracing::instrument(level = "debug", skip(folder), err)]
pub async fn get_current_workspace_setting_handler(
pub(crate) async fn read_current_workspace_setting_handler(
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<WorkspaceSettingPB, FlowyError> {
let folder = upgrade_folder(folder)?;
let workspace = folder.get_current_workspace().await?;
let latest_view: Option<ViewPB> = folder.get_current_view().await;
data_result_ok(WorkspaceSettingPB {
workspace,
latest_view,
})
let setting = folder
.get_workspace_setting_pb()
.await
.ok_or(FlowyError::record_not_found())?;
data_result_ok(setting)
}
#[tracing::instrument(level = "debug", skip(folder), err)]
pub(crate) async fn read_current_workspace_handler(
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<WorkspacePB, FlowyError> {
let folder = upgrade_folder(folder)?;
let workspace = folder
.get_workspace_pb()
.await
.ok_or(FlowyError::record_not_found())?;
data_result_ok(workspace)
}
pub(crate) async fn create_view_handler(
@ -125,7 +123,7 @@ pub(crate) async fn read_view_handler(
) -> DataResult<ViewPB, FlowyError> {
let folder = upgrade_folder(folder)?;
let view_id: ViewIdPB = data.into_inner();
let view_pb = folder.get_view(&view_id.value).await?;
let view_pb = folder.get_view_pb(&view_id.value).await?;
data_result_ok(view_pb)
}
@ -239,17 +237,10 @@ pub(crate) async fn read_favorites_handler(
let favorites = folder.get_all_favorites().await;
let mut views = vec![];
for info in favorites {
let view = folder.get_view(&info.id).await;
match view {
Ok(view) => {
views.push(view);
},
Err(err) => {
return Err(err);
},
if let Ok(view) = folder.get_view_pb(&info.id).await {
views.push(view);
}
}
data_result_ok(RepeatedViewPB { items: views })
}
#[tracing::instrument(level = "debug", skip(folder), err)]
@ -319,10 +310,7 @@ pub(crate) async fn get_folder_snapshots_handler(
folder: AFPluginState<Weak<FolderManager>>,
) -> DataResult<RepeatedFolderSnapshotPB, FlowyError> {
let folder = upgrade_folder(folder)?;
if let Some(workspace_id) = &data.value {
let snapshots = folder.get_folder_snapshots(workspace_id, 10).await?;
data_result_ok(RepeatedFolderSnapshotPB { items: snapshots })
} else {
data_result_ok(RepeatedFolderSnapshotPB { items: vec![] })
}
let data = data.into_inner();
let snapshots = folder.get_folder_snapshots(&data.value, 10).await?;
data_result_ok(RepeatedFolderSnapshotPB { items: snapshots })
}

View File

@ -12,11 +12,8 @@ pub fn init(folder: Weak<FolderManager>) -> AFPlugin {
AFPlugin::new().name("Flowy-Folder").state(folder)
// Workspace
.event(FolderEvent::CreateWorkspace, create_workspace_handler)
.event(
FolderEvent::GetCurrentWorkspace,
get_current_workspace_setting_handler,
)
.event(FolderEvent::ReadAllWorkspaces, read_workspaces_handler)
.event(FolderEvent::GetCurrentWorkspaceSetting, read_current_workspace_setting_handler)
.event(FolderEvent::ReadCurrentWorkspace, read_current_workspace_handler)
.event(FolderEvent::OpenWorkspace, open_workspace_handler)
.event(FolderEvent::ReadWorkspaceViews, get_workspace_views_handler)
// View
@ -52,11 +49,11 @@ pub enum FolderEvent {
/// Read the current opening workspace. Currently, we only support one workspace
#[event(output = "WorkspaceSettingPB")]
GetCurrentWorkspace = 1,
GetCurrentWorkspaceSetting = 1,
/// Return a list of workspaces that the current user can access.
#[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")]
ReadAllWorkspaces = 2,
#[event(output = "WorkspacePB")]
ReadCurrentWorkspace = 2,
/// Delete the workspace
#[event(input = "WorkspaceIdPB")]

View File

@ -1,4 +1,4 @@
pub use collab_folder::core::ViewLayout;
pub use collab_folder::ViewLayout;
pub mod entities;
pub mod event_handler;

View File

@ -5,9 +5,9 @@ use std::sync::{Arc, Weak};
use collab::core::collab::{CollabRawData, MutexCollab};
use collab::core::collab_state::SyncState;
use collab_entity::CollabType;
use collab_folder::core::{
FavoritesInfo, Folder, FolderData, FolderNotify, TrashChange, TrashChangeReceiver, TrashInfo,
View, ViewChange, ViewChangeReceiver, ViewLayout, ViewUpdate, Workspace,
use collab_folder::{
FavoriteId, Folder, FolderData, FolderNotify, TrashChange, TrashChangeReceiver, TrashInfo,
UserId, View, ViewChange, ViewChangeReceiver, ViewLayout, ViewUpdate, Workspace,
};
use parking_lot::{Mutex, RwLock};
use tokio_stream::wrappers::WatchStream;
@ -24,12 +24,11 @@ use crate::entities::icon::UpdateViewIconParams;
use crate::entities::{
view_pb_with_child_views, view_pb_without_child_views, ChildViewUpdatePB, CreateViewParams,
CreateWorkspaceParams, DeletedViewPB, FolderSnapshotPB, FolderSnapshotStatePB, FolderSyncStatePB,
RepeatedTrashPB, RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, UserFolderPB, ViewPB,
WorkspacePB,
RepeatedTrashPB, RepeatedViewPB, UpdateViewParams, UserFolderPB, ViewPB, WorkspacePB,
WorkspaceSettingPB,
};
use crate::notification::{
send_notification, send_workspace_notification, send_workspace_setting_notification,
FolderNotification,
send_notification, send_workspace_setting_notification, FolderNotification,
};
use crate::share::ImportParams;
use crate::user_default::DefaultFolderBuilder;
@ -74,6 +73,7 @@ impl FolderManager {
Ok(manager)
}
#[instrument(level = "debug", skip(self), err)]
pub async fn get_current_workspace(&self) -> FlowyResult<WorkspacePB> {
self.with_folder(
|| {
@ -92,19 +92,7 @@ impl FolderManager {
};
match folder.get_current_workspace() {
None => {
// The current workspace should always exist. If not, try to find the first workspace.
// from the folder. Otherwise, return an error.
let mut workspaces = folder.workspaces.get_all_workspaces();
if workspaces.is_empty() {
Err(FlowyError::record_not_found().with_context("Can not find the workspace"))
} else {
tracing::error!("Can't find the current workspace, use the first workspace");
let workspace = workspaces.remove(0);
folder.set_current_workspace(&workspace.id);
workspace_pb_from_workspace(workspace, folder)
}
},
None => Err(FlowyError::record_not_found().with_context("Can not find the workspace")),
Some(workspace) => workspace_pb_from_workspace(workspace, folder),
}
},
@ -118,9 +106,9 @@ impl FolderManager {
.mutex_folder
.lock()
.as_ref()
.map(|folder| folder.get_current_workspace_id());
.map(|folder| folder.get_workspace_id());
if let Some(Some(workspace_id)) = workspace_id {
if let Some(workspace_id) = workspace_id {
self.get_workspace_views(&workspace_id).await
} else {
tracing::warn!("Can't get current workspace views");
@ -129,7 +117,7 @@ impl FolderManager {
}
pub async fn get_workspace_views(&self, workspace_id: &str) -> FlowyResult<Vec<ViewPB>> {
let views = self.with_folder(std::vec::Vec::new, |folder| {
let views = self.with_folder(Vec::new, |folder| {
get_workspace_view_pbs(workspace_id, folder)
});
@ -160,18 +148,25 @@ impl FolderManager {
} => {
let is_exist = is_exist_in_local_disk(&self.user, &workspace_id).unwrap_or(false);
if is_exist {
event!(Level::INFO, "Restore folder from local disk");
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, vec![])
.await?;
Folder::open(collab, Some(folder_notifier))
Folder::open(UserId::from(uid), collab, Some(folder_notifier))?
} else if create_if_not_exist {
event!(Level::INFO, "Create folder with default folder builder");
let folder_data =
DefaultFolderBuilder::build(uid, workspace_id.to_string(), &self.operation_handlers)
.await;
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, vec![])
.await?;
Folder::create(collab, Some(folder_notifier), Some(folder_data))
Folder::create(
UserId::from(uid),
collab,
Some(folder_notifier),
folder_data,
)
} else {
return Err(FlowyError::new(
ErrorCode::RecordNotFound,
@ -180,19 +175,26 @@ impl FolderManager {
}
},
FolderInitializeDataSource::Cloud(raw_data) => {
event!(Level::INFO, "Restore folder from cloud service");
if raw_data.is_empty() {
return Err(workspace_data_not_sync_error(uid, &workspace_id));
}
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, raw_data)
.await?;
Folder::open(collab, Some(folder_notifier))
Folder::open(UserId::from(uid), collab, Some(folder_notifier))?
},
FolderInitializeDataSource::FolderData(folder_data) => {
event!(Level::INFO, "Restore folder with passed-in folder data");
let collab = self
.collab_for_folder(uid, &workspace_id, collab_db, vec![])
.await?;
Folder::create(collab, Some(folder_notifier), Some(folder_data))
Folder::create(
UserId::from(uid),
collab,
Some(folder_notifier),
folder_data,
)
},
};
@ -325,49 +327,58 @@ impl FolderManager {
pub async fn clear(&self, _user_id: i64) {}
#[tracing::instrument(level = "info", skip_all, err)]
pub async fn create_workspace(&self, params: CreateWorkspaceParams) -> FlowyResult<Workspace> {
let workspace = self
.cloud_service
.create_workspace(self.user.user_id()?, &params.name)
.await?;
self.with_folder(
|| (),
|folder| {
folder.workspaces.create_workspace(workspace.clone());
folder.set_current_workspace(&workspace.id);
},
);
let repeated_workspace = RepeatedWorkspacePB {
items: vec![workspace.clone().into()],
};
send_workspace_notification(FolderNotification::DidCreateWorkspace, repeated_workspace);
Ok(workspace)
pub async fn create_workspace(&self, _params: CreateWorkspaceParams) -> FlowyResult<Workspace> {
Err(FlowyError::not_support())
}
#[tracing::instrument(level = "info", skip_all, err)]
pub async fn open_workspace(&self, workspace_id: &str) -> FlowyResult<Workspace> {
pub async fn open_workspace(&self, _workspace_id: &str) -> FlowyResult<Workspace> {
self.with_folder(
|| Err(FlowyError::internal()),
|folder| {
let workspace = folder
.workspaces
.get_workspace(workspace_id)
.ok_or_else(|| {
FlowyError::record_not_found().with_context("Can't open not existing workspace")
})?;
folder.set_current_workspace(&workspace.id);
let workspace = folder.get_current_workspace().ok_or_else(|| {
FlowyError::record_not_found().with_context("Can't open not existing workspace")
})?;
Ok::<Workspace, FlowyError>(workspace)
},
)
}
pub async fn get_workspace(&self, workspace_id: &str) -> Option<Workspace> {
self.with_folder(
|| None,
|folder| folder.workspaces.get_workspace(workspace_id),
)
pub async fn get_workspace(&self, _workspace_id: &str) -> Option<Workspace> {
self.with_folder(|| None, |folder| folder.get_current_workspace())
}
pub async fn get_workspace_setting_pb(&self) -> Option<WorkspaceSettingPB> {
let workspace_id = self.get_current_workspace_id().await.ok()?;
let latest_view = self.get_current_view().await;
Some(WorkspaceSettingPB {
workspace_id,
latest_view,
})
}
pub async fn get_workspace_pb(&self) -> Option<WorkspacePB> {
let workspace_pb = {
let guard = self.mutex_folder.lock();
let folder = guard.as_ref()?;
let workspace = folder.get_current_workspace()?;
let views = folder
.views
.get_views_belong_to(&workspace.id)
.into_iter()
.map(view_pb_without_child_views)
.collect::<Vec<ViewPB>>();
WorkspacePB {
id: workspace.id,
name: workspace.name,
views,
create_time: workspace.created_at,
}
};
Some(workspace_pb)
}
async fn get_current_workspace_id(&self) -> FlowyResult<String> {
@ -375,7 +386,7 @@ impl FolderManager {
.mutex_folder
.lock()
.as_ref()
.and_then(|folder| folder.get_current_workspace_id())
.map(|folder| folder.get_workspace_id())
.ok_or(FlowyError::internal().with_context("Unexpected empty workspace id"))
}
@ -399,8 +410,12 @@ impl FolderManager {
}
pub async fn get_all_workspaces(&self) -> Vec<Workspace> {
self.with_folder(std::vec::Vec::new, |folder| {
folder.workspaces.get_all_workspaces()
self.with_folder(Vec::new, |folder| {
let mut workspaces = vec![];
if let Some(workspace) = folder.get_current_workspace() {
workspaces.push(workspace);
}
workspaces
})
}
@ -478,7 +493,7 @@ impl FolderManager {
/// The child views of the view will only access the first. So if you want to get the child view's
/// child view, you need to call this method again.
#[tracing::instrument(level = "debug", skip(self, view_id), err)]
pub async fn get_view(&self, view_id: &str) -> FlowyResult<ViewPB> {
pub async fn get_view_pb(&self, view_id: &str) -> FlowyResult<ViewPB> {
let view_id = view_id.to_string();
let folder = self.mutex_folder.lock();
let folder = folder.as_ref().ok_or_else(folder_not_init_error)?;
@ -586,7 +601,7 @@ impl FolderManager {
new_parent_id: String,
prev_view_id: Option<String>,
) -> FlowyResult<()> {
let view = self.get_view(&view_id).await?;
let view = self.get_view_pb(&view_id).await?;
let old_parent_id = view.parent_view_id;
self.with_folder(
|| (),
@ -620,7 +635,7 @@ impl FolderManager {
.collect::<Vec<_>>()
} else {
self
.get_view(&parent_view_id)
.get_view_pb(&parent_view_id)
.await?
.child_views
.into_iter()
@ -653,7 +668,7 @@ impl FolderManager {
/// Return a list of views that belong to the given parent view id.
#[tracing::instrument(level = "debug", skip(self, parent_view_id), err)]
pub async fn get_views_belong_to(&self, parent_view_id: &str) -> FlowyResult<Vec<Arc<View>>> {
let views = self.with_folder(std::vec::Vec::new, |folder| {
let views = self.with_folder(Vec::new, |folder| {
folder.views.get_views_belong_to(parent_view_id)
});
Ok(views)
@ -722,22 +737,22 @@ impl FolderManager {
#[tracing::instrument(level = "trace", skip(self), err)]
pub(crate) async fn set_current_view(&self, view_id: &str) -> Result<(), FlowyError> {
let folder = self.mutex_folder.lock();
let folder = folder.as_ref().ok_or_else(folder_not_init_error)?;
folder.set_current_view(view_id);
let workspace_id = self.with_folder(
|| Err(FlowyError::record_not_found()),
|folder| {
folder.set_current_view(view_id);
Ok(folder.get_workspace_id())
},
)?;
let workspace = folder.get_current_workspace();
let view = folder
.get_current_view()
.and_then(|view_id| folder.views.get_view(&view_id));
send_workspace_setting_notification(workspace, view);
send_workspace_setting_notification(workspace_id, self.get_current_view().await);
Ok(())
}
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn get_current_view(&self) -> Option<ViewPB> {
let view_id = self.with_folder(|| None, |folder| folder.get_current_view())?;
self.get_view(&view_id).await.ok()
self.get_view_pb(&view_id).await.ok()
}
/// Toggles the favorite status of a view identified by `view_id`If the view is not a favorite, it will be added to the favorites list; otherwise, it will be removed from the list.
@ -761,7 +776,7 @@ impl FolderManager {
// Used by toggle_favorites to send notification to frontend, after the favorite status of view has been changed.It sends two distinct notifications: one to correctly update the concerned view's is_favorite status, and another to update the list of favorites that is to be displayed.
async fn send_toggle_favorite_notification(&self, view_id: &str) {
if let Ok(view) = self.get_view(view_id).await {
if let Ok(view) = self.get_view_pb(view_id).await {
let notification_type = if view.is_favorite {
FolderNotification::DidFavoriteView
} else {
@ -780,8 +795,8 @@ impl FolderManager {
}
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn get_all_favorites(&self) -> Vec<FavoritesInfo> {
self.with_folder(std::vec::Vec::new, |folder| {
pub(crate) async fn get_all_favorites(&self) -> Vec<FavoriteId> {
self.with_folder(Vec::new, |folder| {
let trash_ids = folder
.get_all_trash()
.into_iter()
@ -796,7 +811,7 @@ impl FolderManager {
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn get_all_trash(&self) -> Vec<TrashInfo> {
self.with_folder(std::vec::Vec::new, |folder| folder.get_all_trash())
self.with_folder(Vec::new, |folder| folder.get_all_trash())
}
#[tracing::instrument(level = "trace", skip(self))]
@ -825,7 +840,7 @@ impl FolderManager {
/// Delete all the trash permanently.
#[tracing::instrument(level = "trace", skip(self))]
pub(crate) async fn delete_all_trash(&self) {
let deleted_trash = self.with_folder(std::vec::Vec::new, |folder| folder.get_all_trash());
let deleted_trash = self.with_folder(Vec::new, |folder| folder.get_all_trash());
for trash in deleted_trash {
let _ = self.delete_trash(&trash.id).await;
}
@ -928,7 +943,7 @@ impl FolderManager {
}
}
if let Ok(view_pb) = self.get_view(view_id).await {
if let Ok(view_pb) = self.get_view_pb(view_id).await {
send_notification(&view_pb.id, FolderNotification::DidUpdateView)
.payload(view_pb)
.send();
@ -1179,7 +1194,7 @@ fn notify_parent_view_did_change<T: AsRef<str>>(
) -> Option<()> {
let folder = folder.lock();
let folder = folder.as_ref()?;
let workspace_id = folder.get_current_workspace_id()?;
let workspace_id = folder.get_workspace_id();
let trash_ids = folder
.get_all_trash()
.into_iter()

View File

@ -1,12 +1,8 @@
use std::sync::Arc;
use collab_folder::core::{View, Workspace};
use flowy_derive::ProtoBuf_Enum;
use flowy_notification::NotificationBuilder;
use lib_dispatch::prelude::ToBytes;
use crate::entities::{view_pb_without_child_views, WorkspacePB, WorkspaceSettingPB};
use crate::entities::{ViewPB, WorkspaceSettingPB};
const FOLDER_OBSERVABLE_SOURCE: &str = "Workspace";
@ -82,13 +78,11 @@ pub(crate) fn send_workspace_notification<T: ToBytes>(ty: FolderNotification, pa
}
pub(crate) fn send_workspace_setting_notification(
current_workspace: Option<Workspace>,
current_view: Option<Arc<View>>,
workspace_id: String,
latest_view: Option<ViewPB>,
) -> Option<()> {
let workspace: WorkspacePB = current_workspace?.into();
let latest_view = current_view.map(view_pb_without_child_views);
let setting = WorkspaceSettingPB {
workspace,
workspace_id,
latest_view,
};
send_workspace_notification(FolderNotification::DidUpdateWorkspaceSetting, setting);

View File

@ -1,4 +1,4 @@
use collab_folder::core::ViewLayout;
use collab_folder::ViewLayout;
#[derive(Clone, Debug)]
pub enum ImportType {

View File

@ -1,6 +1,6 @@
use std::sync::Arc;
use collab_folder::core::{FolderData, RepeatedViewIdentifier, ViewIdentifier, Workspace};
use collab_folder::{FolderData, RepeatedViewIdentifier, ViewIdentifier, Workspace};
use tokio::sync::RwLock;
use lib_infra::util::timestamp;
@ -44,10 +44,10 @@ impl DefaultFolderBuilder {
};
FolderData {
current_workspace_id: workspace.id.clone(),
workspace,
current_view: first_view.id,
workspaces: vec![workspace],
views: FlattedViews::flatten_views(views),
favorites: Default::default(),
}
}
}

View File

@ -3,8 +3,8 @@ use std::future::Future;
use std::sync::Arc;
use bytes::Bytes;
pub use collab_folder::core::View;
use collab_folder::core::{RepeatedViewIdentifier, ViewIcon, ViewIdentifier, ViewLayout};
pub use collab_folder::View;
use collab_folder::{RepeatedViewIdentifier, ViewIcon, ViewIdentifier, ViewLayout};
use tokio::sync::RwLock;
use flowy_error::FlowyError;

View File

@ -1,4 +1,4 @@
use anyhow::Error;
use anyhow::{anyhow, Error};
use client_api::entity::QueryCollabParams;
use collab::core::origin::CollabOrigin;
use collab_entity::CollabType;
@ -16,10 +16,15 @@ where
T: AFServer,
{
fn create_workspace(&self, _uid: i64, _name: &str) -> FutureResult<Workspace, Error> {
FutureResult::new(async move { todo!() })
FutureResult::new(async move { Err(anyhow!("Not support yet")) })
}
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error> {
fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
let uid = *uid;
let workspace_id = workspace_id.to_string();
let try_get_client = self.0.try_get_client();
FutureResult::new(async move {
@ -33,7 +38,7 @@ where
.await
.map_err(FlowyError::from)?];
let folder =
Folder::from_collab_raw_data(CollabOrigin::Empty, updates, &workspace_id, vec![])?;
Folder::from_collab_raw_data(uid, CollabOrigin::Empty, updates, &workspace_id, vec![])?;
Ok(folder.get_folder_data())
})
}

View File

@ -27,7 +27,11 @@ impl FolderCloudService for LocalServerFolderCloudServiceImpl {
})
}
fn get_folder_data(&self, _workspace_id: &str) -> FutureResult<Option<FolderData>, Error> {
fn get_folder_data(
&self,
_workspace_id: &str,
_uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
FutureResult::new(async move { Ok(None) })
}

View File

@ -69,7 +69,12 @@ where
})
}
fn get_folder_data(&self, workspace_id: &str) -> FutureResult<Option<FolderData>, Error> {
fn get_folder_data(
&self,
workspace_id: &str,
uid: &i64,
) -> FutureResult<Option<FolderData>, Error> {
let uid = *uid;
let try_get_postgrest = self.server.try_get_postgrest();
let workspace_id = workspace_id.to_string();
FutureResult::new(async move {
@ -85,7 +90,7 @@ where
}
let folder =
Folder::from_collab_raw_data(CollabOrigin::Empty, updates, &workspace_id, vec![])?;
Folder::from_collab_raw_data(uid, CollabOrigin::Empty, updates, &workspace_id, vec![])?;
Ok(folder.get_folder_data())
})
}

View File

@ -17,14 +17,13 @@ use tokio_retry::{Action, RetryIf};
use uuid::Uuid;
use flowy_error::FlowyError;
use flowy_folder_deps::cloud::{Folder, Workspace};
use flowy_folder_deps::cloud::{Folder, FolderData, Workspace};
use flowy_user_deps::cloud::*;
use flowy_user_deps::entities::*;
use flowy_user_deps::DEFAULT_USER_NAME;
use lib_dispatch::prelude::af_spawn;
use lib_infra::box_any::BoxAny;
use lib_infra::future::FutureResult;
use lib_infra::util::timestamp;
use crate::response::ExtendedResponse;
use crate::supabase::api::request::{
@ -609,15 +608,9 @@ fn empty_workspace_update(collab_object: &CollabObject) -> Vec<u8> {
&collab_object.object_id,
vec![],
));
let folder = Folder::create(collab.clone(), None, None);
folder.workspaces.create_workspace(Workspace {
id: workspace_id.clone(),
name: "My workspace".to_string(),
child_views: Default::default(),
created_at: timestamp(),
});
folder.set_current_workspace(&workspace_id);
collab.encode_as_update_v1().0
let workspace = Workspace::new(workspace_id, "My workspace".to_string());
let folder = Folder::create(collab_object.uid, collab, None, FolderData::new(workspace));
folder.encode_as_update_v1().0
}
fn oauth_params_from_box_any(any: BoxAny) -> Result<SupabaseOAuthParams, Error> {

View File

@ -96,15 +96,23 @@ pub fn encryption_collab_service(
}
#[allow(dead_code)]
pub async fn print_encryption_folder(folder_id: &str, encryption_secret: Option<String>) {
pub async fn print_encryption_folder(
uid: &i64,
folder_id: &str,
encryption_secret: Option<String>,
) {
let (cloud_service, _encryption) = encryption_folder_service(encryption_secret);
let folder_data = cloud_service.get_folder_data(folder_id).await.unwrap();
let folder_data = cloud_service.get_folder_data(folder_id, uid).await.unwrap();
let json = serde_json::to_value(folder_data).unwrap();
println!("{}", serde_json::to_string_pretty(&json).unwrap());
}
#[allow(dead_code)]
pub async fn print_encryption_folder_snapshot(folder_id: &str, encryption_secret: Option<String>) {
pub async fn print_encryption_folder_snapshot(
uid: &i64,
folder_id: &str,
encryption_secret: Option<String>,
) {
let (cloud_service, _encryption) = encryption_collab_service(encryption_secret);
let snapshot = cloud_service
.get_snapshots(folder_id, 1)
@ -115,7 +123,10 @@ pub async fn print_encryption_folder_snapshot(folder_id: &str, encryption_secret
MutexCollab::new_with_raw_data(CollabOrigin::Empty, folder_id, vec![snapshot.blob], vec![])
.unwrap(),
);
let folder_data = Folder::open(collab, None).get_folder_data().unwrap();
let folder_data = Folder::open(uid, collab, None)
.unwrap()
.get_folder_data()
.unwrap();
let json = serde_json::to_value(folder_data).unwrap();
println!("{}", serde_json::to_string_pretty(&json).unwrap());
}

View File

@ -11,7 +11,7 @@ use collab_database::database::{
};
use collab_database::rows::{database_row_document_id_from_row_id, mut_row_with_collab, RowId};
use collab_database::user::DatabaseWithViewsArray;
use collab_folder::core::Folder;
use collab_folder::{Folder, UserId};
use parking_lot::{Mutex, RwLock};
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
@ -22,7 +22,7 @@ use crate::migrations::MigrationUser;
/// Migration the collab objects of the old user to new user. Currently, it only happens when
/// the user is a local user and try to use AppFlowy cloud service.
pub fn migration_local_user_on_sign_up(
pub fn migration_anon_user_on_sign_up(
old_user: &MigrationUser,
old_collab_db: &Arc<RocksCollabDB>,
new_user: &MigrationUser,
@ -207,7 +207,13 @@ where
old_folder_collab.with_origin_transact_mut(|txn| {
old_collab_r_txn.load_doc_with_txn(old_uid, old_workspace_id, txn)
})?;
let old_folder = Folder::open(Arc::new(MutexCollab::from_collab(old_folder_collab)), None);
let oid_user_id = UserId::from(old_uid);
let old_folder = Folder::open(
oid_user_id,
Arc::new(MutexCollab::from_collab(old_folder_collab)),
None,
)
.map_err(|err| PersistenceError::InvalidData(err.to_string()))?;
let mut folder_data = old_folder
.get_folder_data()
.ok_or(PersistenceError::Internal(
@ -219,25 +225,13 @@ where
.insert(old_workspace_id.to_string(), new_workspace_id.to_string());
// 1. Replace the workspace views id to new id
debug_assert!(folder_data.workspaces.len() == 1);
folder_data.workspace.id = new_workspace_id.clone();
folder_data
.workspaces
.workspace
.child_views
.iter_mut()
.enumerate()
.for_each(|(index, workspace)| {
if index == 0 {
workspace.id = new_workspace_id.to_string();
} else {
tracing::warn!("🔴migrate folder: more than one workspace");
workspace.id = old_to_new_id_map.get_new_id(&workspace.id);
}
workspace
.child_views
.iter_mut()
.for_each(|view_identifier| {
view_identifier.id = old_to_new_id_map.get_new_id(&view_identifier.id);
});
.for_each(|view_identifier| {
view_identifier.id = old_to_new_id_map.get_new_id(&view_identifier.id);
});
folder_data.views.iter_mut().for_each(|view| {
@ -253,15 +247,6 @@ where
});
});
match old_to_new_id_map.get(&folder_data.current_workspace_id) {
Some(new_workspace_id) => {
folder_data.current_workspace_id = new_workspace_id.clone();
},
None => {
tracing::error!("🔴migrate folder: current workspace id not found");
},
}
match old_to_new_id_map.get(&folder_data.current_view) {
Some(new_view_id) => {
folder_data.current_view = new_view_id.clone();
@ -276,7 +261,8 @@ where
let new_folder_collab = Collab::new_with_raw_data(origin, new_workspace_id, vec![], vec![])
.map_err(|err| PersistenceError::Internal(Box::new(err)))?;
let mutex_collab = Arc::new(MutexCollab::from_collab(new_folder_collab));
let _ = Folder::create(mutex_collab.clone(), None, Some(folder_data));
let new_user_id = UserId::from(new_uid);
let _ = Folder::create(new_user_id, mutex_collab.clone(), None, folder_data);
{
let mutex_collab = mutex_collab.lock();

View File

@ -0,0 +1,5 @@
pub use anon_user_data::*;
pub use sync_new_user::*;
mod anon_user_data;
mod sync_new_user;

View File

@ -10,7 +10,7 @@ use collab_database::database::get_database_row_ids;
use collab_database::rows::database_row_document_id_from_row_id;
use collab_database::user::{get_database_with_views, DatabaseWithViews};
use collab_entity::{CollabObject, CollabType};
use collab_folder::core::{Folder, View, ViewLayout};
use collab_folder::{Folder, View, ViewLayout};
use parking_lot::Mutex;
use collab_integrate::{PersistenceError, RocksCollabDB, YrsDocAction};
@ -255,9 +255,10 @@ async fn sync_folder(
let update = collab.encode_as_update_v1().0;
(
MutexFolder::new(Folder::open(
uid,
Arc::new(MutexCollab::from_collab(collab)),
None,
)),
)?),
update,
)
};

View File

@ -1,7 +1,7 @@
use std::sync::{Arc, Weak};
use collab_database::database::WatchStream;
use collab_folder::core::FolderData;
use collab_folder::FolderData;
use strum_macros::Display;
use flowy_derive::{Flowy_Event, ProtoBuf_Enum};

View File

@ -1,6 +1,7 @@
#[macro_use]
extern crate flowy_sqlite;
mod anon_user_upgrade;
pub mod entities;
mod event_handler;
pub mod event_map;

View File

@ -19,12 +19,12 @@ use flowy_user_deps::entities::*;
use lib_dispatch::prelude::af_spawn;
use lib_infra::box_any::BoxAny;
use crate::anon_user_upgrade::{migration_anon_user_on_sign_up, sync_user_data_to_cloud};
use crate::entities::{AuthStateChangedPB, AuthStatePB, UserProfilePB, UserSettingPB};
use crate::event_map::{DefaultUserStatusCallback, UserCloudServiceProvider, UserStatusCallback};
use crate::migrations::historical_document::HistoricalEmptyDocumentMigration;
use crate::migrations::migrate_to_new_user::migration_local_user_on_sign_up;
use crate::migrations::migration::UserLocalDataMigration;
use crate::migrations::sync_new_user::sync_user_data_to_cloud;
use crate::migrations::document_empty_content::HistoricalEmptyDocumentMigration;
use crate::migrations::migration::{UserDataMigration, UserLocalDataMigration};
use crate::migrations::workspace_and_favorite_v1::FavoriteV1AndWorkspaceArrayMigration;
use crate::migrations::MigrationUser;
use crate::services::cloud_config::get_cloud_config;
use crate::services::collab_interact::{CollabInteract, DefaultCollabInteract};
@ -165,8 +165,13 @@ impl UserManager {
self.database.get_pool(session.user_id),
) {
(Ok(collab_db), Ok(sqlite_pool)) => {
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool)
.run(vec![Box::new(HistoricalEmptyDocumentMigration)])
// ⚠The order of migrations is crucial. If you're adding a new migration, please ensure
// it's appended to the end of the list.
let migrations: Vec<Box<dyn UserDataMigration>> = vec![
Box::new(HistoricalEmptyDocumentMigration),
Box::new(FavoriteV1AndWorkspaceArrayMigration),
];
match UserLocalDataMigration::new(session.clone(), collab_db, sqlite_pool).run(migrations)
{
Ok(applied_migrations) => {
if !applied_migrations.is_empty() {
@ -358,12 +363,12 @@ impl UserManager {
};
event!(
tracing::Level::INFO,
"Migrate old user data from {:?} to {:?}",
"Migrate anon user data from {:?} to {:?}",
old_user.user_profile.uid,
new_user.user_profile.uid
);
self
.migrate_local_user_to_cloud(&old_user, &new_user)
.migrate_anon_user_to_cloud(&old_user, &new_user)
.await?;
let _ = self.database.close(old_user.session.user_id);
}
@ -689,14 +694,14 @@ impl UserManager {
Ok(())
}
async fn migrate_local_user_to_cloud(
async fn migrate_anon_user_to_cloud(
&self,
old_user: &MigrationUser,
new_user: &MigrationUser,
) -> Result<(), FlowyError> {
let old_collab_db = self.database.get_collab_db(old_user.session.user_id)?;
let new_collab_db = self.database.get_collab_db(new_user.session.user_id)?;
migration_local_user_on_sign_up(old_user, &old_collab_db, new_user, &new_collab_db)?;
migration_anon_user_on_sign_up(old_user, &old_collab_db, new_user, &new_collab_db)?;
if let Err(err) = sync_user_data_to_cloud(
self.cloud_services.get_user_service()?,

View File

@ -4,7 +4,7 @@ use collab::core::collab::MutexCollab;
use collab::core::origin::{CollabClient, CollabOrigin};
use collab_document::document::Document;
use collab_document::document_data::default_document_data;
use collab_folder::core::Folder;
use collab_folder::Folder;
use collab_integrate::{RocksCollabDB, YrsDocAction};
use flowy_error::{internal_error, FlowyResult};
@ -25,8 +25,13 @@ impl UserDataMigration for HistoricalEmptyDocumentMigration {
if let Ok(updates) = write_txn.get_all_updates(session.user_id, &session.user_workspace.id) {
let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom"));
// Deserialize the folder from the raw data
let folder =
Folder::from_collab_raw_data(origin.clone(), updates, &session.user_workspace.id, vec![])?;
let folder = Folder::from_collab_raw_data(
session.user_id,
origin.clone(),
updates,
&session.user_workspace.id,
vec![],
)?;
// Migration the first level documents of the workspace
let migration_views = folder.get_workspace_views(&session.user_workspace.id);

View File

@ -2,6 +2,7 @@ use std::sync::Arc;
use chrono::NaiveDateTime;
use diesel::{RunQueryDsl, SqliteConnection};
use tracing::event;
use collab_integrate::RocksCollabDB;
use flowy_error::FlowyResult;
@ -54,6 +55,12 @@ impl UserLocalDataMigration {
{
let migration_name = migration.name().to_string();
if !duplicated_names.contains(&migration_name) {
event!(
tracing::Level::INFO,
"Running migration {}",
migration.name()
);
migration.run(&self.session, &self.collab_db)?;
applied_migrations.push(migration.name().to_string());
save_record(&conn, &migration_name);

View File

@ -1,7 +1,6 @@
pub use define::*;
mod define;
pub mod historical_document;
pub mod migrate_to_new_user;
pub mod document_empty_content;
pub mod migration;
pub mod sync_new_user;
pub mod workspace_and_favorite_v1;

View File

@ -0,0 +1,55 @@
use std::sync::Arc;
use collab::core::origin::{CollabClient, CollabOrigin};
use collab_folder::Folder;
use collab_integrate::{RocksCollabDB, YrsDocAction};
use flowy_error::{internal_error, FlowyResult};
use crate::migrations::migration::UserDataMigration;
use crate::services::entities::Session;
/// 1. Migrate the workspace: { favorite: [view_id] } to { favorite: { uid: [view_id] } }
/// 2. Migrate { workspaces: [workspace object] } to { views: { workspace object } }. Make each folder
/// only have one workspace.
pub struct FavoriteV1AndWorkspaceArrayMigration;
impl UserDataMigration for FavoriteV1AndWorkspaceArrayMigration {
fn name(&self) -> &str {
"workspace_favorite_v1_and_workspace_array_migration"
}
fn run(&self, session: &Session, collab_db: &Arc<RocksCollabDB>) -> FlowyResult<()> {
let write_txn = collab_db.write_txn();
if let Ok(updates) = write_txn.get_all_updates(session.user_id, &session.user_workspace.id) {
let origin = CollabOrigin::Client(CollabClient::new(session.user_id, "phantom"));
// Deserialize the folder from the raw data
let folder = Folder::from_collab_raw_data(
session.user_id,
origin,
updates,
&session.user_workspace.id,
vec![],
)?;
folder.migrate_workspace_to_view();
let favorite_view_ids = folder
.get_favorite_v1()
.into_iter()
.map(|fav| fav.id)
.collect::<Vec<String>>();
if !favorite_view_ids.is_empty() {
folder.add_favorites(favorite_view_ids);
}
let (doc_state, sv) = folder.encode_as_update_v1();
write_txn
.flush_doc_with(session.user_id, &session.user_workspace.id, &doc_state, &sv)
.map_err(internal_error)?;
write_txn.commit_transaction().map_err(internal_error)?;
}
Ok(())
}
}