mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
fix: create document (#2701)
* fix: create a new document * fix: the banner don't show after deleteing the page * fix: inserting a divider through the slash menu the cursor should stay active in the next line * fix: the overlay doesn't dismiss after selecting a page * fix: typo * fix: delete the page in document if it has been deleted * chore: l10n * chore: rename events * ci: rm install_diesel in ci * fix: cover color not working * ci: fix tauri build --------- Co-authored-by: nathan <nathan@appflowy.io>
This commit is contained in:
@ -414,7 +414,13 @@
|
|||||||
},
|
},
|
||||||
"optionAction": {
|
"optionAction": {
|
||||||
"click": "Click",
|
"click": "Click",
|
||||||
"toOpenMenu": " to open menu"
|
"toOpenMenu": " to open menu",
|
||||||
|
"delete": "Delete",
|
||||||
|
"duplicate": "Duplicate",
|
||||||
|
"turnInto": "Turn into",
|
||||||
|
"moveUp": "Move up",
|
||||||
|
"moveDown": "Move down",
|
||||||
|
"color": "Color"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -0,0 +1,90 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy_editor/appflowy_editor.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
|
import 'util/util.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
|
group('document', () {
|
||||||
|
const location = 'appflowy';
|
||||||
|
|
||||||
|
setUp(() async {
|
||||||
|
await TestFolder.cleanTestLocation(location);
|
||||||
|
await TestFolder.setTestLocation(location);
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDown(() async {
|
||||||
|
await TestFolder.cleanTestLocation(location);
|
||||||
|
});
|
||||||
|
|
||||||
|
tearDownAll(() async {
|
||||||
|
await TestFolder.cleanTestLocation(null);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('create a new document when launching app in first time',
|
||||||
|
(tester) async {
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
// create a new document
|
||||||
|
await tester.tapAddButton();
|
||||||
|
await tester.tapCreateDocumentButton();
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// expect to see a new document
|
||||||
|
tester.expectToSeePageName(
|
||||||
|
LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
|
||||||
|
);
|
||||||
|
// and with one paragraph block
|
||||||
|
expect(find.byType(TextBlockComponentWidget), findsOneWidget);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('delete the readme page and restore it', (tester) async {
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
// delete the readme page
|
||||||
|
await tester.hoverOnPageName(readme);
|
||||||
|
await tester.tapDeletePageButton();
|
||||||
|
|
||||||
|
// the banner should show up and the readme page should be gone
|
||||||
|
tester.expectToSeeDocumentBanner();
|
||||||
|
tester.expectNotToSeePageName(readme);
|
||||||
|
|
||||||
|
// restore the readme page
|
||||||
|
await tester.tapRestoreButton();
|
||||||
|
|
||||||
|
// the banner should be gone and the readme page should be back
|
||||||
|
tester.expectNotToSeeDocumentBanner();
|
||||||
|
tester.expectToSeePageName(readme);
|
||||||
|
});
|
||||||
|
|
||||||
|
testWidgets('delete the readme page and delete it permanently',
|
||||||
|
(tester) async {
|
||||||
|
await tester.initializeAppFlowy();
|
||||||
|
|
||||||
|
await tester.tapGoButton();
|
||||||
|
|
||||||
|
// delete the readme page
|
||||||
|
await tester.hoverOnPageName(readme);
|
||||||
|
await tester.tapDeletePageButton();
|
||||||
|
|
||||||
|
// the banner should show up and the readme page should be gone
|
||||||
|
tester.expectToSeeDocumentBanner();
|
||||||
|
tester.expectNotToSeePageName(readme);
|
||||||
|
|
||||||
|
// delete the page permanently
|
||||||
|
await tester.tapDeletePermanentlyButton();
|
||||||
|
|
||||||
|
// the banner should be gone and the readme page should be gone
|
||||||
|
tester.expectNotToSeeDocumentBanner();
|
||||||
|
tester.expectNotToSeePageName(readme);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
@ -4,6 +4,7 @@ import 'board_test.dart' as board_test;
|
|||||||
import 'switch_folder_test.dart' as switch_folder_test;
|
import 'switch_folder_test.dart' as switch_folder_test;
|
||||||
import 'empty_document_test.dart' as empty_document_test;
|
import 'empty_document_test.dart' as empty_document_test;
|
||||||
import 'open_ai_smart_menu_test.dart' as smart_menu_test;
|
import 'open_ai_smart_menu_test.dart' as smart_menu_test;
|
||||||
|
import 'document_test.dart' as document_test;
|
||||||
|
|
||||||
/// The main task runner for all integration tests in AppFlowy.
|
/// The main task runner for all integration tests in AppFlowy.
|
||||||
///
|
///
|
||||||
@ -18,4 +19,5 @@ void main() {
|
|||||||
board_test.main();
|
board_test.main();
|
||||||
empty_document_test.main();
|
empty_document_test.main();
|
||||||
smart_menu_test.main();
|
smart_menu_test.main();
|
||||||
|
document_test.main();
|
||||||
}
|
}
|
||||||
|
@ -51,7 +51,7 @@ void main() {
|
|||||||
// Click create button again
|
// Click create button again
|
||||||
await tester.tapCreateButton();
|
await tester.tapCreateButton();
|
||||||
|
|
||||||
await tester.expectToSeeWelcomePage();
|
tester.expectToSeeWelcomePage();
|
||||||
|
|
||||||
await TestFolder.cleanTestLocation(folderName);
|
await TestFolder.cleanTestLocation(folderName);
|
||||||
});
|
});
|
||||||
@ -69,7 +69,7 @@ void main() {
|
|||||||
await tester.tapOpenFolderButton();
|
await tester.tapOpenFolderButton();
|
||||||
|
|
||||||
await tester.wait(1000);
|
await tester.wait(1000);
|
||||||
await tester.expectToSeeWelcomePage();
|
tester.expectToSeeWelcomePage();
|
||||||
|
|
||||||
await TestFolder.cleanTestLocation(folderName);
|
await TestFolder.cleanTestLocation(folderName);
|
||||||
});
|
});
|
||||||
@ -84,7 +84,7 @@ void main() {
|
|||||||
await tester.initializeAppFlowy();
|
await tester.initializeAppFlowy();
|
||||||
|
|
||||||
await tester.tapGoButton();
|
await tester.tapGoButton();
|
||||||
await tester.expectToSeeWelcomePage();
|
tester.expectToSeeWelcomePage();
|
||||||
|
|
||||||
// switch to user B
|
// switch to user B
|
||||||
{
|
{
|
||||||
@ -99,7 +99,7 @@ void main() {
|
|||||||
await mockGetDirectoryPath(userB);
|
await mockGetDirectoryPath(userB);
|
||||||
await tester.tapCustomLocationButton();
|
await tester.tapCustomLocationButton();
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
await tester.expectToSeeWelcomePage();
|
tester.expectToSeeWelcomePage();
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch to the userA
|
// switch to the userA
|
||||||
@ -116,7 +116,7 @@ void main() {
|
|||||||
await tester.tapCustomLocationButton();
|
await tester.tapCustomLocationButton();
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
await tester.expectToSeeWelcomePage();
|
tester.expectToSeeWelcomePage();
|
||||||
expect(find.textContaining(userA), findsOneWidget);
|
expect(find.textContaining(userA), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ void main() {
|
|||||||
await tester.tapCustomLocationButton();
|
await tester.tapCustomLocationButton();
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
await tester.expectToSeeWelcomePage();
|
tester.expectToSeeWelcomePage();
|
||||||
expect(find.textContaining(userB), findsOneWidget);
|
expect(find.textContaining(userB), findsOneWidget);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,7 +145,7 @@ void main() {
|
|||||||
await tester.tapGoButton();
|
await tester.tapGoButton();
|
||||||
|
|
||||||
// home and readme document
|
// home and readme document
|
||||||
await tester.expectToSeeWelcomePage();
|
tester.expectToSeeWelcomePage();
|
||||||
|
|
||||||
// open settings and restore the location
|
// open settings and restore the location
|
||||||
await tester.openSettings();
|
await tester.openSettings();
|
||||||
|
@ -91,7 +91,7 @@ extension AppFlowyTestBase on WidgetTester {
|
|||||||
String tr, {
|
String tr, {
|
||||||
int milliseconds = 500,
|
int milliseconds = 500,
|
||||||
}) async {
|
}) async {
|
||||||
final button = find.text(tr);
|
final button = find.text(tr, findRichText: true);
|
||||||
await tapButton(
|
await tapButton(
|
||||||
button,
|
button,
|
||||||
milliseconds: milliseconds,
|
milliseconds: milliseconds,
|
||||||
|
@ -1,23 +1,100 @@
|
|||||||
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:appflowy/generated/locale_keys.g.dart';
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
|
import 'package:appflowy/plugins/document/presentation/banner.dart';
|
||||||
|
import 'package:appflowy/user/presentation/skip_log_in_screen.dart';
|
||||||
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
import 'package:appflowy/workspace/presentation/home/home_stack.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/app/header/add_button.dart';
|
||||||
|
import 'package:appflowy/workspace/presentation/home/menu/app/section/item.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
import 'base.dart';
|
import 'base.dart';
|
||||||
|
|
||||||
|
const String readme = 'Read me';
|
||||||
|
|
||||||
extension AppFlowyLaunch on WidgetTester {
|
extension AppFlowyLaunch on WidgetTester {
|
||||||
Future<void> tapGoButton() async {
|
Future<void> tapGoButton() async {
|
||||||
await tapButtonWithName(LocaleKeys.letsGoButtonText.tr());
|
final goButton = find.byType(GoButton);
|
||||||
return;
|
await tapButton(goButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> tapCreateButton() async {
|
Future<void> tapCreateButton() async {
|
||||||
await tapButtonWithName(LocaleKeys.settings_files_create.tr());
|
await tapButtonWithName(LocaleKeys.settings_files_create.tr());
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> expectToSeeWelcomePage() async {
|
void expectToSeeWelcomePage() {
|
||||||
expect(find.byType(HomeStack), findsOneWidget);
|
expect(find.byType(HomeStack), findsOneWidget);
|
||||||
expect(find.textContaining('Read me'), findsNWidgets(2));
|
expect(find.textContaining('Read me'), findsNWidgets(2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> tapAddButton() async {
|
||||||
|
final addButton = find.byType(AddButton);
|
||||||
|
await tapButton(addButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> tapCreateDocumentButton() async {
|
||||||
|
await tapButtonWithName(LocaleKeys.document_menuName.tr());
|
||||||
|
}
|
||||||
|
|
||||||
|
Finder findPageName(String name) {
|
||||||
|
return find.byWidgetPredicate(
|
||||||
|
(widget) => widget is ViewSectionItem && widget.view.name == name,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectToSeePageName(String name) {
|
||||||
|
final pageName = findPageName(name);
|
||||||
|
expect(pageName, findsOneWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectNotToSeePageName(String name) {
|
||||||
|
final pageName = findPageName(name);
|
||||||
|
expect(pageName, findsNothing);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> hoverOnPageName(String name) async {
|
||||||
|
final pageName = find.byWidgetPredicate(
|
||||||
|
(widget) => widget is ViewSectionItem && widget.view.name == name,
|
||||||
|
);
|
||||||
|
|
||||||
|
final gesture = await createGesture(kind: PointerDeviceKind.mouse);
|
||||||
|
await gesture.addPointer(location: Offset.zero);
|
||||||
|
addTearDown(gesture.removePointer);
|
||||||
|
await pump();
|
||||||
|
await gesture.moveTo(getCenter(pageName));
|
||||||
|
await pumpAndSettle();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> tapPageOptionButton() async {
|
||||||
|
final optionButton = find.byType(ViewDisclosureButton);
|
||||||
|
await tapButton(optionButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> tapDeletePageButton() async {
|
||||||
|
await tapPageOptionButton();
|
||||||
|
await tapButtonWithName(ViewDisclosureAction.delete.name);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectToSeeDocumentBanner() {
|
||||||
|
expect(find.byType(DocumentBanner), findsOneWidget);
|
||||||
|
}
|
||||||
|
|
||||||
|
void expectNotToSeeDocumentBanner() {
|
||||||
|
expect(find.byType(DocumentBanner), findsNothing);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> tapRestoreButton() async {
|
||||||
|
final restoreButton = find.textContaining(
|
||||||
|
LocaleKeys.deletePagePrompt_restore.tr(),
|
||||||
|
);
|
||||||
|
await tapButton(restoreButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> tapDeletePermanentlyButton() async {
|
||||||
|
final restoreButton = find.textContaining(
|
||||||
|
LocaleKeys.deletePagePrompt_deletePermanent.tr(),
|
||||||
|
);
|
||||||
|
await tapButton(restoreButton);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -66,7 +66,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
await _subscribe(state);
|
await _subscribe(state);
|
||||||
emit(state);
|
emit(state);
|
||||||
},
|
},
|
||||||
deleted: (Deleted value) async {
|
moveToTrash: (MoveToTrash value) async {
|
||||||
emit(state.copyWith(isDeleted: true));
|
emit(state.copyWith(isDeleted: true));
|
||||||
},
|
},
|
||||||
restore: (Restore value) async {
|
restore: (Restore value) async {
|
||||||
@ -74,11 +74,13 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
},
|
},
|
||||||
deletePermanently: (DeletePermanently value) async {
|
deletePermanently: (DeletePermanently value) async {
|
||||||
final result = await _trashService.deleteViews([view.id]);
|
final result = await _trashService.deleteViews([view.id]);
|
||||||
emit(state.copyWith(forceClose: result.swap().isLeft()));
|
final forceClose = result.fold((l) => true, (r) => false);
|
||||||
|
emit(state.copyWith(forceClose: forceClose));
|
||||||
},
|
},
|
||||||
restorePage: (RestorePage value) async {
|
restorePage: (RestorePage value) async {
|
||||||
final result = await _trashService.putback(view.id);
|
final result = await _trashService.putback(view.id);
|
||||||
emit(state.copyWith(isDeleted: result.swap().isRight()));
|
final isDeleted = result.fold((l) => false, (r) => true);
|
||||||
|
emit(state.copyWith(isDeleted: isDeleted));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@ -98,8 +100,12 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
/// subscribe to the view(document page) change
|
/// subscribe to the view(document page) change
|
||||||
void _onViewChanged() {
|
void _onViewChanged() {
|
||||||
_viewListener.start(
|
_viewListener.start(
|
||||||
onViewDeleted: (r) =>
|
onViewMoveToTrash: (r) {
|
||||||
r.swap().map((r) => add(const DocumentEvent.deleted())),
|
r.swap().map((r) => add(const DocumentEvent.moveToTrash()));
|
||||||
|
},
|
||||||
|
onViewDeleted: (r) {
|
||||||
|
r.swap().map((r) => add(const DocumentEvent.moveToTrash()));
|
||||||
|
},
|
||||||
onViewRestored: (r) =>
|
onViewRestored: (r) =>
|
||||||
r.swap().map((r) => add(const DocumentEvent.restore())),
|
r.swap().map((r) => add(const DocumentEvent.restore())),
|
||||||
);
|
);
|
||||||
@ -161,7 +167,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
|
|||||||
@freezed
|
@freezed
|
||||||
class DocumentEvent with _$DocumentEvent {
|
class DocumentEvent with _$DocumentEvent {
|
||||||
const factory DocumentEvent.initial() = Initial;
|
const factory DocumentEvent.initial() = Initial;
|
||||||
const factory DocumentEvent.deleted() = Deleted;
|
const factory DocumentEvent.moveToTrash() = MoveToTrash;
|
||||||
const factory DocumentEvent.restore() = Restore;
|
const factory DocumentEvent.restore() = Restore;
|
||||||
const factory DocumentEvent.restorePage() = RestorePage;
|
const factory DocumentEvent.restorePage() = RestorePage;
|
||||||
const factory DocumentEvent.deletePermanently() = DeletePermanently;
|
const factory DocumentEvent.deletePermanently() = DeletePermanently;
|
||||||
|
@ -88,35 +88,22 @@ extension DocumentDataPBFromTo on DocumentDataPB {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _BackendKeys {
|
|
||||||
const _BackendKeys._();
|
|
||||||
|
|
||||||
static const String text = 'text';
|
|
||||||
}
|
|
||||||
|
|
||||||
extension BlockToNode on BlockPB {
|
extension BlockToNode on BlockPB {
|
||||||
Node toNode({
|
Node toNode({
|
||||||
Iterable<Node>? children,
|
Iterable<Node>? children,
|
||||||
}) {
|
}) {
|
||||||
return Node(
|
return Node(
|
||||||
id: id,
|
id: id,
|
||||||
type: _typeAdapter(ty),
|
type: ty,
|
||||||
attributes: _dataAdapter(ty, data),
|
attributes: _dataAdapter(ty, data),
|
||||||
children: children ?? [],
|
children: children ?? [],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String _typeAdapter(String ty) {
|
|
||||||
final adapter = {
|
|
||||||
_BackendKeys.text: ParagraphBlockKeys.type,
|
|
||||||
};
|
|
||||||
return adapter[ty] ?? ty;
|
|
||||||
}
|
|
||||||
|
|
||||||
Attributes _dataAdapter(String ty, String data) {
|
Attributes _dataAdapter(String ty, String data) {
|
||||||
final map = Attributes.from(jsonDecode(data));
|
final map = Attributes.from(jsonDecode(data));
|
||||||
final adapter = {
|
final adapter = {
|
||||||
'text': (Attributes map) => map
|
ParagraphBlockKeys.type: (Attributes map) => map
|
||||||
..putIfAbsent(
|
..putIfAbsent(
|
||||||
'delta',
|
'delta',
|
||||||
() => Delta().toJson(),
|
() => Delta().toJson(),
|
||||||
@ -134,7 +121,7 @@ extension NodeToBlock on Node {
|
|||||||
assert(id.isNotEmpty);
|
assert(id.isNotEmpty);
|
||||||
final block = BlockPB.create()
|
final block = BlockPB.create()
|
||||||
..id = id
|
..id = id
|
||||||
..ty = _typeAdapter(type)
|
..ty = type
|
||||||
..data = _dataAdapter(type, attributes);
|
..data = _dataAdapter(type, attributes);
|
||||||
if (childrenId != null && childrenId.isNotEmpty) {
|
if (childrenId != null && childrenId.isNotEmpty) {
|
||||||
block.childrenId = childrenId;
|
block.childrenId = childrenId;
|
||||||
@ -145,13 +132,6 @@ extension NodeToBlock on Node {
|
|||||||
return block;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _typeAdapter(String type) {
|
|
||||||
final adapter = {
|
|
||||||
'paragraph': 'text',
|
|
||||||
};
|
|
||||||
return adapter[type] ?? type;
|
|
||||||
}
|
|
||||||
|
|
||||||
String _dataAdapter(String type, Attributes attributes) {
|
String _dataAdapter(String type, Attributes attributes) {
|
||||||
return jsonEncode(attributes);
|
return jsonEncode(attributes);
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxWidth: double.infinity,
|
maxWidth: double.infinity,
|
||||||
|
maxHeight: double.infinity,
|
||||||
),
|
),
|
||||||
child: FloatingToolbar(
|
child: FloatingToolbar(
|
||||||
style: styleCustomizer.floatingToolbarStyleBuilder(),
|
style: styleCustomizer.floatingToolbarStyleBuilder(),
|
||||||
@ -225,7 +226,7 @@ class _AppFlowyEditorPageState extends State<AppFlowyEditorPage> {
|
|||||||
];
|
];
|
||||||
|
|
||||||
final colorAction = [
|
final colorAction = [
|
||||||
// OptionAction.divider,
|
OptionAction.divider,
|
||||||
OptionAction.color,
|
OptionAction.color,
|
||||||
];
|
];
|
||||||
|
|
||||||
|
@ -1,9 +1,11 @@
|
|||||||
|
import 'package:appflowy/generated/locale_keys.g.dart';
|
||||||
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart';
|
import 'package:appflowy/plugins/database_view/grid/presentation/widgets/header/type_option/select_option_editor.dart';
|
||||||
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
|
import 'package:appflowy/plugins/database_view/widgets/row/cells/select_option_cell/extension.dart';
|
||||||
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
|
||||||
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg;
|
import 'package:appflowy_editor/appflowy_editor.dart' hide FlowySvg;
|
||||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flowy_infra/image.dart';
|
import 'package:flowy_infra/image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
@ -45,7 +47,7 @@ class ColorOptionAction extends PopoverActionCell {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String get name {
|
String get name {
|
||||||
return 'Color'; // todo: l10n
|
return LocaleKeys.toolbar_color.tr();
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -55,7 +57,6 @@ class ColorOptionAction extends PopoverActionCell {
|
|||||||
if (selection == null) {
|
if (selection == null) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
// TODO: should we support multiple selection?
|
|
||||||
final node = editorState.getNodeAtPath(selection.start.path);
|
final node = editorState.getNodeAtPath(selection.start.path);
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
return const SizedBox.shrink();
|
return const SizedBox.shrink();
|
||||||
@ -70,6 +71,8 @@ class ColorOptionAction extends PopoverActionCell {
|
|||||||
return SelectOptionColorList(
|
return SelectOptionColorList(
|
||||||
selectedColor: selectedColor,
|
selectedColor: selectedColor,
|
||||||
onSelectedColor: (color) {
|
onSelectedColor: (color) {
|
||||||
|
controller.close();
|
||||||
|
|
||||||
final nodes = editorState.getNodesInSelection(selection);
|
final nodes = editorState.getNodesInSelection(selection);
|
||||||
final transaction = editorState.transaction;
|
final transaction = editorState.transaction;
|
||||||
for (final node in nodes) {
|
for (final node in nodes) {
|
||||||
@ -79,8 +82,6 @@ class ColorOptionAction extends PopoverActionCell {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
editorState.apply(transaction);
|
editorState.apply(transaction);
|
||||||
|
|
||||||
controller.close();
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
@ -141,22 +142,22 @@ class OptionActionWrapper extends ActionCell {
|
|||||||
switch (inner) {
|
switch (inner) {
|
||||||
// TODO: l10n
|
// TODO: l10n
|
||||||
case OptionAction.delete:
|
case OptionAction.delete:
|
||||||
description = 'Delete';
|
description = LocaleKeys.document_plugins_optionAction_delete.tr();
|
||||||
break;
|
break;
|
||||||
case OptionAction.duplicate:
|
case OptionAction.duplicate:
|
||||||
description = 'Duplicate';
|
description = LocaleKeys.document_plugins_optionAction_duplicate.tr();
|
||||||
break;
|
break;
|
||||||
case OptionAction.turnInto:
|
case OptionAction.turnInto:
|
||||||
description = 'Turn into';
|
description = LocaleKeys.document_plugins_optionAction_turnInto.tr();
|
||||||
break;
|
break;
|
||||||
case OptionAction.moveUp:
|
case OptionAction.moveUp:
|
||||||
description = 'Move up';
|
description = LocaleKeys.document_plugins_optionAction_moveUp.tr();
|
||||||
break;
|
break;
|
||||||
case OptionAction.moveDown:
|
case OptionAction.moveDown:
|
||||||
description = 'Move down';
|
description = LocaleKeys.document_plugins_optionAction_moveDown.tr();
|
||||||
break;
|
break;
|
||||||
case OptionAction.color:
|
case OptionAction.color:
|
||||||
description = 'Color';
|
description = LocaleKeys.document_plugins_optionAction_color.tr();
|
||||||
break;
|
break;
|
||||||
case OptionAction.divider:
|
case OptionAction.divider:
|
||||||
throw UnimplementedError();
|
throw UnimplementedError();
|
||||||
|
@ -69,6 +69,10 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
|
|||||||
return _build(context, page);
|
return _build(context, page);
|
||||||
}
|
}
|
||||||
if (snapshot.connectionState == ConnectionState.done) {
|
if (snapshot.connectionState == ConnectionState.done) {
|
||||||
|
WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
|
||||||
|
// just delete the page if it is not found
|
||||||
|
_deletePage();
|
||||||
|
});
|
||||||
return const Center(
|
return const Center(
|
||||||
child: FlowyText('Cannot load the page'),
|
child: FlowyText('Cannot load the page'),
|
||||||
);
|
);
|
||||||
@ -174,6 +178,12 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> _deletePage() async {
|
||||||
|
final transaction = widget.editorState.transaction;
|
||||||
|
transaction.deleteNode(widget.node);
|
||||||
|
widget.editorState.apply(transaction);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
enum _ActionType {
|
enum _ActionType {
|
||||||
|
@ -23,7 +23,8 @@ void showLinkToPageMenu(
|
|||||||
final top = alignment == Alignment.bottomLeft ? offset.dy : null;
|
final top = alignment == Alignment.bottomLeft ? offset.dy : null;
|
||||||
final bottom = alignment == Alignment.topLeft ? offset.dy : null;
|
final bottom = alignment == Alignment.topLeft ? offset.dy : null;
|
||||||
|
|
||||||
final linkToPageMenuEntry = FullScreenOverlayEntry(
|
late OverlayEntry linkToPageMenuEntry;
|
||||||
|
linkToPageMenuEntry = FullScreenOverlayEntry(
|
||||||
top: top,
|
top: top,
|
||||||
bottom: bottom,
|
bottom: bottom,
|
||||||
left: offset.dx,
|
left: offset.dx,
|
||||||
@ -35,6 +36,7 @@ void showLinkToPageMenu(
|
|||||||
hintText: pageType.toHintText(),
|
hintText: pageType.toHintText(),
|
||||||
onSelected: (appPB, viewPB) {
|
onSelected: (appPB, viewPB) {
|
||||||
editorState.insertPage(appPB, viewPB);
|
editorState.insertPage(appPB, viewPB);
|
||||||
|
linkToPageMenuEntry.remove();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -465,17 +465,11 @@ class _CoverColorPickerState extends State<CoverColorPicker> {
|
|||||||
},
|
},
|
||||||
platform: TargetPlatform.windows,
|
platform: TargetPlatform.windows,
|
||||||
),
|
),
|
||||||
child: ListView.builder(
|
child: SingleChildScrollView(
|
||||||
controller: scrollController,
|
child: _buildColorItems(
|
||||||
shrinkWrap: true,
|
widget.backgroundColorOptions,
|
||||||
itemCount: widget.backgroundColorOptions.length,
|
widget.selectedBackgroundColorHex,
|
||||||
scrollDirection: Axis.horizontal,
|
),
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return _buildColorItems(
|
|
||||||
widget.backgroundColorOptions,
|
|
||||||
widget.selectedBackgroundColorHex,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -303,10 +303,11 @@ class _CoverImageState extends State<_CoverImage> {
|
|||||||
CoverSelectionType get selectionType => CoverSelectionType.fromString(
|
CoverSelectionType get selectionType => CoverSelectionType.fromString(
|
||||||
widget.node.attributes[CoverBlockKeys.selectionType],
|
widget.node.attributes[CoverBlockKeys.selectionType],
|
||||||
);
|
);
|
||||||
Color get color => Color(
|
Color get color {
|
||||||
int.tryParse(widget.node.attributes[CoverBlockKeys.selection]) ??
|
final hex = widget.node.attributes[CoverBlockKeys.selection] as String?;
|
||||||
0xFFFFFFFF,
|
return hex?.toColor() ?? Colors.white;
|
||||||
);
|
}
|
||||||
|
|
||||||
bool get hasIcon =>
|
bool get hasIcon =>
|
||||||
widget.node.attributes[CoverBlockKeys.iconSelection] == null
|
widget.node.attributes[CoverBlockKeys.iconSelection] == null
|
||||||
? false
|
? false
|
||||||
|
@ -35,7 +35,7 @@ CharacterShortcutEventHandler _convertMinusesToDividerHandler =
|
|||||||
..insertNode(path, dividerNode())
|
..insertNode(path, dividerNode())
|
||||||
..insertNode(path, paragraphNode())
|
..insertNode(path, paragraphNode())
|
||||||
..deleteNode(node)
|
..deleteNode(node)
|
||||||
..afterSelection = Selection.collapse(path.next, 0);
|
..afterSelection = Selection.collapse(path, 0);
|
||||||
editorState.apply(transaction);
|
editorState.apply(transaction);
|
||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
@ -61,7 +61,9 @@ SelectionMenuItem dividerMenuItem = SelectionMenuItem(
|
|||||||
}
|
}
|
||||||
final insertedPath = delta.isEmpty ? path : path.next;
|
final insertedPath = delta.isEmpty ? path : path.next;
|
||||||
final transaction = editorState.transaction
|
final transaction = editorState.transaction
|
||||||
..insertNode(insertedPath, dividerNode());
|
..insertNode(insertedPath, dividerNode())
|
||||||
|
..insertNode(insertedPath, paragraphNode())
|
||||||
|
..afterSelection = Selection.collapse(insertedPath.next, 0);
|
||||||
editorState.apply(transaction);
|
editorState.apply(transaction);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
@ -70,7 +70,7 @@ class UserBackendService {
|
|||||||
Future<Either<List<WorkspacePB>, FlowyError>> getWorkspaces() {
|
Future<Either<List<WorkspacePB>, FlowyError>> getWorkspaces() {
|
||||||
final request = WorkspaceIdPB.create();
|
final request = WorkspaceIdPB.create();
|
||||||
|
|
||||||
return FolderEventReadWorkspaces(request).send().then((result) {
|
return FolderEventReadAllWorkspaces(request).send().then((result) {
|
||||||
return result.fold(
|
return result.fold(
|
||||||
(workspaces) => left(workspaces.items),
|
(workspaces) => left(workspaces.items),
|
||||||
(error) => right(error),
|
(error) => right(error),
|
||||||
|
@ -50,7 +50,7 @@ class AuthRouter {
|
|||||||
BuildContext context,
|
BuildContext context,
|
||||||
UserProfilePB userProfile,
|
UserProfilePB userProfile,
|
||||||
) async {
|
) async {
|
||||||
final result = await FolderEventReadCurrentWorkspace().send();
|
final result = await FolderEventGetCurrentWorkspace().send();
|
||||||
result.fold(
|
result.fold(
|
||||||
(workspaceSettingPB) => pushHomeScreenWithWorkSpace(
|
(workspaceSettingPB) => pushHomeScreenWithWorkSpace(
|
||||||
context,
|
context,
|
||||||
@ -75,7 +75,7 @@ class SplashRoute {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
FolderEventReadCurrentWorkspace().send().then((result) {
|
FolderEventGetCurrentWorkspace().send().then((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(workspaceSettingPB) =>
|
(workspaceSettingPB) =>
|
||||||
pushHomeScreen(context, userProfile, workspaceSettingPB),
|
pushHomeScreen(context, userProfile, workspaceSettingPB),
|
||||||
|
@ -126,7 +126,7 @@ class _SkipLogInScreenState extends State<SkipLogInScreen> {
|
|||||||
Log.error(error);
|
Log.error(error);
|
||||||
},
|
},
|
||||||
(user) {
|
(user) {
|
||||||
FolderEventReadCurrentWorkspace().send().then((result) {
|
FolderEventGetCurrentWorkspace().send().then((result) {
|
||||||
_openCurrentWorkspace(context, user, result);
|
_openCurrentWorkspace(context, user, result);
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -70,7 +70,7 @@ class SplashScreen extends StatelessWidget {
|
|||||||
Authenticated authenticated,
|
Authenticated authenticated,
|
||||||
) async {
|
) async {
|
||||||
final userProfile = authenticated.userProfile;
|
final userProfile = authenticated.userProfile;
|
||||||
final result = await FolderEventReadCurrentWorkspace().send();
|
final result = await FolderEventGetCurrentWorkspace().send();
|
||||||
result.fold(
|
result.fold(
|
||||||
(workspaceSetting) {
|
(workspaceSetting) {
|
||||||
getIt<SplashRoute>().pushHomeScreen(
|
getIt<SplashRoute>().pushHomeScreen(
|
||||||
|
@ -122,7 +122,7 @@ class ViewBackendService {
|
|||||||
ViewLayoutPB layoutType,
|
ViewLayoutPB layoutType,
|
||||||
) async {
|
) async {
|
||||||
final result = <(ViewPB, List<ViewPB>)>[];
|
final result = <(ViewPB, List<ViewPB>)>[];
|
||||||
return FolderEventReadCurrentWorkspace().send().then((value) async {
|
return FolderEventGetCurrentWorkspace().send().then((value) async {
|
||||||
final workspaces = value.getLeftOrNull<WorkspaceSettingPB>();
|
final workspaces = value.getLeftOrNull<WorkspaceSettingPB>();
|
||||||
if (workspaces != null) {
|
if (workspaces != null) {
|
||||||
final views = workspaces.workspace.views;
|
final views = workspaces.workspace.views;
|
||||||
|
@ -35,7 +35,7 @@ class WorkspaceService {
|
|||||||
|
|
||||||
Future<Either<WorkspacePB, FlowyError>> getWorkspace() {
|
Future<Either<WorkspacePB, FlowyError>> getWorkspace() {
|
||||||
final payload = WorkspaceIdPB.create()..value = workspaceId;
|
final payload = WorkspaceIdPB.create()..value = workspaceId;
|
||||||
return FolderEventReadWorkspaces(payload).send().then((result) {
|
return FolderEventReadAllWorkspaces(payload).send().then((result) {
|
||||||
return result.fold(
|
return result.fold(
|
||||||
(workspaces) {
|
(workspaces) {
|
||||||
assert(workspaces.items.length == 1);
|
assert(workspaces.items.length == 1);
|
||||||
|
@ -35,7 +35,7 @@ class _FileExporterWidgetState extends State<FileExporterWidget> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return FutureBuilder<dartz.Either<WorkspaceSettingPB, FlowyError>>(
|
return FutureBuilder<dartz.Either<WorkspaceSettingPB, FlowyError>>(
|
||||||
future: FolderEventReadCurrentWorkspace().send(),
|
future: FolderEventGetCurrentWorkspace().send(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
if (snapshot.hasData &&
|
if (snapshot.hasData &&
|
||||||
snapshot.connectionState == ConnectionState.done) {
|
snapshot.connectionState == ConnectionState.done) {
|
||||||
|
@ -179,7 +179,6 @@ class PopoverActionCellWidget<T extends PopoverAction> extends StatelessWidget {
|
|||||||
final rightIcon =
|
final rightIcon =
|
||||||
actionCell.rightIcon(Theme.of(context).colorScheme.onSurface);
|
actionCell.rightIcon(Theme.of(context).colorScheme.onSurface);
|
||||||
return AppFlowyPopover(
|
return AppFlowyPopover(
|
||||||
// mutex: mutex,
|
|
||||||
controller: popoverController,
|
controller: popoverController,
|
||||||
asBarrier: true,
|
asBarrier: true,
|
||||||
popupBuilder: (context) => actionCell.builder(
|
popupBuilder: (context) => actionCell.builder(
|
||||||
|
@ -127,7 +127,7 @@ void main() {
|
|||||||
..add(const DocumentEvent.initial());
|
..add(const DocumentEvent.initial());
|
||||||
await blocResponseFuture();
|
await blocResponseFuture();
|
||||||
|
|
||||||
final workspaceSetting = await FolderEventReadCurrentWorkspace()
|
final workspaceSetting = await FolderEventGetCurrentWorkspace()
|
||||||
.send()
|
.send()
|
||||||
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
||||||
workspaceSetting.latestView.id == document1.id;
|
workspaceSetting.latestView.id == document1.id;
|
||||||
@ -148,7 +148,7 @@ void main() {
|
|||||||
final grid = bloc.state.latestCreatedView;
|
final grid = bloc.state.latestCreatedView;
|
||||||
assert(grid!.name == "grid 2");
|
assert(grid!.name == "grid 2");
|
||||||
|
|
||||||
var workspaceSetting = await FolderEventReadCurrentWorkspace()
|
var workspaceSetting = await FolderEventGetCurrentWorkspace()
|
||||||
.send()
|
.send()
|
||||||
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
||||||
workspaceSetting.latestView.id == grid!.id;
|
workspaceSetting.latestView.id == grid!.id;
|
||||||
@ -159,7 +159,7 @@ void main() {
|
|||||||
..add(const DocumentEvent.initial());
|
..add(const DocumentEvent.initial());
|
||||||
await blocResponseFuture();
|
await blocResponseFuture();
|
||||||
|
|
||||||
workspaceSetting = await FolderEventReadCurrentWorkspace()
|
workspaceSetting = await FolderEventGetCurrentWorkspace()
|
||||||
.send()
|
.send()
|
||||||
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
||||||
workspaceSetting.latestView.id == document.id;
|
workspaceSetting.latestView.id == document.id;
|
||||||
|
@ -15,7 +15,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('initi home screen', () async {
|
test('initi home screen', () async {
|
||||||
final workspaceSetting = await FolderEventReadCurrentWorkspace()
|
final workspaceSetting = await FolderEventGetCurrentWorkspace()
|
||||||
.send()
|
.send()
|
||||||
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
||||||
await blocResponseFuture();
|
await blocResponseFuture();
|
||||||
@ -28,7 +28,7 @@ void main() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('open the document', () async {
|
test('open the document', () async {
|
||||||
final workspaceSetting = await FolderEventReadCurrentWorkspace()
|
final workspaceSetting = await FolderEventGetCurrentWorkspace()
|
||||||
.send()
|
.send()
|
||||||
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
.then((result) => result.fold((l) => l, (r) => throw Exception()));
|
||||||
await blocResponseFuture();
|
await blocResponseFuture();
|
||||||
|
20
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
20
frontend/appflowy_tauri/src-tauri/Cargo.lock
generated
@ -99,7 +99,7 @@ checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "appflowy-integrate"
|
name = "appflowy-integrate"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -1024,7 +1024,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab"
|
name = "collab"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -1042,7 +1042,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-client-ws"
|
name = "collab-client-ws"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"collab-sync",
|
"collab-sync",
|
||||||
@ -1060,7 +1060,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-database"
|
name = "collab-database"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -1086,7 +1086,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-derive"
|
name = "collab-derive"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
@ -1098,7 +1098,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-document"
|
name = "collab-document"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -1115,7 +1115,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-folder"
|
name = "collab-folder"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"collab",
|
"collab",
|
||||||
@ -1134,7 +1134,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-persistence"
|
name = "collab-persistence"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bincode",
|
"bincode",
|
||||||
"chrono",
|
"chrono",
|
||||||
@ -1154,7 +1154,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-plugins"
|
name = "collab-plugins"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"async-trait",
|
"async-trait",
|
||||||
@ -1184,7 +1184,7 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "collab-sync"
|
name = "collab-sync"
|
||||||
version = "0.1.0"
|
version = "0.1.0"
|
||||||
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=12e373#12e373f972d893d5f34b18794e77d3b49783ddcf"
|
source = "git+https://github.com/AppFlowy-IO/AppFlowy-Collab?rev=13b178#13b17802de31e75255b4303914042bdbb04361b2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"bytes",
|
"bytes",
|
||||||
"collab",
|
"collab",
|
||||||
|
@ -2,7 +2,7 @@ import { currentUserActions } from '../../stores/reducers/current-user/slice';
|
|||||||
import { useAppDispatch, useAppSelector } from '../../stores/store';
|
import { useAppDispatch, useAppSelector } from '../../stores/store';
|
||||||
import { UserProfilePB } from '../../../services/backend/events/flowy-user';
|
import { UserProfilePB } from '../../../services/backend/events/flowy-user';
|
||||||
import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc';
|
import { AuthBackendService, UserBackendService } from '../../stores/effects/user/user_bd_svc';
|
||||||
import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
|
import { FolderEventGetCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
|
||||||
import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder2/workspace';
|
import { WorkspaceSettingPB } from '../../../services/backend/models/flowy-folder2/workspace';
|
||||||
import { Log } from '../../utils/log';
|
import { Log } from '../../utils/log';
|
||||||
|
|
||||||
@ -90,7 +90,7 @@ export const useAuth = () => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async function _openWorkspace() {
|
async function _openWorkspace() {
|
||||||
return FolderEventReadCurrentWorkspace();
|
return FolderEventGetCurrentWorkspace();
|
||||||
}
|
}
|
||||||
|
|
||||||
return { currentUser, checkUser, register, login, logout };
|
return { currentUser, checkUser, register, login, logout };
|
||||||
|
@ -5,7 +5,7 @@ import {
|
|||||||
ViewPB,
|
ViewPB,
|
||||||
WorkspaceSettingPB,
|
WorkspaceSettingPB,
|
||||||
} from '../../../services/backend';
|
} from '../../../services/backend';
|
||||||
import { FolderEventReadCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
|
import { FolderEventGetCurrentWorkspace } from '../../../services/backend/events/flowy-folder2';
|
||||||
import { AppBackendService } from '../../stores/effects/folder/app/app_bd_svc';
|
import { AppBackendService } from '../../stores/effects/folder/app/app_bd_svc';
|
||||||
import { DatabaseController } from '../../stores/effects/database/database_controller';
|
import { DatabaseController } from '../../stores/effects/database/database_controller';
|
||||||
import { RowInfo } from '../../stores/effects/database/row/row_cache';
|
import { RowInfo } from '../../stores/effects/database/row/row_cache';
|
||||||
@ -31,7 +31,7 @@ import { Log } from '$app/utils/log';
|
|||||||
// Create a database view for specific layout type
|
// Create a database view for specific layout type
|
||||||
// Do not use it production code. Just for testing
|
// Do not use it production code. Just for testing
|
||||||
export async function createTestDatabaseView(layout: ViewLayoutPB): Promise<ViewPB> {
|
export async function createTestDatabaseView(layout: ViewLayoutPB): Promise<ViewPB> {
|
||||||
const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap());
|
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspace().then((result) => result.unwrap());
|
||||||
const appService = new AppBackendService(workspaceSetting.workspace.id);
|
const appService = new AppBackendService(workspaceSetting.workspace.id);
|
||||||
return await appService.createView({ name: 'New Grid', layoutType: layout });
|
return await appService.createView({ name: 'New Grid', layoutType: layout });
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
import { ViewLayoutPB, WorkspaceSettingPB } from '@/services/backend';
|
import { ViewLayoutPB, WorkspaceSettingPB } from '@/services/backend';
|
||||||
import { FolderEventReadCurrentWorkspace } from '@/services/backend/events/flowy-folder2';
|
import { FolderEventGetCurrentWorkspace } from '@/services/backend/events/flowy-folder2';
|
||||||
import { AppBackendService } from '$app/stores/effects/folder/app/app_bd_svc';
|
import { AppBackendService } from '$app/stores/effects/folder/app/app_bd_svc';
|
||||||
|
|
||||||
export async function createTestDocument() {
|
export async function createTestDocument() {
|
||||||
const workspaceSetting: WorkspaceSettingPB = await FolderEventReadCurrentWorkspace().then((result) => result.unwrap());
|
const workspaceSetting: WorkspaceSettingPB = await FolderEventGetCurrentWorkspace().then((result) => result.unwrap());
|
||||||
const app = workspaceSetting.workspace.views[0];
|
const app = workspaceSetting.workspace.views[0];
|
||||||
const appService = new AppBackendService(app.id);
|
const appService = new AppBackendService(app.id);
|
||||||
return await appService.createView({ name: 'New Document', layoutType: ViewLayoutPB.Document });
|
return await appService.createView({ name: 'New Document', layoutType: ViewLayoutPB.Document });
|
||||||
|
@ -3,7 +3,7 @@ import {
|
|||||||
FolderEventCreateView,
|
FolderEventCreateView,
|
||||||
FolderEventMoveItem,
|
FolderEventMoveItem,
|
||||||
FolderEventReadWorkspaceViews,
|
FolderEventReadWorkspaceViews,
|
||||||
FolderEventReadWorkspaces,
|
FolderEventReadAllWorkspaces,
|
||||||
} from '@/services/backend/events/flowy-folder2';
|
} from '@/services/backend/events/flowy-folder2';
|
||||||
import {
|
import {
|
||||||
CreateViewPayloadPB,
|
CreateViewPayloadPB,
|
||||||
@ -35,7 +35,7 @@ export class WorkspaceBackendService {
|
|||||||
|
|
||||||
getWorkspace = () => {
|
getWorkspace = () => {
|
||||||
const payload = WorkspaceIdPB.fromObject({ value: this.workspaceId });
|
const payload = WorkspaceIdPB.fromObject({ value: this.workspaceId });
|
||||||
return FolderEventReadWorkspaces(payload).then((result) => {
|
return FolderEventReadAllWorkspaces(payload).then((result) => {
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
const workspaces = result.val.items;
|
const workspaces = result.val.items;
|
||||||
if (workspaces.length === 0) {
|
if (workspaces.length === 0) {
|
||||||
|
@ -21,8 +21,8 @@ import {
|
|||||||
import {
|
import {
|
||||||
FolderEventCreateWorkspace,
|
FolderEventCreateWorkspace,
|
||||||
FolderEventOpenWorkspace,
|
FolderEventOpenWorkspace,
|
||||||
FolderEventReadCurrentWorkspace,
|
FolderEventGetCurrentWorkspace,
|
||||||
FolderEventReadWorkspaces,
|
FolderEventReadAllWorkspaces,
|
||||||
} from '@/services/backend/events/flowy-folder2';
|
} from '@/services/backend/events/flowy-folder2';
|
||||||
|
|
||||||
export class UserBackendService {
|
export class UserBackendService {
|
||||||
@ -54,7 +54,7 @@ export class UserBackendService {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getCurrentWorkspace = async (): Promise<WorkspaceSettingPB> => {
|
getCurrentWorkspace = async (): Promise<WorkspaceSettingPB> => {
|
||||||
const result = await FolderEventReadCurrentWorkspace();
|
const result = await FolderEventGetCurrentWorkspace();
|
||||||
if (result.ok) {
|
if (result.ok) {
|
||||||
return result.val;
|
return result.val;
|
||||||
} else {
|
} else {
|
||||||
@ -64,7 +64,7 @@ export class UserBackendService {
|
|||||||
|
|
||||||
getWorkspaces = () => {
|
getWorkspaces = () => {
|
||||||
const payload = WorkspaceIdPB.fromObject({});
|
const payload = WorkspaceIdPB.fromObject({});
|
||||||
return FolderEventReadWorkspaces(payload);
|
return FolderEventReadAllWorkspaces(payload);
|
||||||
};
|
};
|
||||||
|
|
||||||
openWorkspace = (workspaceId: string) => {
|
openWorkspace = (workspaceId: string) => {
|
||||||
|
@ -12,10 +12,10 @@ pub fn init(folder: Arc<Folder2Manager>) -> AFPlugin {
|
|||||||
// Workspace
|
// Workspace
|
||||||
.event(FolderEvent::CreateWorkspace, create_workspace_handler)
|
.event(FolderEvent::CreateWorkspace, create_workspace_handler)
|
||||||
.event(
|
.event(
|
||||||
FolderEvent::ReadCurrentWorkspace,
|
FolderEvent::GetCurrentWorkspace,
|
||||||
read_cur_workspace_setting_handler,
|
read_cur_workspace_setting_handler,
|
||||||
)
|
)
|
||||||
.event(FolderEvent::ReadWorkspaces, read_workspaces_handler)
|
.event(FolderEvent::ReadAllWorkspaces, read_workspaces_handler)
|
||||||
.event(FolderEvent::OpenWorkspace, open_workspace_handler)
|
.event(FolderEvent::OpenWorkspace, open_workspace_handler)
|
||||||
.event(FolderEvent::ReadWorkspaceViews, read_workspace_views_handler)
|
.event(FolderEvent::ReadWorkspaceViews, read_workspace_views_handler)
|
||||||
// View
|
// View
|
||||||
@ -45,11 +45,11 @@ pub enum FolderEvent {
|
|||||||
|
|
||||||
/// Read the current opening workspace. Currently, we only support one workspace
|
/// Read the current opening workspace. Currently, we only support one workspace
|
||||||
#[event(output = "WorkspaceSettingPB")]
|
#[event(output = "WorkspaceSettingPB")]
|
||||||
ReadCurrentWorkspace = 1,
|
GetCurrentWorkspace = 1,
|
||||||
|
|
||||||
/// Return a list of workspaces that the current user can access
|
/// Return a list of workspaces that the current user can access.
|
||||||
#[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")]
|
#[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")]
|
||||||
ReadWorkspaces = 2,
|
ReadAllWorkspaces = 2,
|
||||||
|
|
||||||
/// Delete the workspace
|
/// Delete the workspace
|
||||||
#[event(input = "WorkspaceIdPB")]
|
#[event(input = "WorkspaceIdPB")]
|
||||||
@ -59,7 +59,8 @@ pub enum FolderEvent {
|
|||||||
#[event(input = "WorkspaceIdPB", output = "WorkspacePB")]
|
#[event(input = "WorkspaceIdPB", output = "WorkspacePB")]
|
||||||
OpenWorkspace = 4,
|
OpenWorkspace = 4,
|
||||||
|
|
||||||
/// Return a list of views that belong to this workspace.
|
/// Return a list of views of the current workspace.
|
||||||
|
/// Only the first level of child views are included.
|
||||||
#[event(input = "WorkspaceIdPB", output = "RepeatedViewPB")]
|
#[event(input = "WorkspaceIdPB", output = "RepeatedViewPB")]
|
||||||
ReadWorkspaceViews = 5,
|
ReadWorkspaceViews = 5,
|
||||||
|
|
||||||
|
@ -18,8 +18,8 @@ use lib_infra::util::timestamp;
|
|||||||
|
|
||||||
use crate::deps::{FolderCloudService, FolderUser};
|
use crate::deps::{FolderCloudService, FolderUser};
|
||||||
use crate::entities::{
|
use crate::entities::{
|
||||||
view_pb_with_child_views, CreateViewParams, CreateWorkspaceParams, RepeatedTrashPB,
|
view_pb_with_child_views, CreateViewParams, CreateWorkspaceParams, DeletedViewPB,
|
||||||
RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, ViewPB,
|
RepeatedTrashPB, RepeatedViewPB, RepeatedWorkspacePB, UpdateViewParams, ViewPB,
|
||||||
};
|
};
|
||||||
use crate::notification::{
|
use crate::notification::{
|
||||||
send_notification, send_workspace_notification, send_workspace_setting_notification,
|
send_notification, send_workspace_notification, send_workspace_setting_notification,
|
||||||
@ -68,6 +68,8 @@ impl Folder2Manager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Return a list of views of the current workspace.
|
||||||
|
/// Only the first level of child views are included.
|
||||||
pub async fn get_current_workspace_views(&self) -> FlowyResult<Vec<ViewPB>> {
|
pub async fn get_current_workspace_views(&self) -> FlowyResult<Vec<ViewPB>> {
|
||||||
let workspace_id = self
|
let workspace_id = self
|
||||||
.mutex_folder
|
.mutex_folder
|
||||||
@ -315,6 +317,14 @@ impl Folder2Manager {
|
|||||||
folder.set_current_view("");
|
folder.set_current_view("");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// notify the parent view that the view is moved to trash
|
||||||
|
send_notification(view_id, FolderNotification::DidMoveViewToTrash)
|
||||||
|
.payload(DeletedViewPB {
|
||||||
|
view_id: view_id.to_string(),
|
||||||
|
index: None,
|
||||||
|
})
|
||||||
|
.send();
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
@ -4,14 +4,14 @@ use flowy_folder2::entities::CreateWorkspacePayloadPB;
|
|||||||
use flowy_test::{event_builder::*, FlowyCoreTest};
|
use flowy_test::{event_builder::*, FlowyCoreTest};
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn workspace_read_all() {
|
async fn read_all_workspace_test() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
test.run_scripts(vec![ReadAllWorkspaces]).await;
|
test.run_scripts(vec![ReadAllWorkspaces]).await;
|
||||||
assert!(!test.all_workspace.is_empty());
|
assert!(!test.all_workspace.is_empty());
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn workspace_create() {
|
async fn create_workspace_test() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
let name = "My new workspace".to_owned();
|
let name = "My new workspace".to_owned();
|
||||||
let desc = "Daily routines".to_owned();
|
let desc = "Daily routines".to_owned();
|
||||||
@ -34,7 +34,7 @@ async fn workspace_create() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn workspace_read() {
|
async fn get_workspace_test() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
let workspace = test.workspace.clone();
|
let workspace = test.workspace.clone();
|
||||||
|
|
||||||
@ -47,21 +47,21 @@ async fn workspace_read() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn workspace_create_with_apps() {
|
async fn create_parent_view_test() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
test
|
test
|
||||||
.run_scripts(vec![CreateApp {
|
.run_scripts(vec![CreateParentView {
|
||||||
name: "App".to_string(),
|
name: "App".to_string(),
|
||||||
desc: "App description".to_string(),
|
desc: "App description".to_string(),
|
||||||
}])
|
}])
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let app = test.parent_view.clone();
|
let app = test.parent_view.clone();
|
||||||
test.run_scripts(vec![RefreshRootView(app.id)]).await;
|
test.run_scripts(vec![ReloadParentView(app.id)]).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn workspace_create_with_invalid_name() {
|
async fn create_parent_view_with_invalid_name() {
|
||||||
for (name, code) in invalid_workspace_name_test_case() {
|
for (name, code) in invalid_workspace_name_test_case() {
|
||||||
let sdk = FlowyCoreTest::new();
|
let sdk = FlowyCoreTest::new();
|
||||||
let request = CreateWorkspacePayloadPB {
|
let request = CreateWorkspacePayloadPB {
|
||||||
@ -84,46 +84,46 @@ async fn workspace_create_with_invalid_name() {
|
|||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
#[should_panic]
|
#[should_panic]
|
||||||
async fn app_delete() {
|
async fn delete_parent_view_test() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
let app = test.parent_view.clone();
|
let parent_view = test.parent_view.clone();
|
||||||
test
|
test
|
||||||
.run_scripts(vec![DeleteRootView, RefreshRootView(app.id)])
|
.run_scripts(vec![DeleteParentView, ReloadParentView(parent_view.id)])
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn app_delete_then_restore() {
|
async fn delete_parent_view_then_restore() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
test
|
test
|
||||||
.run_scripts(vec![RefreshRootView(test.parent_view.id.clone())])
|
.run_scripts(vec![ReloadParentView(test.parent_view.id.clone())])
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
let parent_view = test.parent_view.clone();
|
let parent_view = test.parent_view.clone();
|
||||||
test
|
test
|
||||||
.run_scripts(vec![
|
.run_scripts(vec![
|
||||||
DeleteRootView,
|
DeleteParentView,
|
||||||
RestoreAppFromTrash,
|
RestoreAppFromTrash,
|
||||||
RefreshRootView(parent_view.id.clone()),
|
ReloadParentView(parent_view.id.clone()),
|
||||||
AssertRootView(parent_view),
|
AssertParentView(parent_view),
|
||||||
])
|
])
|
||||||
.await;
|
.await;
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn app_update() {
|
async fn update_parent_view_test() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
let app = test.parent_view.clone();
|
let parent_view = test.parent_view.clone();
|
||||||
let new_name = "😁 hell world".to_owned();
|
let new_name = "😁 hell world".to_owned();
|
||||||
assert_ne!(app.name, new_name);
|
assert_ne!(parent_view.name, new_name);
|
||||||
|
|
||||||
test
|
test
|
||||||
.run_scripts(vec![
|
.run_scripts(vec![
|
||||||
UpdateRootView {
|
UpdateParentView {
|
||||||
name: Some(new_name.clone()),
|
name: Some(new_name.clone()),
|
||||||
desc: None,
|
desc: None,
|
||||||
},
|
},
|
||||||
RefreshRootView(app.id),
|
ReloadParentView(parent_view.id),
|
||||||
])
|
])
|
||||||
.await;
|
.await;
|
||||||
assert_eq!(test.parent_view.name, new_name);
|
assert_eq!(test.parent_view.name, new_name);
|
||||||
@ -145,7 +145,7 @@ async fn app_create_with_view() {
|
|||||||
desc: "Grid description".to_owned(),
|
desc: "Grid description".to_owned(),
|
||||||
layout: ViewLayout::Grid,
|
layout: ViewLayout::Grid,
|
||||||
},
|
},
|
||||||
RefreshRootView(app.id),
|
ReloadParentView(app.id),
|
||||||
])
|
])
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -212,7 +212,7 @@ async fn view_delete_all() {
|
|||||||
desc: "Grid description".to_owned(),
|
desc: "Grid description".to_owned(),
|
||||||
layout: ViewLayout::Grid,
|
layout: ViewLayout::Grid,
|
||||||
},
|
},
|
||||||
RefreshRootView(parent_view.id.clone()),
|
ReloadParentView(parent_view.id.clone()),
|
||||||
])
|
])
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -230,7 +230,7 @@ async fn view_delete_all() {
|
|||||||
test
|
test
|
||||||
.run_scripts(vec![
|
.run_scripts(vec![
|
||||||
DeleteViews(view_ids),
|
DeleteViews(view_ids),
|
||||||
RefreshRootView(parent_view.id),
|
ReloadParentView(parent_view.id),
|
||||||
ReadTrash,
|
ReadTrash,
|
||||||
])
|
])
|
||||||
.await;
|
.await;
|
||||||
@ -242,7 +242,7 @@ async fn view_delete_all() {
|
|||||||
#[tokio::test]
|
#[tokio::test]
|
||||||
async fn view_delete_all_permanent() {
|
async fn view_delete_all_permanent() {
|
||||||
let mut test = FolderTest::new().await;
|
let mut test = FolderTest::new().await;
|
||||||
let app = test.parent_view.clone();
|
let parent_view = test.parent_view.clone();
|
||||||
test
|
test
|
||||||
.run_scripts(vec![
|
.run_scripts(vec![
|
||||||
CreateView {
|
CreateView {
|
||||||
@ -250,7 +250,7 @@ async fn view_delete_all_permanent() {
|
|||||||
desc: "View A description".to_owned(),
|
desc: "View A description".to_owned(),
|
||||||
layout: ViewLayout::Document,
|
layout: ViewLayout::Document,
|
||||||
},
|
},
|
||||||
RefreshRootView(app.id.clone()),
|
ReloadParentView(parent_view.id.clone()),
|
||||||
])
|
])
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -263,7 +263,7 @@ async fn view_delete_all_permanent() {
|
|||||||
test
|
test
|
||||||
.run_scripts(vec![
|
.run_scripts(vec![
|
||||||
DeleteViews(view_ids),
|
DeleteViews(view_ids),
|
||||||
RefreshRootView(app.id),
|
ReloadParentView(parent_view.id),
|
||||||
DeleteAllTrash,
|
DeleteAllTrash,
|
||||||
ReadTrash,
|
ReadTrash,
|
||||||
])
|
])
|
||||||
|
@ -16,17 +16,17 @@ pub enum FolderScript {
|
|||||||
ReadWorkspace(Option<String>),
|
ReadWorkspace(Option<String>),
|
||||||
|
|
||||||
// App
|
// App
|
||||||
CreateApp {
|
CreateParentView {
|
||||||
name: String,
|
name: String,
|
||||||
desc: String,
|
desc: String,
|
||||||
},
|
},
|
||||||
AssertRootView(ViewPB),
|
AssertParentView(ViewPB),
|
||||||
RefreshRootView(String),
|
ReloadParentView(String),
|
||||||
UpdateRootView {
|
UpdateParentView {
|
||||||
name: Option<String>,
|
name: Option<String>,
|
||||||
desc: Option<String>,
|
desc: Option<String>,
|
||||||
},
|
},
|
||||||
DeleteRootView,
|
DeleteParentView,
|
||||||
|
|
||||||
// View
|
// View
|
||||||
CreateView {
|
CreateView {
|
||||||
@ -107,24 +107,23 @@ impl FolderTest {
|
|||||||
let workspace = read_workspace(sdk, workspace_id).await.pop().unwrap();
|
let workspace = read_workspace(sdk, workspace_id).await.pop().unwrap();
|
||||||
self.workspace = workspace;
|
self.workspace = workspace;
|
||||||
},
|
},
|
||||||
FolderScript::CreateApp { name, desc } => {
|
FolderScript::CreateParentView { name, desc } => {
|
||||||
let app = create_app(sdk, &self.workspace.id, &name, &desc).await;
|
let app = create_app(sdk, &self.workspace.id, &name, &desc).await;
|
||||||
self.parent_view = app;
|
self.parent_view = app;
|
||||||
},
|
},
|
||||||
FolderScript::AssertRootView(app) => {
|
FolderScript::AssertParentView(app) => {
|
||||||
assert_eq!(self.parent_view, app, "App not equal");
|
assert_eq!(self.parent_view, app, "App not equal");
|
||||||
},
|
},
|
||||||
FolderScript::RefreshRootView(app_id) => {
|
FolderScript::ReloadParentView(parent_view_id) => {
|
||||||
let app = read_view(sdk, &app_id).await;
|
let parent_view = read_view(sdk, &parent_view_id).await;
|
||||||
self.parent_view = app;
|
self.parent_view = parent_view;
|
||||||
},
|
},
|
||||||
FolderScript::UpdateRootView { name, desc } => {
|
FolderScript::UpdateParentView { name, desc } => {
|
||||||
update_view(sdk, &self.parent_view.id, name, desc).await;
|
update_view(sdk, &self.parent_view.id, name, desc).await;
|
||||||
},
|
},
|
||||||
FolderScript::DeleteRootView => {
|
FolderScript::DeleteParentView => {
|
||||||
delete_view(sdk, vec![self.parent_view.id.clone()]).await;
|
delete_view(sdk, vec![self.parent_view.id.clone()]).await;
|
||||||
},
|
},
|
||||||
|
|
||||||
FolderScript::CreateView { name, desc, layout } => {
|
FolderScript::CreateView { name, desc, layout } => {
|
||||||
let view = create_view(sdk, &self.parent_view.id, &name, &desc, layout).await;
|
let view = create_view(sdk, &self.parent_view.id, &name, &desc, layout).await;
|
||||||
self.child_view = view;
|
self.child_view = view;
|
||||||
@ -189,7 +188,7 @@ pub async fn read_workspace(sdk: &FlowyCoreTest, workspace_id: Option<String>) -
|
|||||||
value: workspace_id,
|
value: workspace_id,
|
||||||
};
|
};
|
||||||
let repeated_workspace = EventBuilder::new(sdk.clone())
|
let repeated_workspace = EventBuilder::new(sdk.clone())
|
||||||
.event(ReadWorkspaces)
|
.event(ReadAllWorkspaces)
|
||||||
.payload(request.clone())
|
.payload(request.clone())
|
||||||
.async_send()
|
.async_send()
|
||||||
.await
|
.await
|
||||||
@ -256,7 +255,7 @@ pub async fn create_view(
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn read_view(sdk: &FlowyCoreTest, view_id: &str) -> ViewPB {
|
pub async fn read_view(sdk: &FlowyCoreTest, view_id: &str) -> ViewPB {
|
||||||
let view_id: ViewIdPB = view_id.into();
|
let view_id = ViewIdPB::from(view_id);
|
||||||
EventBuilder::new(sdk.clone())
|
EventBuilder::new(sdk.clone())
|
||||||
.event(ReadView)
|
.event(ReadView)
|
||||||
.payload(view_id)
|
.payload(view_id)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::user::supabase_test::helper::get_supabase_config;
|
use crate::user::supabase_test::helper::get_supabase_config;
|
||||||
use flowy_folder2::entities::WorkspaceSettingPB;
|
use flowy_folder2::entities::WorkspaceSettingPB;
|
||||||
use flowy_folder2::event_map::FolderEvent::ReadCurrentWorkspace;
|
use flowy_folder2::event_map::FolderEvent::GetCurrentWorkspace;
|
||||||
|
|
||||||
use flowy_test::{event_builder::EventBuilder, FlowyCoreTest};
|
use flowy_test::{event_builder::EventBuilder, FlowyCoreTest};
|
||||||
use flowy_user::entities::{AuthTypePB, ThirdPartyAuthPB, UserProfilePB};
|
use flowy_user::entities::{AuthTypePB, ThirdPartyAuthPB, UserProfilePB};
|
||||||
@ -27,7 +27,7 @@ async fn initial_workspace_test() {
|
|||||||
.parse::<UserProfilePB>();
|
.parse::<UserProfilePB>();
|
||||||
|
|
||||||
let workspace_settings = EventBuilder::new(test.clone())
|
let workspace_settings = EventBuilder::new(test.clone())
|
||||||
.event(ReadCurrentWorkspace)
|
.event(GetCurrentWorkspace)
|
||||||
.async_send()
|
.async_send()
|
||||||
.await
|
.await
|
||||||
.parse::<WorkspaceSettingPB>();
|
.parse::<WorkspaceSettingPB>();
|
||||||
|
@ -1,8 +1,14 @@
|
|||||||
[tasks.appflowy-flutter-deps-tools]
|
[tasks.appflowy-flutter-deps-tools]
|
||||||
run_task = { name = ["install_flutter_prerequests","install_diesel"] }
|
run_task = { name = ["install_flutter_prerequests"] }
|
||||||
|
|
||||||
[tasks.appflowy-tauri-deps-tools]
|
[tasks.appflowy-tauri-deps-tools]
|
||||||
run_task = { name = ["install_tauri_prerequests","install_diesel"] }
|
run_task = { name = ["install_tauri_prerequests"] }
|
||||||
|
|
||||||
|
[tasks.appflowy-flutter-dev-tools]
|
||||||
|
run_task = { name = ["appflowy-flutter-deps-tools","install_diesel"] }
|
||||||
|
|
||||||
|
[tasks.appflowy-tauri-dev-tools]
|
||||||
|
run_task = { name = ["appflowy-tauri-deps-tools","install_diesel"] }
|
||||||
|
|
||||||
[tasks.install_windows_deps.windows]
|
[tasks.install_windows_deps.windows]
|
||||||
dependencies=["check_duckscript_installation", "check_visual_studio_installation", "check_vcpkg", "install_vcpkg_sqlite", "install_rust_vcpkg_cli"]
|
dependencies=["check_duckscript_installation", "check_visual_studio_installation", "check_vcpkg", "install_vcpkg_sqlite", "install_rust_vcpkg_cli"]
|
||||||
@ -78,9 +84,9 @@ dependencies = ["check_vcpkg"]
|
|||||||
|
|
||||||
[tasks.install_targets.mac]
|
[tasks.install_targets.mac]
|
||||||
script = """
|
script = """
|
||||||
rustup target add x86_64-apple-ios
|
#rustup target add x86_64-apple-ios
|
||||||
rustup target add x86_64-apple-darwin
|
#rustup target add x86_64-apple-darwin
|
||||||
rustup target add aarch64-apple-ios
|
#rustup target add aarch64-apple-ios
|
||||||
rustup target add aarch64-apple-darwin
|
rustup target add aarch64-apple-darwin
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user