mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
docs: update code documentation (#1804)
* docs: update code documentation * chore: fix bloc test * chore: reduce lock granularity * chore: fix bloc test
This commit is contained in:
2
frontend/.vscode/tasks.json
vendored
2
frontend/.vscode/tasks.json
vendored
@ -58,7 +58,7 @@
|
|||||||
"label": "AF: Build Appflowy Core",
|
"label": "AF: Build Appflowy Core",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
"windows": {
|
"windows": {
|
||||||
"command": "cargo make --profile development-windows appflowy-core-dev"
|
"command": "cargo make --profile development-windows-x86 appflowy-core-dev"
|
||||||
},
|
},
|
||||||
"linux": {
|
"linux": {
|
||||||
"command": "cargo make --profile \"development-linux-$(uname -m)\" appflowy-core-dev"
|
"command": "cargo make --profile \"development-linux-$(uname -m)\" appflowy-core-dev"
|
||||||
|
@ -34,7 +34,7 @@ class DocumentPluginBuilder extends PluginBuilder {
|
|||||||
PluginType get pluginType => PluginType.editor;
|
PluginType get pluginType => PluginType.editor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ViewDataFormatPB get dataFormatType => ViewDataFormatPB.TreeFormat;
|
ViewDataFormatPB get dataFormatType => ViewDataFormatPB.NodeFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
class DocumentPlugin extends Plugin<int> {
|
class DocumentPlugin extends Plugin<int> {
|
||||||
|
@ -147,8 +147,10 @@ class SelectOptionCellEditorBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _filterOption(String optionName, Emitter<SelectOptionEditorState> emit) {
|
void _filterOption(String optionName, Emitter<SelectOptionEditorState> emit) {
|
||||||
final _MakeOptionResult result =
|
final _MakeOptionResult result = _makeOptions(
|
||||||
_makeOptions(Some(optionName), state.allOptions);
|
Some(optionName),
|
||||||
|
state.allOptions,
|
||||||
|
);
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
filter: Some(optionName),
|
filter: Some(optionName),
|
||||||
options: result.options,
|
options: result.options,
|
||||||
@ -159,6 +161,7 @@ class SelectOptionCellEditorBloc
|
|||||||
Future<void> _loadOptions() async {
|
Future<void> _loadOptions() async {
|
||||||
final result = await _selectOptionService.getOptionContext();
|
final result = await _selectOptionService.getOptionContext();
|
||||||
if (isClosed) {
|
if (isClosed) {
|
||||||
|
Log.warn("Unexpected closing the bloc");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -177,7 +180,9 @@ class SelectOptionCellEditorBloc
|
|||||||
}
|
}
|
||||||
|
|
||||||
_MakeOptionResult _makeOptions(
|
_MakeOptionResult _makeOptions(
|
||||||
Option<String> filter, List<SelectOptionPB> allOptions) {
|
Option<String> filter,
|
||||||
|
List<SelectOptionPB> allOptions,
|
||||||
|
) {
|
||||||
final List<SelectOptionPB> options = List.from(allOptions);
|
final List<SelectOptionPB> options = List.from(allOptions);
|
||||||
Option<String> createOption = filter;
|
Option<String> createOption = filter;
|
||||||
|
|
||||||
|
@ -12,7 +12,7 @@ import 'type_option_context.dart';
|
|||||||
class TypeOptionDataController {
|
class TypeOptionDataController {
|
||||||
final String databaseId;
|
final String databaseId;
|
||||||
final IFieldTypeOptionLoader loader;
|
final IFieldTypeOptionLoader loader;
|
||||||
late TypeOptionPB _data;
|
late TypeOptionPB _typeOptiondata;
|
||||||
final PublishNotifier<FieldPB> _fieldNotifier = PublishNotifier();
|
final PublishNotifier<FieldPB> _fieldNotifier = PublishNotifier();
|
||||||
|
|
||||||
/// Returns a [TypeOptionDataController] used to modify the specified
|
/// Returns a [TypeOptionDataController] used to modify the specified
|
||||||
@ -27,7 +27,7 @@ class TypeOptionDataController {
|
|||||||
FieldInfo? fieldInfo,
|
FieldInfo? fieldInfo,
|
||||||
}) {
|
}) {
|
||||||
if (fieldInfo != null) {
|
if (fieldInfo != null) {
|
||||||
_data = TypeOptionPB.create()
|
_typeOptiondata = TypeOptionPB.create()
|
||||||
..databaseId = databaseId
|
..databaseId = databaseId
|
||||||
..field_2 = fieldInfo.field;
|
..field_2 = fieldInfo.field;
|
||||||
}
|
}
|
||||||
@ -38,7 +38,7 @@ class TypeOptionDataController {
|
|||||||
return result.fold(
|
return result.fold(
|
||||||
(data) {
|
(data) {
|
||||||
data.freeze();
|
data.freeze();
|
||||||
_data = data;
|
_typeOptiondata = data;
|
||||||
_fieldNotifier.value = data.field_2;
|
_fieldNotifier.value = data.field_2;
|
||||||
return left(data);
|
return left(data);
|
||||||
},
|
},
|
||||||
@ -50,28 +50,28 @@ class TypeOptionDataController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
FieldPB get field {
|
FieldPB get field {
|
||||||
return _data.field_2;
|
return _typeOptiondata.field_2;
|
||||||
}
|
}
|
||||||
|
|
||||||
T getTypeOption<T>(TypeOptionDataParser<T> parser) {
|
T getTypeOption<T>(TypeOptionDataParser<T> parser) {
|
||||||
return parser.fromBuffer(_data.typeOptionData);
|
return parser.fromBuffer(_typeOptiondata.typeOptionData);
|
||||||
}
|
}
|
||||||
|
|
||||||
set fieldName(String name) {
|
set fieldName(String name) {
|
||||||
_data = _data.rebuild((rebuildData) {
|
_typeOptiondata = _typeOptiondata.rebuild((rebuildData) {
|
||||||
rebuildData.field_2 = rebuildData.field_2.rebuild((rebuildField) {
|
rebuildData.field_2 = rebuildData.field_2.rebuild((rebuildField) {
|
||||||
rebuildField.name = name;
|
rebuildField.name = name;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
_fieldNotifier.value = _data.field_2;
|
_fieldNotifier.value = _typeOptiondata.field_2;
|
||||||
|
|
||||||
FieldService(databaseId: databaseId, fieldId: field.id)
|
FieldService(databaseId: databaseId, fieldId: field.id)
|
||||||
.updateField(name: name);
|
.updateField(name: name);
|
||||||
}
|
}
|
||||||
|
|
||||||
set typeOptionData(List<int> typeOptionData) {
|
set typeOptionData(List<int> typeOptionData) {
|
||||||
_data = _data.rebuild((rebuildData) {
|
_typeOptiondata = _typeOptiondata.rebuild((rebuildData) {
|
||||||
if (typeOptionData.isNotEmpty) {
|
if (typeOptionData.isNotEmpty) {
|
||||||
rebuildData.typeOptionData = typeOptionData;
|
rebuildData.typeOptionData = typeOptionData;
|
||||||
}
|
}
|
||||||
|
@ -52,7 +52,7 @@ abstract class PluginBuilder {
|
|||||||
|
|
||||||
PluginType get pluginType;
|
PluginType get pluginType;
|
||||||
|
|
||||||
ViewDataFormatPB get dataFormatType => ViewDataFormatPB.TreeFormat;
|
ViewDataFormatPB get dataFormatType => ViewDataFormatPB.NodeFormat;
|
||||||
|
|
||||||
ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Document;
|
ViewLayoutTypePB? get layoutType => ViewLayoutTypePB.Document;
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ class AppService {
|
|||||||
..to = toIndex
|
..to = toIndex
|
||||||
..ty = MoveFolderItemType.MoveView;
|
..ty = MoveFolderItemType.MoveView;
|
||||||
|
|
||||||
return FolderEventMoveFolderItem(payload).send();
|
return FolderEventMoveItem(payload).send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<Tuple2<AppPB, List<ViewPB>>>> fetchViews(
|
Future<List<Tuple2<AppPB, List<ViewPB>>>> fetchViews(
|
||||||
|
@ -65,6 +65,6 @@ class WorkspaceService {
|
|||||||
..to = toIndex
|
..to = toIndex
|
||||||
..ty = MoveFolderItemType.MoveApp;
|
..ty = MoveFolderItemType.MoveApp;
|
||||||
|
|
||||||
return FolderEventMoveFolderItem(payload).send();
|
return FolderEventMoveItem(payload).send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,7 @@ void main() {
|
|||||||
final gridGroupBloc = GridGroupBloc(
|
final gridGroupBloc = GridGroupBloc(
|
||||||
viewId: context.gridView.id,
|
viewId: context.gridView.id,
|
||||||
fieldController: context.fieldController,
|
fieldController: context.fieldController,
|
||||||
);
|
)..add(const GridGroupEvent.initial());
|
||||||
gridGroupBloc.add(GridGroupEvent.setGroupByField(
|
gridGroupBloc.add(GridGroupEvent.setGroupByField(
|
||||||
checkboxField.id,
|
checkboxField.id,
|
||||||
checkboxField.fieldType,
|
checkboxField.fieldType,
|
||||||
|
@ -14,7 +14,7 @@ void main() {
|
|||||||
boardTest = await AppFlowyBoardTest.ensureInitialized();
|
boardTest = await AppFlowyBoardTest.ensureInitialized();
|
||||||
});
|
});
|
||||||
|
|
||||||
test('group by multi select with no options test', () async {
|
test('no status group name test', () async {
|
||||||
final context = await boardTest.createTestBoard();
|
final context = await boardTest.createTestBoard();
|
||||||
|
|
||||||
// create multi-select field
|
// create multi-select field
|
||||||
@ -27,7 +27,9 @@ void main() {
|
|||||||
final gridGroupBloc = GridGroupBloc(
|
final gridGroupBloc = GridGroupBloc(
|
||||||
viewId: context.gridView.id,
|
viewId: context.gridView.id,
|
||||||
fieldController: context.fieldController,
|
fieldController: context.fieldController,
|
||||||
);
|
)..add(const GridGroupEvent.initial());
|
||||||
|
await boardResponseFuture();
|
||||||
|
|
||||||
gridGroupBloc.add(GridGroupEvent.setGroupByField(
|
gridGroupBloc.add(GridGroupEvent.setGroupByField(
|
||||||
multiSelectField.id,
|
multiSelectField.id,
|
||||||
multiSelectField.fieldType,
|
multiSelectField.fieldType,
|
||||||
@ -72,7 +74,9 @@ void main() {
|
|||||||
final gridGroupBloc = GridGroupBloc(
|
final gridGroupBloc = GridGroupBloc(
|
||||||
viewId: context.gridView.id,
|
viewId: context.gridView.id,
|
||||||
fieldController: context.fieldController,
|
fieldController: context.fieldController,
|
||||||
);
|
)..add(const GridGroupEvent.initial());
|
||||||
|
await boardResponseFuture();
|
||||||
|
|
||||||
gridGroupBloc.add(GridGroupEvent.setGroupByField(
|
gridGroupBloc.add(GridGroupEvent.setGroupByField(
|
||||||
multiSelectField.id,
|
multiSelectField.id,
|
||||||
multiSelectField.fieldType,
|
multiSelectField.fieldType,
|
||||||
|
@ -64,15 +64,24 @@ void main() {
|
|||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.newOption("A"));
|
bloc.add(const SelectOptionEditorEvent.newOption("A"));
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
assert(bloc.state.options.length == 1,
|
||||||
|
"Expect 1 but receive ${bloc.state.options.length}, Options: ${bloc.state.options}");
|
||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.newOption("B"));
|
bloc.add(const SelectOptionEditorEvent.newOption("B"));
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
assert(bloc.state.options.length == 2,
|
||||||
|
"Expect 2 but receive ${bloc.state.options.length}, Options: ${bloc.state.options}");
|
||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.newOption("C"));
|
bloc.add(const SelectOptionEditorEvent.newOption("C"));
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
assert(bloc.state.options.length == 3,
|
||||||
|
"Expect 3 but receive ${bloc.state.options.length}. Options: ${bloc.state.options}");
|
||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.deleteAllOptions());
|
bloc.add(const SelectOptionEditorEvent.deleteAllOptions());
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
|
||||||
assert(bloc.state.options.isEmpty);
|
assert(bloc.state.options.isEmpty,
|
||||||
|
"Expect empty but receive ${bloc.state.options.length}");
|
||||||
});
|
});
|
||||||
|
|
||||||
test('select/unselect option', () async {
|
test('select/unselect option', () async {
|
||||||
@ -161,18 +170,41 @@ void main() {
|
|||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.newOption("abcd"));
|
bloc.add(const SelectOptionEditorEvent.newOption("abcd"));
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
expect(
|
||||||
|
bloc.state.options.length,
|
||||||
|
1,
|
||||||
|
reason: "Options: ${bloc.state.options}",
|
||||||
|
);
|
||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.newOption("aaaa"));
|
bloc.add(const SelectOptionEditorEvent.newOption("aaaa"));
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
expect(
|
||||||
|
bloc.state.options.length,
|
||||||
|
2,
|
||||||
|
reason: "Options: ${bloc.state.options}",
|
||||||
|
);
|
||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.newOption("defg"));
|
bloc.add(const SelectOptionEditorEvent.newOption("defg"));
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
expect(
|
||||||
|
bloc.state.options.length,
|
||||||
|
3,
|
||||||
|
reason: "Options: ${bloc.state.options}",
|
||||||
|
);
|
||||||
|
|
||||||
bloc.add(const SelectOptionEditorEvent.filterOption("a"));
|
bloc.add(const SelectOptionEditorEvent.filterOption("a"));
|
||||||
await gridResponseFuture();
|
await gridResponseFuture();
|
||||||
|
|
||||||
expect(bloc.state.options.length, 2);
|
expect(
|
||||||
expect(bloc.state.allOptions.length, 3);
|
bloc.state.options.length,
|
||||||
|
2,
|
||||||
|
reason: "Options: ${bloc.state.options}",
|
||||||
|
);
|
||||||
|
expect(
|
||||||
|
bloc.state.allOptions.length,
|
||||||
|
3,
|
||||||
|
reason: "Options: ${bloc.state.options}",
|
||||||
|
);
|
||||||
expect(bloc.state.createOption, const Some("a"));
|
expect(bloc.state.createOption, const Some("a"));
|
||||||
expect(bloc.state.filter, const Some("a"));
|
expect(bloc.state.filter, const Some("a"));
|
||||||
});
|
});
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_context.dart';
|
||||||
import 'package:app_flowy/plugins/grid/application/prelude.dart';
|
import 'package:app_flowy/plugins/grid/application/prelude.dart';
|
||||||
import 'package:bloc_test/bloc_test.dart';
|
|
||||||
import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
|
import 'package:appflowy_backend/protobuf/flowy-database/field_entities.pb.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import '../util.dart';
|
import '../util.dart';
|
||||||
@ -28,75 +27,69 @@ void main() {
|
|||||||
gridTest = await AppFlowyGridTest.ensureInitialized();
|
gridTest = await AppFlowyGridTest.ensureInitialized();
|
||||||
});
|
});
|
||||||
|
|
||||||
group('$FieldEditorBloc', () {
|
test('rename field', () async {
|
||||||
late FieldEditorBloc editorBloc;
|
final editorBloc = await makeEditorBloc(gridTest);
|
||||||
|
editorBloc.add(const FieldEditorEvent.updateName('Hello world'));
|
||||||
|
await gridResponseFuture();
|
||||||
|
|
||||||
setUp(() async {
|
editorBloc.state.field.fold(
|
||||||
final context = await gridTest.createTestGrid();
|
() => throw Exception("The field should not be none"),
|
||||||
final fieldInfo = context.singleSelectFieldContext();
|
(field) {
|
||||||
final loader = FieldTypeOptionLoader(
|
assert(field.name == 'Hello world');
|
||||||
databaseId: context.gridView.id,
|
|
||||||
field: fieldInfo.field,
|
|
||||||
);
|
|
||||||
|
|
||||||
editorBloc = FieldEditorBloc(
|
|
||||||
databaseId: context.gridView.id,
|
|
||||||
fieldName: fieldInfo.name,
|
|
||||||
isGroupField: fieldInfo.isGroupField,
|
|
||||||
loader: loader,
|
|
||||||
)..add(const FieldEditorEvent.initial());
|
|
||||||
|
|
||||||
await gridResponseFuture();
|
|
||||||
});
|
|
||||||
|
|
||||||
blocTest<FieldEditorBloc, FieldEditorState>(
|
|
||||||
"rename field",
|
|
||||||
build: () => editorBloc,
|
|
||||||
act: (bloc) async {
|
|
||||||
editorBloc.add(const FieldEditorEvent.updateName('Hello world'));
|
|
||||||
},
|
|
||||||
wait: gridResponseDuration(),
|
|
||||||
verify: (bloc) {
|
|
||||||
bloc.state.field.fold(
|
|
||||||
() => throw Exception("The field should not be none"),
|
|
||||||
(field) {
|
|
||||||
assert(field.name == 'Hello world');
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
blocTest<FieldEditorBloc, FieldEditorState>(
|
test('switch to text field', () async {
|
||||||
"switch to text field",
|
final editorBloc = await makeEditorBloc(gridTest);
|
||||||
build: () => editorBloc,
|
|
||||||
act: (bloc) async {
|
editorBloc.add(const FieldEditorEvent.switchToField(FieldType.RichText));
|
||||||
editorBloc
|
await gridResponseFuture();
|
||||||
.add(const FieldEditorEvent.switchToField(FieldType.RichText));
|
|
||||||
},
|
editorBloc.state.field.fold(
|
||||||
wait: gridResponseDuration(),
|
() => throw Exception("The field should not be none"),
|
||||||
verify: (bloc) {
|
(field) {
|
||||||
bloc.state.field.fold(
|
// The default length of the fields is 3. The length of the fields
|
||||||
() => throw Exception("The field should not be none"),
|
// should not change after switching to other field type
|
||||||
(field) {
|
// assert(gridTest.fieldContexts.length == 3);
|
||||||
// The default length of the fields is 3. The length of the fields
|
assert(field.fieldType == FieldType.RichText);
|
||||||
// should not change after switching to other field type
|
|
||||||
// assert(gridTest.fieldContexts.length == 3);
|
|
||||||
assert(field.fieldType == FieldType.RichText);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
});
|
||||||
|
|
||||||
blocTest<FieldEditorBloc, FieldEditorState>(
|
test('delete field', () async {
|
||||||
"delete field",
|
final editorBloc = await makeEditorBloc(gridTest);
|
||||||
build: () => editorBloc,
|
editorBloc.add(const FieldEditorEvent.switchToField(FieldType.RichText));
|
||||||
act: (bloc) async {
|
await gridResponseFuture();
|
||||||
editorBloc.add(const FieldEditorEvent.deleteField());
|
|
||||||
},
|
editorBloc.state.field.fold(
|
||||||
wait: gridResponseDuration(),
|
() => throw Exception("The field should not be none"),
|
||||||
verify: (bloc) {
|
(field) {
|
||||||
// assert(gridTest.fieldContexts.length == 2);
|
// The default length of the fields is 3. The length of the fields
|
||||||
|
// should not change after switching to other field type
|
||||||
|
// assert(gridTest.fieldContexts.length == 3);
|
||||||
|
assert(field.fieldType == FieldType.RichText);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<FieldEditorBloc> makeEditorBloc(AppFlowyGridTest gridTest) async {
|
||||||
|
final context = await gridTest.createTestGrid();
|
||||||
|
final fieldInfo = context.singleSelectFieldContext();
|
||||||
|
final loader = FieldTypeOptionLoader(
|
||||||
|
databaseId: context.gridView.id,
|
||||||
|
field: fieldInfo.field,
|
||||||
|
);
|
||||||
|
|
||||||
|
final editorBloc = FieldEditorBloc(
|
||||||
|
databaseId: context.gridView.id,
|
||||||
|
fieldName: fieldInfo.name,
|
||||||
|
isGroupField: fieldInfo.isGroupField,
|
||||||
|
loader: loader,
|
||||||
|
)..add(const FieldEditorEvent.initial());
|
||||||
|
|
||||||
|
await gridResponseFuture();
|
||||||
|
|
||||||
|
return editorBloc;
|
||||||
|
}
|
||||||
|
@ -210,7 +210,7 @@ class AppFlowyGridCellTest {
|
|||||||
|
|
||||||
Future<GridSelectOptionCellController> makeSelectOptionCellController(
|
Future<GridSelectOptionCellController> makeSelectOptionCellController(
|
||||||
FieldType fieldType, int rowIndex) async {
|
FieldType fieldType, int rowIndex) async {
|
||||||
return context.makeSelectOptionCellController(fieldType, rowIndex);
|
return await context.makeSelectOptionCellController(fieldType, rowIndex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ void main() {
|
|||||||
viewBloc.add(const ViewEvent.duplicate());
|
viewBloc.add(const ViewEvent.duplicate());
|
||||||
await blocResponseFuture();
|
await blocResponseFuture();
|
||||||
|
|
||||||
assert(appBloc.state.views.length == 2);
|
expect(appBloc.state.views.length, 2);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('delete view test', () async {
|
test('delete view test', () async {
|
||||||
@ -59,7 +59,7 @@ void main() {
|
|||||||
DocumentPluginBuilder(),
|
DocumentPluginBuilder(),
|
||||||
));
|
));
|
||||||
await blocResponseFuture();
|
await blocResponseFuture();
|
||||||
assert(appBloc.state.views.length == 1);
|
expect(appBloc.state.views.length, 1);
|
||||||
|
|
||||||
final viewBloc = ViewBloc(view: appBloc.state.views.first)
|
final viewBloc = ViewBloc(view: appBloc.state.views.first)
|
||||||
..add(const ViewEvent.initial());
|
..add(const ViewEvent.initial());
|
||||||
|
@ -211,7 +211,7 @@ impl ViewDataProcessor for DocumentViewDataProcessor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn data_types(&self) -> Vec<ViewDataFormatPB> {
|
fn data_types(&self) -> Vec<ViewDataFormatPB> {
|
||||||
vec![ViewDataFormatPB::DeltaFormat, ViewDataFormatPB::TreeFormat]
|
vec![ViewDataFormatPB::DeltaFormat, ViewDataFormatPB::NodeFormat]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -297,7 +297,7 @@ impl UserStatusListener {
|
|||||||
async fn did_sign_up(&self, user_profile: &UserProfile) -> FlowyResult<()> {
|
async fn did_sign_up(&self, user_profile: &UserProfile) -> FlowyResult<()> {
|
||||||
let view_data_type = match self.config.document.version {
|
let view_data_type = match self.config.document.version {
|
||||||
DocumentVersionPB::V0 => ViewDataFormatPB::DeltaFormat,
|
DocumentVersionPB::V0 => ViewDataFormatPB::DeltaFormat,
|
||||||
DocumentVersionPB::V1 => ViewDataFormatPB::TreeFormat,
|
DocumentVersionPB::V1 => ViewDataFormatPB::NodeFormat,
|
||||||
};
|
};
|
||||||
self.folder_manager
|
self.folder_manager
|
||||||
.initialize_with_new_user(&user_profile.id, &user_profile.token, view_data_type)
|
.initialize_with_new_user(&user_profile.id, &user_profile.token, view_data_type)
|
||||||
|
@ -5,6 +5,7 @@ use crate::services::field::*;
|
|||||||
use crate::services::filter::{FilterChangeset, FilterResult, FilterResultNotification, FilterType};
|
use crate::services::filter::{FilterChangeset, FilterResult, FilterResultNotification, FilterType};
|
||||||
use crate::services::row::DatabaseBlockRowRevision;
|
use crate::services::row::DatabaseBlockRowRevision;
|
||||||
use crate::services::view_editor::{GridViewChanged, GridViewChangedNotifier};
|
use crate::services::view_editor::{GridViewChanged, GridViewChangedNotifier};
|
||||||
|
use dashmap::DashMap;
|
||||||
use flowy_error::FlowyResult;
|
use flowy_error::FlowyResult;
|
||||||
use flowy_task::{QualityOfService, Task, TaskContent, TaskDispatcher};
|
use flowy_task::{QualityOfService, Task, TaskContent, TaskDispatcher};
|
||||||
use grid_model::{CellRevision, FieldId, FieldRevision, FilterRevision, RowRevision};
|
use grid_model::{CellRevision, FieldId, FieldRevision, FilterRevision, RowRevision};
|
||||||
@ -34,7 +35,7 @@ pub struct FilterController {
|
|||||||
view_id: String,
|
view_id: String,
|
||||||
handler_id: String,
|
handler_id: String,
|
||||||
delegate: Box<dyn FilterDelegate>,
|
delegate: Box<dyn FilterDelegate>,
|
||||||
result_by_row_id: HashMap<RowId, FilterResult>,
|
result_by_row_id: DashMap<RowId, FilterResult>,
|
||||||
cell_data_cache: AtomicCellDataCache,
|
cell_data_cache: AtomicCellDataCache,
|
||||||
cell_filter_cache: AtomicCellFilterCache,
|
cell_filter_cache: AtomicCellFilterCache,
|
||||||
task_scheduler: Arc<RwLock<TaskDispatcher>>,
|
task_scheduler: Arc<RwLock<TaskDispatcher>>,
|
||||||
@ -54,11 +55,11 @@ impl FilterController {
|
|||||||
where
|
where
|
||||||
T: FilterDelegate + 'static,
|
T: FilterDelegate + 'static,
|
||||||
{
|
{
|
||||||
let mut this = Self {
|
let this = Self {
|
||||||
view_id: view_id.to_string(),
|
view_id: view_id.to_string(),
|
||||||
handler_id: handler_id.to_string(),
|
handler_id: handler_id.to_string(),
|
||||||
delegate: Box::new(delegate),
|
delegate: Box::new(delegate),
|
||||||
result_by_row_id: HashMap::default(),
|
result_by_row_id: DashMap::default(),
|
||||||
cell_data_cache,
|
cell_data_cache,
|
||||||
cell_filter_cache: AnyTypeCache::<FilterType>::new(),
|
cell_filter_cache: AnyTypeCache::<FilterType>::new(),
|
||||||
task_scheduler,
|
task_scheduler,
|
||||||
@ -83,7 +84,7 @@ impl FilterController {
|
|||||||
self.task_scheduler.write().await.add_task(task);
|
self.task_scheduler.write().await.add_task(task);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn filter_row_revs(&mut self, row_revs: &mut Vec<Arc<RowRevision>>) {
|
pub async fn filter_row_revs(&self, row_revs: &mut Vec<Arc<RowRevision>>) {
|
||||||
if self.cell_filter_cache.read().is_empty() {
|
if self.cell_filter_cache.read().is_empty() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -91,7 +92,7 @@ impl FilterController {
|
|||||||
row_revs.iter().for_each(|row_rev| {
|
row_revs.iter().for_each(|row_rev| {
|
||||||
let _ = filter_row(
|
let _ = filter_row(
|
||||||
row_rev,
|
row_rev,
|
||||||
&mut self.result_by_row_id,
|
&self.result_by_row_id,
|
||||||
&field_rev_by_field_id,
|
&field_rev_by_field_id,
|
||||||
&self.cell_data_cache,
|
&self.cell_data_cache,
|
||||||
&self.cell_filter_cache,
|
&self.cell_filter_cache,
|
||||||
@ -116,7 +117,7 @@ impl FilterController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(name = "process_filter_task", level = "trace", skip_all, fields(filter_result), err)]
|
#[tracing::instrument(name = "process_filter_task", level = "trace", skip_all, fields(filter_result), err)]
|
||||||
pub async fn process(&mut self, predicate: &str) -> FlowyResult<()> {
|
pub async fn process(&self, predicate: &str) -> FlowyResult<()> {
|
||||||
let event_type = FilterEvent::from_str(predicate).unwrap();
|
let event_type = FilterEvent::from_str(predicate).unwrap();
|
||||||
match event_type {
|
match event_type {
|
||||||
FilterEvent::FilterDidChanged => self.filter_all_rows().await?,
|
FilterEvent::FilterDidChanged => self.filter_all_rows().await?,
|
||||||
@ -125,13 +126,13 @@ impl FilterController {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn filter_row(&mut self, row_id: String) -> FlowyResult<()> {
|
async fn filter_row(&self, row_id: String) -> FlowyResult<()> {
|
||||||
if let Some((_, row_rev)) = self.delegate.get_row_rev(&row_id).await {
|
if let Some((_, row_rev)) = self.delegate.get_row_rev(&row_id).await {
|
||||||
let field_rev_by_field_id = self.get_filter_revs_map().await;
|
let field_rev_by_field_id = self.get_filter_revs_map().await;
|
||||||
let mut notification = FilterResultNotification::new(self.view_id.clone(), row_rev.block_id.clone());
|
let mut notification = FilterResultNotification::new(self.view_id.clone(), row_rev.block_id.clone());
|
||||||
if let Some((row_id, is_visible)) = filter_row(
|
if let Some((row_id, is_visible)) = filter_row(
|
||||||
&row_rev,
|
&row_rev,
|
||||||
&mut self.result_by_row_id,
|
&self.result_by_row_id,
|
||||||
&field_rev_by_field_id,
|
&field_rev_by_field_id,
|
||||||
&self.cell_data_cache,
|
&self.cell_data_cache,
|
||||||
&self.cell_filter_cache,
|
&self.cell_filter_cache,
|
||||||
@ -153,7 +154,7 @@ impl FilterController {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn filter_all_rows(&mut self) -> FlowyResult<()> {
|
async fn filter_all_rows(&self) -> FlowyResult<()> {
|
||||||
let field_rev_by_field_id = self.get_filter_revs_map().await;
|
let field_rev_by_field_id = self.get_filter_revs_map().await;
|
||||||
for block in self.delegate.get_blocks().await.into_iter() {
|
for block in self.delegate.get_blocks().await.into_iter() {
|
||||||
// The row_ids contains the row that its visibility was changed.
|
// The row_ids contains the row that its visibility was changed.
|
||||||
@ -163,7 +164,7 @@ impl FilterController {
|
|||||||
for (index, row_rev) in block.row_revs.iter().enumerate() {
|
for (index, row_rev) in block.row_revs.iter().enumerate() {
|
||||||
if let Some((row_id, is_visible)) = filter_row(
|
if let Some((row_id, is_visible)) = filter_row(
|
||||||
row_rev,
|
row_rev,
|
||||||
&mut self.result_by_row_id,
|
&self.result_by_row_id,
|
||||||
&field_rev_by_field_id,
|
&field_rev_by_field_id,
|
||||||
&self.cell_data_cache,
|
&self.cell_data_cache,
|
||||||
&self.cell_filter_cache,
|
&self.cell_filter_cache,
|
||||||
@ -198,7 +199,7 @@ impl FilterController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip(self))]
|
#[tracing::instrument(level = "trace", skip(self))]
|
||||||
pub async fn did_receive_changes(&mut self, changeset: FilterChangeset) -> Option<FilterChangesetNotificationPB> {
|
pub async fn did_receive_changes(&self, changeset: FilterChangeset) -> Option<FilterChangesetNotificationPB> {
|
||||||
let mut notification: Option<FilterChangesetNotificationPB> = None;
|
let mut notification: Option<FilterChangesetNotificationPB> = None;
|
||||||
if let Some(filter_type) = &changeset.insert_filter {
|
if let Some(filter_type) = &changeset.insert_filter {
|
||||||
if let Some(filter) = self.filter_from_filter_type(filter_type).await {
|
if let Some(filter) = self.filter_from_filter_type(filter_type).await {
|
||||||
@ -258,7 +259,7 @@ impl FilterController {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all)]
|
#[tracing::instrument(level = "trace", skip_all)]
|
||||||
async fn refresh_filters(&mut self, filter_revs: Vec<Arc<FilterRevision>>) {
|
async fn refresh_filters(&self, filter_revs: Vec<Arc<FilterRevision>>) {
|
||||||
for filter_rev in filter_revs {
|
for filter_rev in filter_revs {
|
||||||
if let Some(field_rev) = self.delegate.get_field_rev(&filter_rev.field_id).await {
|
if let Some(field_rev) = self.delegate.get_field_rev(&filter_rev.field_id).await {
|
||||||
let filter_type = FilterType::from(&field_rev);
|
let filter_type = FilterType::from(&field_rev);
|
||||||
@ -309,13 +310,13 @@ impl FilterController {
|
|||||||
#[tracing::instrument(level = "trace", skip_all)]
|
#[tracing::instrument(level = "trace", skip_all)]
|
||||||
fn filter_row(
|
fn filter_row(
|
||||||
row_rev: &Arc<RowRevision>,
|
row_rev: &Arc<RowRevision>,
|
||||||
result_by_row_id: &mut HashMap<RowId, FilterResult>,
|
result_by_row_id: &DashMap<RowId, FilterResult>,
|
||||||
field_rev_by_field_id: &HashMap<FieldId, Arc<FieldRevision>>,
|
field_rev_by_field_id: &HashMap<FieldId, Arc<FieldRevision>>,
|
||||||
cell_data_cache: &AtomicCellDataCache,
|
cell_data_cache: &AtomicCellDataCache,
|
||||||
cell_filter_cache: &AtomicCellFilterCache,
|
cell_filter_cache: &AtomicCellFilterCache,
|
||||||
) -> Option<(String, bool)> {
|
) -> Option<(String, bool)> {
|
||||||
// Create a filter result cache if it's not exist
|
// Create a filter result cache if it's not exist
|
||||||
let filter_result = result_by_row_id
|
let mut filter_result = result_by_row_id
|
||||||
.entry(row_rev.id.clone())
|
.entry(row_rev.id.clone())
|
||||||
.or_insert_with(FilterResult::default);
|
.or_insert_with(FilterResult::default);
|
||||||
let old_is_visible = filter_result.is_visible();
|
let old_is_visible = filter_result.is_visible();
|
||||||
|
@ -3,15 +3,14 @@ use flowy_task::{TaskContent, TaskHandler};
|
|||||||
use lib_infra::future::BoxResultFuture;
|
use lib_infra::future::BoxResultFuture;
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use tokio::sync::RwLock;
|
|
||||||
|
|
||||||
pub struct FilterTaskHandler {
|
pub struct FilterTaskHandler {
|
||||||
handler_id: String,
|
handler_id: String,
|
||||||
filter_controller: Arc<RwLock<FilterController>>,
|
filter_controller: Arc<FilterController>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FilterTaskHandler {
|
impl FilterTaskHandler {
|
||||||
pub fn new(handler_id: String, filter_controller: Arc<RwLock<FilterController>>) -> Self {
|
pub fn new(handler_id: String, filter_controller: Arc<FilterController>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
handler_id,
|
handler_id,
|
||||||
filter_controller,
|
filter_controller,
|
||||||
@ -33,8 +32,6 @@ impl TaskHandler for FilterTaskHandler {
|
|||||||
Box::pin(async move {
|
Box::pin(async move {
|
||||||
if let TaskContent::Text(predicate) = content {
|
if let TaskContent::Text(predicate) = content {
|
||||||
filter_controller
|
filter_controller
|
||||||
.write()
|
|
||||||
.await
|
|
||||||
.process(&predicate)
|
.process(&predicate)
|
||||||
.await
|
.await
|
||||||
.map_err(anyhow::Error::from)?;
|
.map_err(anyhow::Error::from)?;
|
||||||
|
@ -74,7 +74,7 @@ pub struct DatabaseViewRevisionEditor {
|
|||||||
rev_manager: Arc<RevisionManager<Arc<ConnectionPool>>>,
|
rev_manager: Arc<RevisionManager<Arc<ConnectionPool>>>,
|
||||||
delegate: Arc<dyn DatabaseViewEditorDelegate>,
|
delegate: Arc<dyn DatabaseViewEditorDelegate>,
|
||||||
group_controller: Arc<RwLock<Box<dyn GroupController>>>,
|
group_controller: Arc<RwLock<Box<dyn GroupController>>>,
|
||||||
filter_controller: Arc<RwLock<FilterController>>,
|
filter_controller: Arc<FilterController>,
|
||||||
sort_controller: Arc<RwLock<SortController>>,
|
sort_controller: Arc<RwLock<SortController>>,
|
||||||
pub notifier: GridViewChangedNotifier,
|
pub notifier: GridViewChangedNotifier,
|
||||||
}
|
}
|
||||||
@ -156,7 +156,7 @@ impl DatabaseViewRevisionEditor {
|
|||||||
pub async fn close(&self) {
|
pub async fn close(&self) {
|
||||||
self.rev_manager.generate_snapshot().await;
|
self.rev_manager.generate_snapshot().await;
|
||||||
self.rev_manager.close().await;
|
self.rev_manager.close().await;
|
||||||
self.filter_controller.read().await.close().await;
|
self.filter_controller.close().await;
|
||||||
self.sort_controller.read().await.close().await;
|
self.sort_controller.read().await.close().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,7 +194,7 @@ impl DatabaseViewRevisionEditor {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn filter_rows(&self, _block_id: &str, rows: &mut Vec<Arc<RowRevision>>) {
|
pub async fn filter_rows(&self, _block_id: &str, rows: &mut Vec<Arc<RowRevision>>) {
|
||||||
self.filter_controller.write().await.filter_row_revs(rows).await;
|
self.filter_controller.filter_row_revs(rows).await;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn duplicate_view_data(&self) -> FlowyResult<String> {
|
pub async fn duplicate_view_data(&self) -> FlowyResult<String> {
|
||||||
@ -286,7 +286,7 @@ impl DatabaseViewRevisionEditor {
|
|||||||
let sort_controller = self.sort_controller.clone();
|
let sort_controller = self.sort_controller.clone();
|
||||||
let row_id = row_rev.id.clone();
|
let row_id = row_rev.id.clone();
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
filter_controller.read().await.did_receive_row_changed(&row_id).await;
|
filter_controller.did_receive_row_changed(&row_id).await;
|
||||||
sort_controller.read().await.did_receive_row_changed(&row_id).await;
|
sort_controller.read().await.did_receive_row_changed(&row_id).await;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -514,7 +514,7 @@ impl DatabaseViewRevisionEditor {
|
|||||||
condition: params.condition,
|
condition: params.condition,
|
||||||
content: params.content,
|
content: params.content,
|
||||||
};
|
};
|
||||||
let mut filter_controller = self.filter_controller.write().await;
|
let filter_controller = self.filter_controller.clone();
|
||||||
let changeset = if is_exist {
|
let changeset = if is_exist {
|
||||||
let old_filter_type = self
|
let old_filter_type = self
|
||||||
.delegate
|
.delegate
|
||||||
@ -555,8 +555,6 @@ impl DatabaseViewRevisionEditor {
|
|||||||
let filter_type = params.filter_type;
|
let filter_type = params.filter_type;
|
||||||
let changeset = self
|
let changeset = self
|
||||||
.filter_controller
|
.filter_controller
|
||||||
.write()
|
|
||||||
.await
|
|
||||||
.did_receive_changes(FilterChangeset::from_delete(filter_type.clone()))
|
.did_receive_changes(FilterChangeset::from_delete(filter_type.clone()))
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
@ -590,15 +588,14 @@ impl DatabaseViewRevisionEditor {
|
|||||||
.did_update_view_field_type_option(&field_rev)
|
.did_update_view_field_type_option(&field_rev)
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
if let Some(changeset) = self
|
let filter_controller = self.filter_controller.clone();
|
||||||
.filter_controller
|
let _ = tokio::spawn(async move {
|
||||||
.write()
|
if let Some(notification) = filter_controller.did_receive_changes(filter_changeset).await {
|
||||||
.await
|
send_notification(¬ification.view_id, DatabaseNotification::DidUpdateFilter)
|
||||||
.did_receive_changes(filter_changeset)
|
.payload(notification)
|
||||||
.await
|
.send();
|
||||||
{
|
}
|
||||||
self.notify_did_update_filter(changeset).await;
|
});
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
@ -830,7 +827,7 @@ async fn make_filter_controller(
|
|||||||
notifier: GridViewChangedNotifier,
|
notifier: GridViewChangedNotifier,
|
||||||
cell_data_cache: AtomicCellDataCache,
|
cell_data_cache: AtomicCellDataCache,
|
||||||
pad: Arc<RwLock<GridViewRevisionPad>>,
|
pad: Arc<RwLock<GridViewRevisionPad>>,
|
||||||
) -> Arc<RwLock<FilterController>> {
|
) -> Arc<FilterController> {
|
||||||
let field_revs = delegate.get_field_revs(None).await;
|
let field_revs = delegate.get_field_revs(None).await;
|
||||||
let filter_revs = pad.read().await.get_all_filters(&field_revs);
|
let filter_revs = pad.read().await.get_all_filters(&field_revs);
|
||||||
let task_scheduler = delegate.get_task_scheduler();
|
let task_scheduler = delegate.get_task_scheduler();
|
||||||
@ -849,7 +846,7 @@ async fn make_filter_controller(
|
|||||||
notifier,
|
notifier,
|
||||||
)
|
)
|
||||||
.await;
|
.await;
|
||||||
let filter_controller = Arc::new(RwLock::new(filter_controller));
|
let filter_controller = Arc::new(filter_controller);
|
||||||
task_scheduler
|
task_scheduler
|
||||||
.write()
|
.write()
|
||||||
.await
|
.await
|
||||||
@ -861,7 +858,7 @@ async fn make_sort_controller(
|
|||||||
view_id: &str,
|
view_id: &str,
|
||||||
delegate: Arc<dyn DatabaseViewEditorDelegate>,
|
delegate: Arc<dyn DatabaseViewEditorDelegate>,
|
||||||
notifier: GridViewChangedNotifier,
|
notifier: GridViewChangedNotifier,
|
||||||
filter_controller: Arc<RwLock<FilterController>>,
|
filter_controller: Arc<FilterController>,
|
||||||
pad: Arc<RwLock<GridViewRevisionPad>>,
|
pad: Arc<RwLock<GridViewRevisionPad>>,
|
||||||
cell_data_cache: AtomicCellDataCache,
|
cell_data_cache: AtomicCellDataCache,
|
||||||
) -> Arc<RwLock<SortController>> {
|
) -> Arc<RwLock<SortController>> {
|
||||||
|
@ -185,7 +185,7 @@ impl FilterDelegate for GridViewFilterDelegateImpl {
|
|||||||
pub(crate) struct GridViewSortDelegateImpl {
|
pub(crate) struct GridViewSortDelegateImpl {
|
||||||
pub(crate) editor_delegate: Arc<dyn DatabaseViewEditorDelegate>,
|
pub(crate) editor_delegate: Arc<dyn DatabaseViewEditorDelegate>,
|
||||||
pub(crate) view_revision_pad: Arc<RwLock<GridViewRevisionPad>>,
|
pub(crate) view_revision_pad: Arc<RwLock<GridViewRevisionPad>>,
|
||||||
pub(crate) filter_controller: Arc<RwLock<FilterController>>,
|
pub(crate) filter_controller: Arc<FilterController>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl SortDelegate for GridViewSortDelegateImpl {
|
impl SortDelegate for GridViewSortDelegateImpl {
|
||||||
@ -209,7 +209,7 @@ impl SortDelegate for GridViewSortDelegateImpl {
|
|||||||
let editor_delegate = self.editor_delegate.clone();
|
let editor_delegate = self.editor_delegate.clone();
|
||||||
to_fut(async move {
|
to_fut(async move {
|
||||||
let mut row_revs = editor_delegate.get_row_revs(None).await;
|
let mut row_revs = editor_delegate.get_row_revs(None).await;
|
||||||
filter_controller.write().await.filter_row_revs(&mut row_revs).await;
|
filter_controller.filter_row_revs(&mut row_revs).await;
|
||||||
row_revs
|
row_revs
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -2,11 +2,9 @@ pub mod app;
|
|||||||
mod parser;
|
mod parser;
|
||||||
pub mod trash;
|
pub mod trash;
|
||||||
pub mod view;
|
pub mod view;
|
||||||
mod view_info;
|
|
||||||
pub mod workspace;
|
pub mod workspace;
|
||||||
|
|
||||||
pub use app::*;
|
pub use app::*;
|
||||||
pub use trash::*;
|
pub use trash::*;
|
||||||
pub use view::*;
|
pub use view::*;
|
||||||
pub use view_info::*;
|
|
||||||
pub use workspace::*;
|
pub use workspace::*;
|
||||||
|
@ -50,9 +50,13 @@ impl std::convert::From<ViewRevision> for ViewPB {
|
|||||||
|
|
||||||
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
|
#[derive(Eq, PartialEq, Hash, Debug, ProtoBuf_Enum, Clone)]
|
||||||
pub enum ViewDataFormatPB {
|
pub enum ViewDataFormatPB {
|
||||||
|
/// Indicate this view is using `Delta` for the persistence data format, it's deprecated.
|
||||||
DeltaFormat = 0,
|
DeltaFormat = 0,
|
||||||
|
/// Indicate this view is using `Database` for the persistence data format. It is used in AppFlowy database
|
||||||
|
/// views including Grid,Board, and Calendar.
|
||||||
DatabaseFormat = 1,
|
DatabaseFormat = 1,
|
||||||
TreeFormat = 2,
|
/// Indicate this view is using `Node` for the persistence data format. It is used in AppFlowy document
|
||||||
|
NodeFormat = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::default::Default for ViewDataFormatPB {
|
impl std::default::Default for ViewDataFormatPB {
|
||||||
@ -66,7 +70,7 @@ impl std::convert::From<ViewDataFormatRevision> for ViewDataFormatPB {
|
|||||||
match rev {
|
match rev {
|
||||||
ViewDataFormatRevision::DeltaFormat => ViewDataFormatPB::DeltaFormat,
|
ViewDataFormatRevision::DeltaFormat => ViewDataFormatPB::DeltaFormat,
|
||||||
ViewDataFormatRevision::DatabaseFormat => ViewDataFormatPB::DatabaseFormat,
|
ViewDataFormatRevision::DatabaseFormat => ViewDataFormatPB::DatabaseFormat,
|
||||||
ViewDataFormatRevision::TreeFormat => ViewDataFormatPB::TreeFormat,
|
ViewDataFormatRevision::NodeFormat => ViewDataFormatPB::NodeFormat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -76,7 +80,7 @@ impl std::convert::From<ViewDataFormatPB> for ViewDataFormatRevision {
|
|||||||
match ty {
|
match ty {
|
||||||
ViewDataFormatPB::DeltaFormat => ViewDataFormatRevision::DeltaFormat,
|
ViewDataFormatPB::DeltaFormat => ViewDataFormatRevision::DeltaFormat,
|
||||||
ViewDataFormatPB::DatabaseFormat => ViewDataFormatRevision::DatabaseFormat,
|
ViewDataFormatPB::DatabaseFormat => ViewDataFormatRevision::DatabaseFormat,
|
||||||
ViewDataFormatPB::TreeFormat => ViewDataFormatRevision::TreeFormat,
|
ViewDataFormatPB::NodeFormat => ViewDataFormatRevision::NodeFormat,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,26 +0,0 @@
|
|||||||
use crate::entities::{RepeatedViewPB, ViewDataFormatPB};
|
|
||||||
use flowy_derive::ProtoBuf;
|
|
||||||
|
|
||||||
#[derive(Eq, PartialEq, ProtoBuf, Debug, Default, Clone)]
|
|
||||||
pub struct ViewInfoPB {
|
|
||||||
#[pb(index = 1)]
|
|
||||||
pub id: String,
|
|
||||||
|
|
||||||
#[pb(index = 2)]
|
|
||||||
pub belong_to_id: String,
|
|
||||||
|
|
||||||
#[pb(index = 3)]
|
|
||||||
pub name: String,
|
|
||||||
|
|
||||||
#[pb(index = 4)]
|
|
||||||
pub desc: String,
|
|
||||||
|
|
||||||
#[pb(index = 5)]
|
|
||||||
pub data_type: ViewDataFormatPB,
|
|
||||||
|
|
||||||
#[pb(index = 6)]
|
|
||||||
pub belongings: RepeatedViewPB,
|
|
||||||
|
|
||||||
#[pb(index = 7)]
|
|
||||||
pub ext_data: String,
|
|
||||||
}
|
|
@ -63,12 +63,11 @@ pub fn init(folder: Arc<FolderManager>) -> AFPlugin {
|
|||||||
.event(FolderEvent::CreateView, create_view_handler)
|
.event(FolderEvent::CreateView, create_view_handler)
|
||||||
.event(FolderEvent::ReadView, read_view_handler)
|
.event(FolderEvent::ReadView, read_view_handler)
|
||||||
.event(FolderEvent::UpdateView, update_view_handler)
|
.event(FolderEvent::UpdateView, update_view_handler)
|
||||||
.event(FolderEvent::ReadViewInfo, read_view_info_handler)
|
|
||||||
.event(FolderEvent::DeleteView, delete_view_handler)
|
.event(FolderEvent::DeleteView, delete_view_handler)
|
||||||
.event(FolderEvent::DuplicateView, duplicate_view_handler)
|
.event(FolderEvent::DuplicateView, duplicate_view_handler)
|
||||||
.event(FolderEvent::SetLatestView, set_latest_view_handler)
|
.event(FolderEvent::SetLatestView, set_latest_view_handler)
|
||||||
.event(FolderEvent::CloseView, close_view_handler)
|
.event(FolderEvent::CloseView, close_view_handler)
|
||||||
.event(FolderEvent::MoveFolderItem, move_item_handler);
|
.event(FolderEvent::MoveItem, move_item_handler);
|
||||||
|
|
||||||
// Trash
|
// Trash
|
||||||
plugin = plugin
|
plugin = plugin
|
||||||
@ -84,78 +83,99 @@ pub fn init(folder: Arc<FolderManager>) -> AFPlugin {
|
|||||||
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
#[derive(Clone, Copy, PartialEq, Eq, Debug, Display, Hash, ProtoBuf_Enum, Flowy_Event)]
|
||||||
#[event_err = "FlowyError"]
|
#[event_err = "FlowyError"]
|
||||||
pub enum FolderEvent {
|
pub enum FolderEvent {
|
||||||
|
/// Create a new workspace
|
||||||
#[event(input = "CreateWorkspacePayloadPB", output = "WorkspacePB")]
|
#[event(input = "CreateWorkspacePayloadPB", output = "WorkspacePB")]
|
||||||
CreateWorkspace = 0,
|
CreateWorkspace = 0,
|
||||||
|
|
||||||
|
/// Read the current opening workspace
|
||||||
#[event(output = "WorkspaceSettingPB")]
|
#[event(output = "WorkspaceSettingPB")]
|
||||||
ReadCurrentWorkspace = 1,
|
ReadCurrentWorkspace = 1,
|
||||||
|
|
||||||
|
/// Open the workspace and mark it as the current workspace
|
||||||
#[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")]
|
#[event(input = "WorkspaceIdPB", output = "RepeatedWorkspacePB")]
|
||||||
ReadWorkspaces = 2,
|
ReadWorkspaces = 2,
|
||||||
|
|
||||||
|
/// Delete the workspace
|
||||||
#[event(input = "WorkspaceIdPB")]
|
#[event(input = "WorkspaceIdPB")]
|
||||||
DeleteWorkspace = 3,
|
DeleteWorkspace = 3,
|
||||||
|
|
||||||
|
/// Open the workspace and mark it as the current workspace
|
||||||
#[event(input = "WorkspaceIdPB", output = "WorkspacePB")]
|
#[event(input = "WorkspaceIdPB", output = "WorkspacePB")]
|
||||||
OpenWorkspace = 4,
|
OpenWorkspace = 4,
|
||||||
|
|
||||||
|
/// Return a list of apps that belong to this workspace
|
||||||
#[event(input = "WorkspaceIdPB", output = "RepeatedAppPB")]
|
#[event(input = "WorkspaceIdPB", output = "RepeatedAppPB")]
|
||||||
ReadWorkspaceApps = 5,
|
ReadWorkspaceApps = 5,
|
||||||
|
|
||||||
|
/// Create a new app
|
||||||
#[event(input = "CreateAppPayloadPB", output = "AppPB")]
|
#[event(input = "CreateAppPayloadPB", output = "AppPB")]
|
||||||
CreateApp = 101,
|
CreateApp = 101,
|
||||||
|
|
||||||
|
/// Delete the app
|
||||||
#[event(input = "AppIdPB")]
|
#[event(input = "AppIdPB")]
|
||||||
DeleteApp = 102,
|
DeleteApp = 102,
|
||||||
|
|
||||||
|
/// Read the app
|
||||||
#[event(input = "AppIdPB", output = "AppPB")]
|
#[event(input = "AppIdPB", output = "AppPB")]
|
||||||
ReadApp = 103,
|
ReadApp = 103,
|
||||||
|
|
||||||
|
/// Update the app's properties including the name,description, etc.
|
||||||
#[event(input = "UpdateAppPayloadPB")]
|
#[event(input = "UpdateAppPayloadPB")]
|
||||||
UpdateApp = 104,
|
UpdateApp = 104,
|
||||||
|
|
||||||
|
/// Create a new view in the corresponding app
|
||||||
#[event(input = "CreateViewPayloadPB", output = "ViewPB")]
|
#[event(input = "CreateViewPayloadPB", output = "ViewPB")]
|
||||||
CreateView = 201,
|
CreateView = 201,
|
||||||
|
|
||||||
|
/// Return the view info
|
||||||
#[event(input = "ViewIdPB", output = "ViewPB")]
|
#[event(input = "ViewIdPB", output = "ViewPB")]
|
||||||
ReadView = 202,
|
ReadView = 202,
|
||||||
|
|
||||||
|
/// Update the view's properties including the name,description, etc.
|
||||||
#[event(input = "UpdateViewPayloadPB", output = "ViewPB")]
|
#[event(input = "UpdateViewPayloadPB", output = "ViewPB")]
|
||||||
UpdateView = 203,
|
UpdateView = 203,
|
||||||
|
|
||||||
|
/// Move the view to the trash folder
|
||||||
#[event(input = "RepeatedViewIdPB")]
|
#[event(input = "RepeatedViewIdPB")]
|
||||||
DeleteView = 204,
|
DeleteView = 204,
|
||||||
|
|
||||||
|
/// Duplicate the view
|
||||||
#[event(input = "ViewPB")]
|
#[event(input = "ViewPB")]
|
||||||
DuplicateView = 205,
|
DuplicateView = 205,
|
||||||
|
|
||||||
|
/// Close and release the resources that are used by this view.
|
||||||
|
/// It should get called when the 'View' page get destroy
|
||||||
#[event(input = "ViewIdPB")]
|
#[event(input = "ViewIdPB")]
|
||||||
CloseView = 206,
|
CloseView = 206,
|
||||||
|
|
||||||
#[event(input = "ViewIdPB", output = "ViewInfoPB")]
|
|
||||||
ReadViewInfo = 207,
|
|
||||||
|
|
||||||
#[event()]
|
#[event()]
|
||||||
CopyLink = 220,
|
CopyLink = 220,
|
||||||
|
|
||||||
|
/// Set the current visiting view
|
||||||
#[event(input = "ViewIdPB")]
|
#[event(input = "ViewIdPB")]
|
||||||
SetLatestView = 221,
|
SetLatestView = 221,
|
||||||
|
|
||||||
|
/// Move the view or app to another place
|
||||||
#[event(input = "MoveFolderItemPayloadPB")]
|
#[event(input = "MoveFolderItemPayloadPB")]
|
||||||
MoveFolderItem = 230,
|
MoveItem = 230,
|
||||||
|
|
||||||
|
/// Read the trash that was deleted by the user
|
||||||
#[event(output = "RepeatedTrashPB")]
|
#[event(output = "RepeatedTrashPB")]
|
||||||
ReadTrash = 300,
|
ReadTrash = 300,
|
||||||
|
|
||||||
|
/// Put back the trash to the origin folder
|
||||||
#[event(input = "TrashIdPB")]
|
#[event(input = "TrashIdPB")]
|
||||||
PutbackTrash = 301,
|
PutbackTrash = 301,
|
||||||
|
|
||||||
|
/// Delete the trash from the disk
|
||||||
#[event(input = "RepeatedTrashIdPB")]
|
#[event(input = "RepeatedTrashIdPB")]
|
||||||
DeleteTrash = 302,
|
DeleteTrash = 302,
|
||||||
|
|
||||||
|
/// Put back all the trash to its original folder
|
||||||
#[event()]
|
#[event()]
|
||||||
RestoreAllTrash = 303,
|
RestoreAllTrash = 303,
|
||||||
|
|
||||||
|
/// Delete all the trash from the disk
|
||||||
#[event()]
|
#[event()]
|
||||||
DeleteAllTrash = 304,
|
DeleteAllTrash = 304,
|
||||||
}
|
}
|
||||||
|
@ -89,7 +89,7 @@ impl ViewTable {
|
|||||||
let data_type = match view_rev.data_format {
|
let data_type = match view_rev.data_format {
|
||||||
ViewDataFormatRevision::DeltaFormat => SqlViewDataFormat::Delta,
|
ViewDataFormatRevision::DeltaFormat => SqlViewDataFormat::Delta,
|
||||||
ViewDataFormatRevision::DatabaseFormat => SqlViewDataFormat::Database,
|
ViewDataFormatRevision::DatabaseFormat => SqlViewDataFormat::Database,
|
||||||
ViewDataFormatRevision::TreeFormat => SqlViewDataFormat::Tree,
|
ViewDataFormatRevision::NodeFormat => SqlViewDataFormat::Tree,
|
||||||
};
|
};
|
||||||
|
|
||||||
ViewTable {
|
ViewTable {
|
||||||
@ -113,7 +113,7 @@ impl std::convert::From<ViewTable> for ViewRevision {
|
|||||||
let data_type = match table.view_type {
|
let data_type = match table.view_type {
|
||||||
SqlViewDataFormat::Delta => ViewDataFormatRevision::DeltaFormat,
|
SqlViewDataFormat::Delta => ViewDataFormatRevision::DeltaFormat,
|
||||||
SqlViewDataFormat::Database => ViewDataFormatRevision::DatabaseFormat,
|
SqlViewDataFormat::Database => ViewDataFormatRevision::DatabaseFormat,
|
||||||
SqlViewDataFormat::Tree => ViewDataFormatRevision::TreeFormat,
|
SqlViewDataFormat::Tree => ViewDataFormatRevision::NodeFormat,
|
||||||
};
|
};
|
||||||
|
|
||||||
ViewRevision {
|
ViewRevision {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
pub use crate::entities::view::ViewDataFormatPB;
|
pub use crate::entities::view::ViewDataFormatPB;
|
||||||
use crate::entities::{AppPB, DeletedViewPB, ViewInfoPB, ViewLayoutTypePB};
|
use crate::entities::{AppPB, DeletedViewPB, ViewLayoutTypePB};
|
||||||
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
use crate::manager::{ViewDataProcessor, ViewDataProcessorMap};
|
||||||
use crate::{
|
use crate::{
|
||||||
entities::{
|
entities::{
|
||||||
trash::{RepeatedTrashIdPB, TrashType},
|
trash::{RepeatedTrashIdPB, TrashType},
|
||||||
view::{CreateViewParams, RepeatedViewPB, UpdateViewParams, ViewIdPB, ViewPB},
|
view::{CreateViewParams, UpdateViewParams, ViewIdPB, ViewPB},
|
||||||
},
|
},
|
||||||
errors::{FlowyError, FlowyResult},
|
errors::{FlowyError, FlowyResult},
|
||||||
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
event_map::{FolderCouldServiceV1, WorkspaceUser},
|
||||||
@ -139,35 +139,6 @@ impl ViewController {
|
|||||||
Ok(view_rev)
|
Ok(view_rev)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(self, view_id), fields(view_id = %view_id.value), err)]
|
|
||||||
pub(crate) async fn read_view_pb(&self, view_id: ViewIdPB) -> Result<ViewInfoPB, FlowyError> {
|
|
||||||
let view_info = self
|
|
||||||
.persistence
|
|
||||||
.begin_transaction(|transaction| {
|
|
||||||
let view_rev = transaction.read_view(&view_id.value)?;
|
|
||||||
|
|
||||||
let items: Vec<ViewPB> = view_rev
|
|
||||||
.belongings
|
|
||||||
.into_iter()
|
|
||||||
.map(|view_rev| view_rev.into())
|
|
||||||
.collect();
|
|
||||||
|
|
||||||
let view_info = ViewInfoPB {
|
|
||||||
id: view_rev.id,
|
|
||||||
belong_to_id: view_rev.app_id,
|
|
||||||
name: view_rev.name,
|
|
||||||
desc: view_rev.desc,
|
|
||||||
data_type: view_rev.data_format.into(),
|
|
||||||
belongings: RepeatedViewPB { items },
|
|
||||||
ext_data: view_rev.ext_data,
|
|
||||||
};
|
|
||||||
Ok(view_info)
|
|
||||||
})
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(view_info)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) async fn read_local_views(&self, ids: Vec<String>) -> Result<Vec<ViewRevision>, FlowyError> {
|
pub(crate) async fn read_local_views(&self, ids: Vec<String>) -> Result<Vec<ViewRevision>, FlowyError> {
|
||||||
self.persistence
|
self.persistence
|
||||||
.begin_transaction(|transaction| {
|
.begin_transaction(|transaction| {
|
||||||
|
@ -1,5 +1,4 @@
|
|||||||
use crate::entities::view::{MoveFolderItemParams, MoveFolderItemPayloadPB, MoveFolderItemType};
|
use crate::entities::view::{MoveFolderItemParams, MoveFolderItemPayloadPB, MoveFolderItemType};
|
||||||
use crate::entities::ViewInfoPB;
|
|
||||||
use crate::manager::FolderManager;
|
use crate::manager::FolderManager;
|
||||||
use crate::services::{notify_workspace_setting_did_change, AppController};
|
use crate::services::{notify_workspace_setting_did_change, AppController};
|
||||||
use crate::{
|
use crate::{
|
||||||
@ -35,15 +34,6 @@ pub(crate) async fn read_view_handler(
|
|||||||
data_result(view_rev.into())
|
data_result(view_rev.into())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) async fn read_view_info_handler(
|
|
||||||
data: AFPluginData<ViewIdPB>,
|
|
||||||
controller: AFPluginState<Arc<ViewController>>,
|
|
||||||
) -> DataResult<ViewInfoPB, FlowyError> {
|
|
||||||
let view_id: ViewIdPB = data.into_inner();
|
|
||||||
let view_info = controller.read_view_pb(view_id.clone()).await?;
|
|
||||||
data_result(view_info)
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip(data, controller), err)]
|
#[tracing::instrument(level = "debug", skip(data, controller), err)]
|
||||||
pub(crate) async fn update_view_handler(
|
pub(crate) async fn update_view_handler(
|
||||||
data: AFPluginData<UpdateViewPayloadPB>,
|
data: AFPluginData<UpdateViewPayloadPB>,
|
||||||
|
@ -182,7 +182,7 @@ impl FolderTest {
|
|||||||
FolderScript::CreateView { name, desc, data_type } => {
|
FolderScript::CreateView { name, desc, data_type } => {
|
||||||
let layout = match data_type {
|
let layout = match data_type {
|
||||||
ViewDataFormatPB::DeltaFormat => ViewLayoutTypePB::Document,
|
ViewDataFormatPB::DeltaFormat => ViewLayoutTypePB::Document,
|
||||||
ViewDataFormatPB::TreeFormat => ViewLayoutTypePB::Document,
|
ViewDataFormatPB::NodeFormat => ViewLayoutTypePB::Document,
|
||||||
ViewDataFormatPB::DatabaseFormat => ViewLayoutTypePB::Grid,
|
ViewDataFormatPB::DatabaseFormat => ViewLayoutTypePB::Grid,
|
||||||
};
|
};
|
||||||
let view = create_view(sdk, &self.app.id, &name, &desc, data_type, layout).await;
|
let view = create_view(sdk, &self.app.id, &name, &desc, data_type, layout).await;
|
||||||
|
@ -58,7 +58,7 @@ impl ViewTest {
|
|||||||
pub async fn new_document_view(sdk: &FlowySDKTest) -> Self {
|
pub async fn new_document_view(sdk: &FlowySDKTest) -> Self {
|
||||||
let view_data_format = match sdk.document_version() {
|
let view_data_format = match sdk.document_version() {
|
||||||
DocumentVersionPB::V0 => ViewDataFormatPB::DeltaFormat,
|
DocumentVersionPB::V0 => ViewDataFormatPB::DeltaFormat,
|
||||||
DocumentVersionPB::V1 => ViewDataFormatPB::TreeFormat,
|
DocumentVersionPB::V1 => ViewDataFormatPB::NodeFormat,
|
||||||
};
|
};
|
||||||
Self::new(sdk, view_data_format, ViewLayoutTypePB::Document, vec![]).await
|
Self::new(sdk, view_data_format, ViewLayoutTypePB::Document, vec![]).await
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ impl std::convert::From<ViewRevision> for TrashRevision {
|
|||||||
pub enum ViewDataFormatRevision {
|
pub enum ViewDataFormatRevision {
|
||||||
DeltaFormat = 0,
|
DeltaFormat = 0,
|
||||||
DatabaseFormat = 1,
|
DatabaseFormat = 1,
|
||||||
TreeFormat = 2,
|
NodeFormat = 2,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::default::Default for ViewDataFormatRevision {
|
impl std::default::Default for ViewDataFormatRevision {
|
||||||
|
Reference in New Issue
Block a user