mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: refactor grid field listener
This commit is contained in:
parent
06af45a8ed
commit
fd9e13bf4b
@ -150,9 +150,16 @@ void _resolveGridDeps(GetIt getIt) {
|
|||||||
(view, _) => GridBloc(view: view),
|
(view, _) => GridBloc(view: view),
|
||||||
);
|
);
|
||||||
|
|
||||||
getIt.registerFactoryParam<RowBloc, RowData, void>(
|
getIt.registerFactoryParam<RowBloc, RowData, GridFieldCache>(
|
||||||
(data, _) => RowBloc(
|
(data, fieldCache) => RowBloc(
|
||||||
rowData: data,
|
rowData: data,
|
||||||
|
fieldCache: fieldCache,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
getIt.registerFactoryParam<GridHeaderBloc, String, List<Field>>(
|
||||||
|
(gridId, fields) => GridHeaderBloc(
|
||||||
|
data: GridHeaderData(gridId: gridId, fields: fields),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -123,9 +123,9 @@ class ApplicationBlocObserver extends BlocObserver {
|
|||||||
super.onError(bloc, error, stackTrace);
|
super.onError(bloc, error, stackTrace);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
void onEvent(Bloc bloc, Object? event) {
|
// void onEvent(Bloc bloc, Object? event) {
|
||||||
Log.debug("$event");
|
// Log.debug("$event");
|
||||||
super.onEvent(bloc, event);
|
// super.onEvent(bloc, event);
|
||||||
}
|
// }
|
||||||
}
|
}
|
||||||
|
@ -13,12 +13,12 @@ part 'date_cell_bloc.freezed.dart';
|
|||||||
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
|
||||||
final CellService _service;
|
final CellService _service;
|
||||||
final CellListener _cellListener;
|
final CellListener _cellListener;
|
||||||
final FieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
|
|
||||||
DateCellBloc({required CellData cellData})
|
DateCellBloc({required CellData cellData})
|
||||||
: _service = CellService(),
|
: _service = CellService(),
|
||||||
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||||
_fieldListener = FieldListener(fieldId: cellData.field.id),
|
_fieldListener = SingleFieldListener(fieldId: cellData.field.id),
|
||||||
super(DateCellState.initial(cellData)) {
|
super(DateCellState.initial(cellData)) {
|
||||||
on<DateCellEvent>(
|
on<DateCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
|
@ -13,13 +13,13 @@ part 'number_cell_bloc.freezed.dart';
|
|||||||
class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
|
||||||
final CellService _service;
|
final CellService _service;
|
||||||
final CellListener _cellListener;
|
final CellListener _cellListener;
|
||||||
final FieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
|
|
||||||
NumberCellBloc({
|
NumberCellBloc({
|
||||||
required CellData cellData,
|
required CellData cellData,
|
||||||
}) : _service = CellService(),
|
}) : _service = CellService(),
|
||||||
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||||
_fieldListener = FieldListener(fieldId: cellData.field.id),
|
_fieldListener = SingleFieldListener(fieldId: cellData.field.id),
|
||||||
super(NumberCellState.initial(cellData)) {
|
super(NumberCellState.initial(cellData)) {
|
||||||
on<NumberCellEvent>(
|
on<NumberCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
|
@ -13,13 +13,13 @@ part 'selection_cell_bloc.freezed.dart';
|
|||||||
class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
class SelectionCellBloc extends Bloc<SelectionCellEvent, SelectionCellState> {
|
||||||
final SelectOptionService _service;
|
final SelectOptionService _service;
|
||||||
final CellListener _cellListener;
|
final CellListener _cellListener;
|
||||||
final FieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
|
|
||||||
SelectionCellBloc({
|
SelectionCellBloc({
|
||||||
required CellData cellData,
|
required CellData cellData,
|
||||||
}) : _service = SelectOptionService(),
|
}) : _service = SelectOptionService(),
|
||||||
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||||
_fieldListener = FieldListener(fieldId: cellData.field.id),
|
_fieldListener = SingleFieldListener(fieldId: cellData.field.id),
|
||||||
super(SelectionCellState.initial(cellData)) {
|
super(SelectionCellState.initial(cellData)) {
|
||||||
on<SelectionCellEvent>(
|
on<SelectionCellEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
|
@ -13,7 +13,7 @@ part 'selection_editor_bloc.freezed.dart';
|
|||||||
|
|
||||||
class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionEditorState> {
|
class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionEditorState> {
|
||||||
final SelectOptionService _selectOptionService;
|
final SelectOptionService _selectOptionService;
|
||||||
final FieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
final CellListener _cellListener;
|
final CellListener _cellListener;
|
||||||
Timer? _delayOperation;
|
Timer? _delayOperation;
|
||||||
|
|
||||||
@ -22,7 +22,7 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
|
|||||||
required List<SelectOption> options,
|
required List<SelectOption> options,
|
||||||
required List<SelectOption> selectedOptions,
|
required List<SelectOption> selectedOptions,
|
||||||
}) : _selectOptionService = SelectOptionService(),
|
}) : _selectOptionService = SelectOptionService(),
|
||||||
_fieldListener = FieldListener(fieldId: cellData.field.id),
|
_fieldListener = SingleFieldListener(fieldId: cellData.field.id),
|
||||||
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
_cellListener = CellListener(rowId: cellData.rowId, fieldId: cellData.field.id),
|
||||||
super(SelectOptionEditorState.initial(cellData, options, selectedOptions)) {
|
super(SelectOptionEditorState.initial(cellData, options, selectedOptions)) {
|
||||||
on<SelectOptionEditorEvent>(
|
on<SelectOptionEditorEvent>(
|
||||||
|
@ -9,12 +9,12 @@ import 'dart:async';
|
|||||||
part 'field_cell_bloc.freezed.dart';
|
part 'field_cell_bloc.freezed.dart';
|
||||||
|
|
||||||
class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
|
||||||
final FieldListener _fieldListener;
|
final SingleFieldListener _fieldListener;
|
||||||
final FieldService _fieldService;
|
final FieldService _fieldService;
|
||||||
|
|
||||||
FieldCellBloc({
|
FieldCellBloc({
|
||||||
required GridFieldCellContext cellContext,
|
required GridFieldCellContext cellContext,
|
||||||
}) : _fieldListener = FieldListener(fieldId: cellContext.field.id),
|
}) : _fieldListener = SingleFieldListener(fieldId: cellContext.field.id),
|
||||||
_fieldService = FieldService(gridId: cellContext.gridId),
|
_fieldService = FieldService(gridId: cellContext.gridId),
|
||||||
super(FieldCellState.initial(cellContext)) {
|
super(FieldCellState.initial(cellContext)) {
|
||||||
on<FieldCellEvent>(
|
on<FieldCellEvent>(
|
||||||
|
@ -9,12 +9,12 @@ import 'package:app_flowy/core/notification_helper.dart';
|
|||||||
|
|
||||||
typedef UpdateFieldNotifiedValue = Either<Field, FlowyError>;
|
typedef UpdateFieldNotifiedValue = Either<Field, FlowyError>;
|
||||||
|
|
||||||
class FieldListener {
|
class SingleFieldListener {
|
||||||
final String fieldId;
|
final String fieldId;
|
||||||
PublishNotifier<UpdateFieldNotifiedValue> updateFieldNotifier = PublishNotifier();
|
PublishNotifier<UpdateFieldNotifiedValue> updateFieldNotifier = PublishNotifier();
|
||||||
GridNotificationListener? _listener;
|
GridNotificationListener? _listener;
|
||||||
|
|
||||||
FieldListener({required this.fieldId});
|
SingleFieldListener({required this.fieldId});
|
||||||
|
|
||||||
void start() {
|
void start() {
|
||||||
_listener = GridNotificationListener(
|
_listener = GridNotificationListener(
|
||||||
|
@ -7,7 +7,7 @@ import 'dart:async';
|
|||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
import 'package:app_flowy/core/notification_helper.dart';
|
import 'package:app_flowy/core/notification_helper.dart';
|
||||||
|
|
||||||
typedef UpdateFieldNotifiedValue = Either<List<Field>, FlowyError>;
|
typedef UpdateFieldNotifiedValue = Either<GridFieldChangeset, FlowyError>;
|
||||||
|
|
||||||
class GridFieldsListener {
|
class GridFieldsListener {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
@ -26,7 +26,7 @@ class GridFieldsListener {
|
|||||||
switch (ty) {
|
switch (ty) {
|
||||||
case GridNotification.DidUpdateGrid:
|
case GridNotification.DidUpdateGrid:
|
||||||
result.fold(
|
result.fold(
|
||||||
(payload) => updateFieldsNotifier.value = left(RepeatedField.fromBuffer(payload).items),
|
(payload) => updateFieldsNotifier.value = left(GridFieldChangeset.fromBuffer(payload)),
|
||||||
(error) => updateFieldsNotifier.value = right(error),
|
(error) => updateFieldsNotifier.value = right(error),
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
|
@ -17,18 +17,22 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
|||||||
final GridService _gridService;
|
final GridService _gridService;
|
||||||
final GridListener _gridListener;
|
final GridListener _gridListener;
|
||||||
final GridFieldsListener _fieldListener;
|
final GridFieldsListener _fieldListener;
|
||||||
|
final GridFieldCache fieldCache;
|
||||||
|
final GridRowCache _rowCache;
|
||||||
|
|
||||||
GridBloc({required View view})
|
GridBloc({required View view})
|
||||||
: _fieldListener = GridFieldsListener(gridId: view.id),
|
: _fieldListener = GridFieldsListener(gridId: view.id),
|
||||||
_gridService = GridService(gridId: view.id),
|
_gridService = GridService(gridId: view.id),
|
||||||
_gridListener = GridListener(gridId: view.id),
|
_gridListener = GridListener(gridId: view.id),
|
||||||
|
fieldCache = GridFieldCache(),
|
||||||
|
_rowCache = GridRowCache(gridId: view.id),
|
||||||
super(GridState.initial(view.id)) {
|
super(GridState.initial(view.id)) {
|
||||||
on<GridEvent>(
|
on<GridEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
initial: (InitialGrid value) async {
|
initial: (InitialGrid value) async {
|
||||||
await _initGrid(emit);
|
|
||||||
_startListening();
|
_startListening();
|
||||||
|
await _loadGrid(emit);
|
||||||
},
|
},
|
||||||
createRow: (_CreateRow value) {
|
createRow: (_CreateRow value) {
|
||||||
_gridService.createRow();
|
_gridService.createRow();
|
||||||
@ -37,11 +41,9 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
|||||||
emit(state.copyWith(rows: value.rows, listState: value.listState));
|
emit(state.copyWith(rows: value.rows, listState: value.listState));
|
||||||
},
|
},
|
||||||
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
||||||
final rows = state.rows.map((row) => row.copyWith(fields: value.fields)).toList();
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
rows: rows,
|
rows: _rowCache.rows,
|
||||||
fields: value.fields,
|
fields: value.fields,
|
||||||
listState: const GridListState.reload(),
|
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@ -57,35 +59,39 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
|||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _initGrid(Emitter<GridState> emit) async {
|
void _startListening() {
|
||||||
|
fieldCache.addListener((fields) {
|
||||||
|
_rowCache.updateFields(fields);
|
||||||
|
});
|
||||||
|
|
||||||
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(fields) => add(GridEvent.didReceiveFieldUpdate(fields)),
|
(changeset) {
|
||||||
|
fieldCache.applyChangeset(changeset);
|
||||||
|
add(GridEvent.didReceiveFieldUpdate(List.from(fieldCache.fields)));
|
||||||
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
_fieldListener.start();
|
_fieldListener.start();
|
||||||
|
|
||||||
await _loadGrid(emit);
|
|
||||||
}
|
|
||||||
|
|
||||||
void _startListening() {
|
|
||||||
_gridListener.rowsUpdateNotifier.addPublishListener((result) {
|
_gridListener.rowsUpdateNotifier.addPublishListener((result) {
|
||||||
result.fold((gridBlockChangeset) {
|
result.fold(
|
||||||
for (final changeset in gridBlockChangeset) {
|
(changesets) {
|
||||||
if (changeset.insertedRows.isNotEmpty) {
|
for (final changeset in changesets) {
|
||||||
_insertRows(changeset.insertedRows);
|
_rowCache
|
||||||
}
|
.deleteRows(changeset.deletedRows)
|
||||||
|
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(_rowCache.rows, listState)));
|
||||||
|
|
||||||
if (changeset.deletedRows.isNotEmpty) {
|
_rowCache
|
||||||
_deleteRows(changeset.deletedRows);
|
.insertRows(changeset.insertedRows)
|
||||||
}
|
.foldRight(null, (listState, _) => add(GridEvent.didReceiveRowUpdate(_rowCache.rows, listState)));
|
||||||
|
|
||||||
if (changeset.updatedRows.isNotEmpty) {
|
_rowCache.updateRows(changeset.updatedRows);
|
||||||
_updateRows(changeset.updatedRows);
|
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
}, (err) => Log.error(err));
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
});
|
});
|
||||||
_gridListener.start();
|
_gridListener.start();
|
||||||
}
|
}
|
||||||
@ -105,10 +111,13 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
|||||||
return Future(
|
return Future(
|
||||||
() => result.fold(
|
() => result.fold(
|
||||||
(fields) {
|
(fields) {
|
||||||
|
fieldCache.fields = fields.items;
|
||||||
|
_rowCache.updateWithBlock(grid.blockOrders);
|
||||||
|
|
||||||
emit(state.copyWith(
|
emit(state.copyWith(
|
||||||
grid: Some(grid),
|
grid: Some(grid),
|
||||||
fields: fields.items,
|
fields: fieldCache.fields,
|
||||||
rows: _buildRows(grid.blockOrders, fields.items),
|
rows: _rowCache.rows,
|
||||||
loadingState: GridLoadingState.finish(left(unit)),
|
loadingState: GridLoadingState.finish(left(unit)),
|
||||||
));
|
));
|
||||||
},
|
},
|
||||||
@ -116,60 +125,6 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
|||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _deleteRows(List<RowOrder> deletedRows) {
|
|
||||||
final List<RowData> rows = [];
|
|
||||||
final List<Tuple2<int, RowData>> deletedIndex = [];
|
|
||||||
final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder};
|
|
||||||
state.rows.asMap().forEach((index, value) {
|
|
||||||
if (deletedRowMap[value.rowId] == null) {
|
|
||||||
rows.add(value);
|
|
||||||
} else {
|
|
||||||
deletedIndex.add(Tuple2(index, value));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
add(GridEvent.didReceiveRowUpdate(rows, GridListState.delete(deletedIndex)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _insertRows(List<IndexRowOrder> createdRows) {
|
|
||||||
final List<RowData> rows = List.from(state.rows);
|
|
||||||
List<int> insertIndexs = [];
|
|
||||||
for (final newRow in createdRows) {
|
|
||||||
if (newRow.hasIndex()) {
|
|
||||||
insertIndexs.add(newRow.index);
|
|
||||||
rows.insert(newRow.index, _toRowData(newRow.rowOrder));
|
|
||||||
} else {
|
|
||||||
insertIndexs.add(rows.length);
|
|
||||||
rows.add(_toRowData(newRow.rowOrder));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
add(GridEvent.didReceiveRowUpdate(rows, GridListState.insert(insertIndexs)));
|
|
||||||
}
|
|
||||||
|
|
||||||
void _updateRows(List<RowOrder> updatedRows) {
|
|
||||||
final List<RowData> rows = List.from(state.rows);
|
|
||||||
final List<int> updatedIndexs = [];
|
|
||||||
for (final updatedRow in updatedRows) {
|
|
||||||
final index = rows.indexWhere((row) => row.rowId == updatedRow.rowId);
|
|
||||||
if (index != -1) {
|
|
||||||
rows.removeAt(index);
|
|
||||||
rows.insert(index, _toRowData(updatedRow));
|
|
||||||
updatedIndexs.add(index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
add(GridEvent.didReceiveRowUpdate(rows, const GridListState.reload()));
|
|
||||||
}
|
|
||||||
|
|
||||||
List<RowData> _buildRows(List<GridBlockOrder> blockOrders, List<Field> fields) {
|
|
||||||
return blockOrders.expand((blockOrder) => blockOrder.rowOrders).map((rowOrder) {
|
|
||||||
return RowData.fromBlockRow(state.gridId, rowOrder, fields);
|
|
||||||
}).toList();
|
|
||||||
}
|
|
||||||
|
|
||||||
RowData _toRowData(RowOrder rowOrder) {
|
|
||||||
return RowData.fromBlockRow(state.gridId, rowOrder, state.fields);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
@ -197,7 +152,7 @@ class GridState with _$GridState {
|
|||||||
grid: none(),
|
grid: none(),
|
||||||
gridId: gridId,
|
gridId: gridId,
|
||||||
loadingState: const _Loading(),
|
loadingState: const _Loading(),
|
||||||
listState: const _Reload(),
|
listState: const InitialListState(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -206,10 +161,3 @@ class GridLoadingState with _$GridLoadingState {
|
|||||||
const factory GridLoadingState.loading() = _Loading;
|
const factory GridLoadingState.loading() = _Loading;
|
||||||
const factory GridLoadingState.finish(Either<Unit, FlowyError> successOrFail) = _Finish;
|
const factory GridLoadingState.finish(Either<Unit, FlowyError> successOrFail) = _Finish;
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
|
||||||
class GridListState with _$GridListState {
|
|
||||||
const factory GridListState.insert(List<int> indexs) = _Insert;
|
|
||||||
const factory GridListState.delete(List<Tuple2<int, RowData>> indexs) = _Delete;
|
|
||||||
const factory GridListState.reload() = _Reload;
|
|
||||||
}
|
|
||||||
|
@ -0,0 +1,76 @@
|
|||||||
|
import 'package:app_flowy/workspace/application/grid/data.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart';
|
||||||
|
import 'package:flowy_sdk/log.dart';
|
||||||
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'field/field_service.dart';
|
||||||
|
import 'grid_service.dart';
|
||||||
|
|
||||||
|
part 'grid_header_bloc.freezed.dart';
|
||||||
|
|
||||||
|
class GridHeaderBloc extends Bloc<GridHeaderEvent, GridHeaderState> {
|
||||||
|
final FieldService _fieldService;
|
||||||
|
final GridFieldCache _fieldCache;
|
||||||
|
final GridFieldsListener _fieldListener;
|
||||||
|
|
||||||
|
GridHeaderBloc({
|
||||||
|
required GridHeaderData data,
|
||||||
|
}) : _fieldListener = GridFieldsListener(gridId: data.gridId),
|
||||||
|
_fieldService = FieldService(gridId: data.gridId),
|
||||||
|
_fieldCache = GridFieldCache(),
|
||||||
|
super(GridHeaderState.initial(data.fields)) {
|
||||||
|
_fieldCache.fields = data.fields;
|
||||||
|
|
||||||
|
on<GridHeaderEvent>(
|
||||||
|
(event, emit) async {
|
||||||
|
await event.map(
|
||||||
|
initial: (_InitialHeader value) async {
|
||||||
|
_startListening();
|
||||||
|
},
|
||||||
|
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
|
||||||
|
value.fields.retainWhere((field) => field.visibility);
|
||||||
|
emit(state.copyWith(fields: value.fields));
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _startListening() async {
|
||||||
|
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
||||||
|
result.fold(
|
||||||
|
(changeset) {
|
||||||
|
_fieldCache.applyChangeset(changeset);
|
||||||
|
add(GridHeaderEvent.didReceiveFieldUpdate(List.from(_fieldCache.fields)));
|
||||||
|
},
|
||||||
|
(err) => Log.error(err),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
_fieldListener.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<void> close() async {
|
||||||
|
await _fieldListener.stop();
|
||||||
|
return super.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class GridHeaderEvent with _$GridHeaderEvent {
|
||||||
|
const factory GridHeaderEvent.initial() = _InitialHeader;
|
||||||
|
const factory GridHeaderEvent.didReceiveFieldUpdate(List<Field> fields) = _DidReceiveFieldUpdate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class GridHeaderState with _$GridHeaderState {
|
||||||
|
const factory GridHeaderState({required List<Field> fields}) = _GridHeaderState;
|
||||||
|
|
||||||
|
factory GridHeaderState.initial(List<Field> fields) {
|
||||||
|
fields.retainWhere((field) => field.visibility);
|
||||||
|
return GridHeaderState(fields: fields);
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,11 @@ import 'package:flowy_sdk/dispatch/dispatch.dart';
|
|||||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-folder-data-model/view.pb.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||||
|
|
||||||
|
part 'grid_service.freezed.dart';
|
||||||
|
|
||||||
class GridService {
|
class GridService {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
@ -35,3 +40,174 @@ class GridService {
|
|||||||
return FolderEventCloseView(request).send();
|
return FolderEventCloseView(request).send();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class FieldsNotifier extends ChangeNotifier {
|
||||||
|
List<Field> _fields = [];
|
||||||
|
|
||||||
|
set fields(List<Field> fields) {
|
||||||
|
_fields = fields;
|
||||||
|
notifyListeners();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Field> get fields => _fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
class GridFieldCache {
|
||||||
|
final FieldsNotifier _fieldNotifier = FieldsNotifier();
|
||||||
|
GridFieldCache();
|
||||||
|
|
||||||
|
void applyChangeset(GridFieldChangeset changeset) {
|
||||||
|
_removeFields(changeset.deletedFields);
|
||||||
|
_insertFields(changeset.insertedFields);
|
||||||
|
_updateFields(changeset.updatedFields);
|
||||||
|
}
|
||||||
|
|
||||||
|
List<Field> get fields => _fieldNotifier.fields;
|
||||||
|
|
||||||
|
set fields(List<Field> fields) {
|
||||||
|
_fieldNotifier.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
set onFieldChanged(void Function(List<Field>) onChanged) {
|
||||||
|
_fieldNotifier.addListener(() => onChanged(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
void addListener(void Function(List<Field>) onFieldChanged) {
|
||||||
|
_fieldNotifier.addListener(() => onFieldChanged(fields));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _removeFields(List<FieldOrder> deletedFields) {
|
||||||
|
if (deletedFields.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final List<Field> fields = List.from(_fieldNotifier.fields);
|
||||||
|
final Map<String, FieldOrder> deletedFieldMap = {
|
||||||
|
for (var fieldOrder in deletedFields) fieldOrder.fieldId: fieldOrder
|
||||||
|
};
|
||||||
|
|
||||||
|
fields.retainWhere((field) => (deletedFieldMap[field.id] == null));
|
||||||
|
_fieldNotifier.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _insertFields(List<IndexField> insertedFields) {
|
||||||
|
if (insertedFields.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final List<Field> fields = List.from(_fieldNotifier.fields);
|
||||||
|
for (final indexField in insertedFields) {
|
||||||
|
if (fields.length > indexField.index) {
|
||||||
|
fields.removeAt(indexField.index);
|
||||||
|
fields.insert(indexField.index, indexField.field_1);
|
||||||
|
} else {
|
||||||
|
fields.add(indexField.field_1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_fieldNotifier.fields = fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateFields(List<Field> updatedFields) {
|
||||||
|
if (updatedFields.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final List<Field> fields = List.from(_fieldNotifier.fields);
|
||||||
|
for (final updatedField in updatedFields) {
|
||||||
|
final index = fields.indexWhere((field) => field.id == updatedField.id);
|
||||||
|
if (index != -1) {
|
||||||
|
fields.removeAt(index);
|
||||||
|
fields.insert(index, updatedField);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_fieldNotifier.fields = fields;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GridRowCache {
|
||||||
|
final String gridId;
|
||||||
|
List<Field> _fields = [];
|
||||||
|
List<RowData> _rows = [];
|
||||||
|
|
||||||
|
GridRowCache({required this.gridId});
|
||||||
|
|
||||||
|
List<RowData> get rows => _rows;
|
||||||
|
|
||||||
|
void updateWithBlock(List<GridBlockOrder> blocks) {
|
||||||
|
_rows = blocks.expand((block) => block.rowOrders).map((rowOrder) {
|
||||||
|
return RowData.fromBlockRow(gridId, rowOrder, _fields);
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateFields(List<Field> fields) {
|
||||||
|
if (fields.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_fields = fields;
|
||||||
|
_rows = _rows.map((row) => row.copyWith(fields: fields)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
Option<GridListState> deleteRows(List<RowOrder> deletedRows) {
|
||||||
|
if (deletedRows.isEmpty) {
|
||||||
|
return none();
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<RowData> newRows = [];
|
||||||
|
final List<Tuple2<int, RowData>> deletedIndex = [];
|
||||||
|
final Map<String, RowOrder> deletedRowMap = {for (var rowOrder in deletedRows) rowOrder.rowId: rowOrder};
|
||||||
|
_rows.asMap().forEach((index, value) {
|
||||||
|
if (deletedRowMap[value.rowId] == null) {
|
||||||
|
newRows.add(value);
|
||||||
|
} else {
|
||||||
|
deletedIndex.add(Tuple2(index, value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
_rows = newRows;
|
||||||
|
|
||||||
|
return Some(GridListState.delete(deletedIndex));
|
||||||
|
}
|
||||||
|
|
||||||
|
Option<GridListState> insertRows(List<IndexRowOrder> createdRows) {
|
||||||
|
if (createdRows.isEmpty) {
|
||||||
|
return none();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<int> insertIndexs = [];
|
||||||
|
for (final newRow in createdRows) {
|
||||||
|
if (newRow.hasIndex()) {
|
||||||
|
insertIndexs.add(newRow.index);
|
||||||
|
_rows.insert(newRow.index, _toRowData(newRow.rowOrder));
|
||||||
|
} else {
|
||||||
|
insertIndexs.add(_rows.length);
|
||||||
|
_rows.add(_toRowData(newRow.rowOrder));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Some(GridListState.insert(insertIndexs));
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateRows(List<RowOrder> updatedRows) {
|
||||||
|
if (updatedRows.isEmpty) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final List<int> updatedIndexs = [];
|
||||||
|
for (final updatedRow in updatedRows) {
|
||||||
|
final index = _rows.indexWhere((row) => row.rowId == updatedRow.rowId);
|
||||||
|
if (index != -1) {
|
||||||
|
_rows.removeAt(index);
|
||||||
|
_rows.insert(index, _toRowData(updatedRow));
|
||||||
|
updatedIndexs.add(index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RowData _toRowData(RowOrder rowOrder) {
|
||||||
|
return RowData.fromBlockRow(gridId, rowOrder, _fields);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
class GridListState with _$GridListState {
|
||||||
|
const factory GridListState.insert(List<int> indexs) = _Insert;
|
||||||
|
const factory GridListState.delete(List<Tuple2<int, RowData>> indexs) = _Delete;
|
||||||
|
const factory GridListState.initial() = InitialListState;
|
||||||
|
}
|
||||||
|
@ -3,6 +3,7 @@ export 'row/row_bloc.dart';
|
|||||||
export 'row/row_service.dart';
|
export 'row/row_service.dart';
|
||||||
export 'grid_service.dart';
|
export 'grid_service.dart';
|
||||||
export 'data.dart';
|
export 'data.dart';
|
||||||
|
export 'grid_header_bloc.dart';
|
||||||
|
|
||||||
// Field
|
// Field
|
||||||
export 'field/field_service.dart';
|
export 'field/field_service.dart';
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
import 'dart:collection';
|
import 'dart:collection';
|
||||||
|
|
||||||
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart';
|
import 'package:app_flowy/workspace/application/grid/grid_service.dart';
|
||||||
import 'package:flowy_sdk/log.dart';
|
import 'package:flowy_sdk/log.dart';
|
||||||
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
@ -17,18 +17,18 @@ typedef CellDataMap = LinkedHashMap<String, CellData>;
|
|||||||
class RowBloc extends Bloc<RowEvent, RowState> {
|
class RowBloc extends Bloc<RowEvent, RowState> {
|
||||||
final RowService _rowService;
|
final RowService _rowService;
|
||||||
final RowListener _rowlistener;
|
final RowListener _rowlistener;
|
||||||
final GridFieldsListener _fieldListener;
|
final GridFieldCache _fieldCache;
|
||||||
|
|
||||||
RowBloc({required RowData rowData})
|
RowBloc({required RowData rowData, required GridFieldCache fieldCache})
|
||||||
: _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
: _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
||||||
_fieldListener = GridFieldsListener(gridId: rowData.gridId),
|
_fieldCache = fieldCache,
|
||||||
_rowlistener = RowListener(rowId: rowData.rowId),
|
_rowlistener = RowListener(rowId: rowData.rowId),
|
||||||
super(RowState.initial(rowData)) {
|
super(RowState.initial(rowData)) {
|
||||||
on<RowEvent>(
|
on<RowEvent>(
|
||||||
(event, emit) async {
|
(event, emit) async {
|
||||||
await event.map(
|
await event.map(
|
||||||
initial: (_InitialRow value) async {
|
initial: (_InitialRow value) async {
|
||||||
_startListening();
|
await _startListening();
|
||||||
await _loadRow(emit);
|
await _loadRow(emit);
|
||||||
},
|
},
|
||||||
createRow: (_CreateRow value) {
|
createRow: (_CreateRow value) {
|
||||||
@ -69,7 +69,6 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
|||||||
@override
|
@override
|
||||||
Future<void> close() async {
|
Future<void> close() async {
|
||||||
await _rowlistener.stop();
|
await _rowlistener.stop();
|
||||||
await _fieldListener.stop();
|
|
||||||
return super.close();
|
return super.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -81,15 +80,13 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
_fieldCache.addListener((fields) {
|
||||||
result.fold(
|
if (!isClosed) {
|
||||||
(fields) => add(RowEvent.didReceiveFieldUpdate(fields)),
|
add(RowEvent.didReceiveFieldUpdate(fields));
|
||||||
(err) => Log.error(err),
|
}
|
||||||
);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
_rowlistener.start();
|
_rowlistener.start();
|
||||||
_fieldListener.start();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _loadRow(Emitter<RowState> emit) async {
|
Future<void> _loadRow(Emitter<RowState> emit) async {
|
||||||
|
@ -50,7 +50,7 @@ class GridPropertyBloc extends Bloc<GridPropertyEvent, GridPropertyState> {
|
|||||||
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
||||||
result.fold(
|
result.fold(
|
||||||
(fields) {
|
(fields) {
|
||||||
add(GridPropertyEvent.didReceiveFieldUpdate(fields));
|
// add(GridPropertyEvent.didReceiveFieldUpdate(fields));
|
||||||
},
|
},
|
||||||
(err) => Log.error(err),
|
(err) => Log.error(err),
|
||||||
);
|
);
|
||||||
|
@ -150,11 +150,7 @@ class _GridHeader extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SliverPersistentHeader(
|
return GridHeaderSliverAdaptor(gridId: gridId, fields: fields);
|
||||||
delegate: GridHeaderSliverAdaptor(gridId: gridId, fields: List.from(fields)),
|
|
||||||
floating: true,
|
|
||||||
pinned: true,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,10 +170,13 @@ class _GridRows extends StatelessWidget {
|
|||||||
},
|
},
|
||||||
delete: (value) {
|
delete: (value) {
|
||||||
for (final index in value.indexs) {
|
for (final index in value.indexs) {
|
||||||
_key.currentState?.removeItem(index.value1, (context, animation) => _renderRow(index.value2, animation));
|
_key.currentState?.removeItem(
|
||||||
|
index.value1,
|
||||||
|
(context, animation) => _renderRow(context, index.value2, animation),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
reload: (updatedIndexs) {},
|
initial: (updatedIndexs) {},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
buildWhen: (previous, current) => false,
|
buildWhen: (previous, current) => false,
|
||||||
@ -187,17 +186,22 @@ class _GridRows extends StatelessWidget {
|
|||||||
initialItemCount: context.read<GridBloc>().state.rows.length,
|
initialItemCount: context.read<GridBloc>().state.rows.length,
|
||||||
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
|
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
|
||||||
final rowData = context.read<GridBloc>().state.rows[index];
|
final rowData = context.read<GridBloc>().state.rows[index];
|
||||||
return _renderRow(rowData, animation);
|
return _renderRow(context, rowData, animation);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _renderRow(RowData rowData, Animation<double> animation) {
|
Widget _renderRow(BuildContext context, RowData rowData, Animation<double> animation) {
|
||||||
|
final fieldCache = context.read<GridBloc>().fieldCache;
|
||||||
return SizeTransition(
|
return SizeTransition(
|
||||||
sizeFactor: animation,
|
sizeFactor: animation,
|
||||||
child: GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)),
|
child: GridRowWidget(
|
||||||
|
data: rowData,
|
||||||
|
fieldCache: fieldCache,
|
||||||
|
key: ValueKey(rowData.rowId),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,32 +12,38 @@ import 'package:flutter_bloc/flutter_bloc.dart';
|
|||||||
import 'field_editor.dart';
|
import 'field_editor.dart';
|
||||||
import 'field_cell.dart';
|
import 'field_cell.dart';
|
||||||
|
|
||||||
class GridHeaderSliverAdaptor extends SliverPersistentHeaderDelegate {
|
class GridHeaderSliverAdaptor extends StatelessWidget {
|
||||||
final String gridId;
|
final String gridId;
|
||||||
final List<Field> fields;
|
final List<Field> fields;
|
||||||
|
|
||||||
GridHeaderSliverAdaptor({required this.gridId, required this.fields});
|
const GridHeaderSliverAdaptor({required this.gridId, required this.fields, Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => getIt<GridHeaderBloc>(param1: gridId, param2: fields)..add(const GridHeaderEvent.initial()),
|
||||||
|
child: BlocBuilder<GridHeaderBloc, GridHeaderState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return SliverPersistentHeader(
|
||||||
|
delegate: SliverHeaderDelegateImplementation(gridId: gridId, fields: fields),
|
||||||
|
floating: true,
|
||||||
|
pinned: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SliverHeaderDelegateImplementation extends SliverPersistentHeaderDelegate {
|
||||||
|
final String gridId;
|
||||||
|
final List<Field> fields;
|
||||||
|
|
||||||
|
SliverHeaderDelegateImplementation({required this.gridId, required this.fields});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
|
Widget build(BuildContext context, double shrinkOffset, bool overlapsContent) {
|
||||||
final cells = fields.map(
|
return _GridHeader(gridId: gridId, fields: fields, key: ObjectKey(fields));
|
||||||
(field) => GridFieldCell(
|
|
||||||
GridFieldCellContext(gridId: gridId, field: field),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
color: Colors.white,
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
const _CellLeading(),
|
|
||||||
...cells,
|
|
||||||
_CellTrailing(gridId: gridId),
|
|
||||||
],
|
|
||||||
key: ObjectKey(fields),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -48,13 +54,49 @@ class GridHeaderSliverAdaptor extends SliverPersistentHeaderDelegate {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
|
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
|
||||||
if (oldDelegate is GridHeaderSliverAdaptor) {
|
if (oldDelegate is SliverHeaderDelegateImplementation) {
|
||||||
return fields.length != oldDelegate.fields.length;
|
return fields.length != oldDelegate.fields.length;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _GridHeader extends StatelessWidget {
|
||||||
|
final String gridId;
|
||||||
|
final List<Field> fields;
|
||||||
|
|
||||||
|
const _GridHeader({
|
||||||
|
Key? key,
|
||||||
|
required this.gridId,
|
||||||
|
required this.fields,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final theme = context.watch<AppTheme>();
|
||||||
|
return BlocBuilder<GridHeaderBloc, GridHeaderState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
final cells = state.fields
|
||||||
|
.map((field) => GridFieldCellContext(gridId: gridId, field: field))
|
||||||
|
.map((ctx) => GridFieldCell(ctx, key: ValueKey(ctx.field.id)))
|
||||||
|
.toList();
|
||||||
|
|
||||||
|
return Container(
|
||||||
|
color: theme.surface,
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
const _CellLeading(),
|
||||||
|
...cells,
|
||||||
|
_CellTrailing(gridId: gridId),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _CellLeading extends StatelessWidget {
|
class _CellLeading extends StatelessWidget {
|
||||||
const _CellLeading({Key? key}) : super(key: key);
|
const _CellLeading({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@ -13,7 +13,8 @@ import 'row_action_sheet.dart';
|
|||||||
|
|
||||||
class GridRowWidget extends StatefulWidget {
|
class GridRowWidget extends StatefulWidget {
|
||||||
final RowData data;
|
final RowData data;
|
||||||
const GridRowWidget({required this.data, Key? key}) : super(key: key);
|
final GridFieldCache fieldCache;
|
||||||
|
const GridRowWidget({required this.data, required this.fieldCache, Key? key}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State<GridRowWidget> createState() => _GridRowWidgetState();
|
State<GridRowWidget> createState() => _GridRowWidgetState();
|
||||||
@ -25,7 +26,7 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
_rowBloc = getIt<RowBloc>(param1: widget.data)..add(const RowEvent.initial());
|
_rowBloc = getIt<RowBloc>(param1: widget.data, param2: widget.fieldCache)..add(const RowEvent.initial());
|
||||||
_rowStateNotifier = _RegionStateNotifier();
|
_rowStateNotifier = _RegionStateNotifier();
|
||||||
super.initState();
|
super.initState();
|
||||||
}
|
}
|
||||||
|
@ -325,18 +325,8 @@ class GridFieldChangeset extends $pb.GeneratedMessage {
|
|||||||
$core.List<Field> get updatedFields => $_getList(3);
|
$core.List<Field> get updatedFields => $_getList(3);
|
||||||
}
|
}
|
||||||
|
|
||||||
enum IndexField_OneOfIndex {
|
|
||||||
index_,
|
|
||||||
notSet
|
|
||||||
}
|
|
||||||
|
|
||||||
class IndexField extends $pb.GeneratedMessage {
|
class IndexField extends $pb.GeneratedMessage {
|
||||||
static const $core.Map<$core.int, IndexField_OneOfIndex> _IndexField_OneOfIndexByTag = {
|
|
||||||
2 : IndexField_OneOfIndex.index_,
|
|
||||||
0 : IndexField_OneOfIndex.notSet
|
|
||||||
};
|
|
||||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'IndexField', createEmptyInstance: create)
|
static final $pb.BuilderInfo _i = $pb.BuilderInfo(const $core.bool.fromEnvironment('protobuf.omit_message_names') ? '' : 'IndexField', createEmptyInstance: create)
|
||||||
..oo(0, [2])
|
|
||||||
..aOM<Field>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'field', subBuilder: Field.create)
|
..aOM<Field>(1, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'field', subBuilder: Field.create)
|
||||||
..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'index', $pb.PbFieldType.O3)
|
..a<$core.int>(2, const $core.bool.fromEnvironment('protobuf.omit_field_names') ? '' : 'index', $pb.PbFieldType.O3)
|
||||||
..hasRequiredFields = false
|
..hasRequiredFields = false
|
||||||
@ -377,9 +367,6 @@ class IndexField extends $pb.GeneratedMessage {
|
|||||||
static IndexField getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<IndexField>(create);
|
static IndexField getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<IndexField>(create);
|
||||||
static IndexField? _defaultInstance;
|
static IndexField? _defaultInstance;
|
||||||
|
|
||||||
IndexField_OneOfIndex whichOneOfIndex() => _IndexField_OneOfIndexByTag[$_whichOneof(0)]!;
|
|
||||||
void clearOneOfIndex() => clearField($_whichOneof(0));
|
|
||||||
|
|
||||||
@$pb.TagNumber(1)
|
@$pb.TagNumber(1)
|
||||||
Field get field_1 => $_getN(0);
|
Field get field_1 => $_getN(0);
|
||||||
@$pb.TagNumber(1)
|
@$pb.TagNumber(1)
|
||||||
|
@ -90,15 +90,12 @@ const IndexField$json = const {
|
|||||||
'1': 'IndexField',
|
'1': 'IndexField',
|
||||||
'2': const [
|
'2': const [
|
||||||
const {'1': 'field', '3': 1, '4': 1, '5': 11, '6': '.Field', '10': 'field'},
|
const {'1': 'field', '3': 1, '4': 1, '5': 11, '6': '.Field', '10': 'field'},
|
||||||
const {'1': 'index', '3': 2, '4': 1, '5': 5, '9': 0, '10': 'index'},
|
const {'1': 'index', '3': 2, '4': 1, '5': 5, '10': 'index'},
|
||||||
],
|
|
||||||
'8': const [
|
|
||||||
const {'1': 'one_of_index'},
|
|
||||||
],
|
],
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Descriptor for `IndexField`. Decode as a `google.protobuf.DescriptorProto`.
|
/// Descriptor for `IndexField`. Decode as a `google.protobuf.DescriptorProto`.
|
||||||
final $typed_data.Uint8List indexFieldDescriptor = $convert.base64Decode('CgpJbmRleEZpZWxkEhwKBWZpZWxkGAEgASgLMgYuRmllbGRSBWZpZWxkEhYKBWluZGV4GAIgASgFSABSBWluZGV4Qg4KDG9uZV9vZl9pbmRleA==');
|
final $typed_data.Uint8List indexFieldDescriptor = $convert.base64Decode('CgpJbmRleEZpZWxkEhwKBWZpZWxkGAEgASgLMgYuRmllbGRSBWZpZWxkEhQKBWluZGV4GAIgASgFUgVpbmRleA==');
|
||||||
@$core.Deprecated('Use getEditFieldContextPayloadDescriptor instead')
|
@$core.Deprecated('Use getEditFieldContextPayloadDescriptor instead')
|
||||||
const GetEditFieldContextPayload$json = const {
|
const GetEditFieldContextPayload$json = const {
|
||||||
'1': 'GetEditFieldContextPayload',
|
'1': 'GetEditFieldContextPayload',
|
||||||
|
@ -24,7 +24,7 @@ pub struct ClientFolderEditor {
|
|||||||
pub(crate) folder_id: FolderId,
|
pub(crate) folder_id: FolderId,
|
||||||
pub(crate) folder: Arc<RwLock<FolderPad>>,
|
pub(crate) folder: Arc<RwLock<FolderPad>>,
|
||||||
rev_manager: Arc<RevisionManager>,
|
rev_manager: Arc<RevisionManager>,
|
||||||
ws_manager: Arc<RevisionWebSocketManager>,
|
// ws_manager: Arc<RevisionWebSocketManager>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ClientFolderEditor {
|
impl ClientFolderEditor {
|
||||||
@ -40,14 +40,14 @@ impl ClientFolderEditor {
|
|||||||
});
|
});
|
||||||
let folder = Arc::new(RwLock::new(rev_manager.load::<FolderPadBuilder>(Some(cloud)).await?));
|
let folder = Arc::new(RwLock::new(rev_manager.load::<FolderPadBuilder>(Some(cloud)).await?));
|
||||||
let rev_manager = Arc::new(rev_manager);
|
let rev_manager = Arc::new(rev_manager);
|
||||||
let ws_manager = make_folder_ws_manager(
|
// let ws_manager = make_folder_ws_manager(
|
||||||
user_id,
|
// user_id,
|
||||||
folder_id.as_ref(),
|
// folder_id.as_ref(),
|
||||||
rev_manager.clone(),
|
// rev_manager.clone(),
|
||||||
web_socket,
|
// web_socket,
|
||||||
folder.clone(),
|
// folder.clone(),
|
||||||
)
|
// )
|
||||||
.await;
|
// .await;
|
||||||
|
|
||||||
let user_id = user_id.to_owned();
|
let user_id = user_id.to_owned();
|
||||||
let folder_id = folder_id.to_owned();
|
let folder_id = folder_id.to_owned();
|
||||||
@ -56,15 +56,15 @@ impl ClientFolderEditor {
|
|||||||
folder_id,
|
folder_id,
|
||||||
folder,
|
folder,
|
||||||
rev_manager,
|
rev_manager,
|
||||||
ws_manager,
|
// ws_manager,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn receive_ws_data(&self, data: ServerRevisionWSData) -> FlowyResult<()> {
|
pub async fn receive_ws_data(&self, data: ServerRevisionWSData) -> FlowyResult<()> {
|
||||||
let _ = self.ws_manager.ws_passthrough_tx.send(data).await.map_err(|e| {
|
// let _ = self.ws_manager.ws_passthrough_tx.send(data).await.map_err(|e| {
|
||||||
let err_msg = format!("{} passthrough error: {}", self.folder_id, e);
|
// let err_msg = format!("{} passthrough error: {}", self.folder_id, e);
|
||||||
FlowyError::internal().context(err_msg)
|
// FlowyError::internal().context(err_msg)
|
||||||
})?;
|
// })?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -59,9 +59,9 @@ impl ClientGridEditor {
|
|||||||
grid_id,
|
grid_id,
|
||||||
} = params;
|
} = params;
|
||||||
let field_id = field.id.clone();
|
let field_id = field.id.clone();
|
||||||
let _ = self
|
if self.contain_field(&field_id).await {
|
||||||
.modify(|grid| {
|
let _ = self
|
||||||
if grid.contain_field(&field.id) {
|
.modify(|grid| {
|
||||||
let deserializer = TypeOptionJsonDeserializer(field.field_type.clone());
|
let deserializer = TypeOptionJsonDeserializer(field.field_type.clone());
|
||||||
let changeset = FieldChangesetParams {
|
let changeset = FieldChangesetParams {
|
||||||
field_id: field.id,
|
field_id: field.id,
|
||||||
@ -74,17 +74,22 @@ impl ClientGridEditor {
|
|||||||
width: Some(field.width),
|
width: Some(field.width),
|
||||||
type_option_data: Some(type_option_data),
|
type_option_data: Some(type_option_data),
|
||||||
};
|
};
|
||||||
Ok(grid.update_field(changeset, deserializer)?)
|
Ok(grid.update_field_meta(changeset, deserializer)?)
|
||||||
} else {
|
})
|
||||||
// let type_option_json = type_option_json_str_from_bytes(type_option_data, &field.field_type);
|
.await?;
|
||||||
|
let _ = self.notify_grid_did_update_field(&field_id).await?;
|
||||||
|
} else {
|
||||||
|
let _ = self
|
||||||
|
.modify(|grid| {
|
||||||
let builder = type_option_builder_from_bytes(type_option_data, &field.field_type);
|
let builder = type_option_builder_from_bytes(type_option_data, &field.field_type);
|
||||||
let field_meta = FieldBuilder::from_field(field, builder).build();
|
let field_meta = FieldBuilder::from_field(field, builder).build();
|
||||||
Ok(grid.create_field(field_meta, start_field_id)?)
|
|
||||||
}
|
Ok(grid.create_field_meta(field_meta, start_field_id)?)
|
||||||
})
|
})
|
||||||
.await?;
|
.await?;
|
||||||
let _ = self.notify_did_update_grid().await?;
|
let _ = self.notify_grid_did_insert_field(&field_id).await?;
|
||||||
let _ = self.notify_did_update_field(&field_id).await?;
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,29 +105,31 @@ impl ClientGridEditor {
|
|||||||
|
|
||||||
pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> {
|
pub async fn update_field(&self, params: FieldChangesetParams) -> FlowyResult<()> {
|
||||||
let field_id = params.field_id.clone();
|
let field_id = params.field_id.clone();
|
||||||
let json_deserializer = match self.pad.read().await.get_field(params.field_id.as_str()) {
|
let json_deserializer = match self.pad.read().await.get_field_meta(params.field_id.as_str()) {
|
||||||
None => return Err(ErrorCode::FieldDoesNotExist.into()),
|
None => return Err(ErrorCode::FieldDoesNotExist.into()),
|
||||||
Some(field_meta) => TypeOptionJsonDeserializer(field_meta.field_type.clone()),
|
Some((_, field_meta)) => TypeOptionJsonDeserializer(field_meta.field_type.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
let _ = self
|
let _ = self
|
||||||
.modify(|grid| Ok(grid.update_field(params, json_deserializer)?))
|
.modify(|grid| Ok(grid.update_field_meta(params, json_deserializer)?))
|
||||||
.await?;
|
.await?;
|
||||||
let _ = self.notify_did_update_grid().await?;
|
|
||||||
let _ = self.notify_did_update_field(&field_id).await?;
|
let _ = self.notify_grid_did_update_field(&field_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn replace_field(&self, field_meta: FieldMeta) -> FlowyResult<()> {
|
pub async fn replace_field(&self, field_meta: FieldMeta) -> FlowyResult<()> {
|
||||||
let field_id = field_meta.id.clone();
|
let field_id = field_meta.id.clone();
|
||||||
let _ = self.modify(|pad| Ok(pad.replace_field(field_meta)?)).await?;
|
let _ = self.modify(|pad| Ok(pad.replace_field_meta(field_meta)?)).await?;
|
||||||
let _ = self.notify_did_update_field(&field_id).await?;
|
let _ = self.notify_grid_did_update_field(&field_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn delete_field(&self, field_id: &str) -> FlowyResult<()> {
|
pub async fn delete_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
let _ = self.modify(|grid| Ok(grid.delete_field(field_id)?)).await?;
|
let _ = self.modify(|grid| Ok(grid.delete_field_meta(field_id)?)).await?;
|
||||||
let _ = self.notify_did_update_grid().await?;
|
let field_order = FieldOrder::from(field_id);
|
||||||
|
let notified_changeset = GridFieldChangeset::delete(&self.grid_id, vec![field_order]);
|
||||||
|
let _ = self.notify_did_update_grid(notified_changeset).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,27 +152,24 @@ impl ClientGridEditor {
|
|||||||
let _ = self
|
let _ = self
|
||||||
.modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?))
|
.modify(|grid| Ok(grid.switch_to_field(field_id, field_type.clone(), type_option_json_builder)?))
|
||||||
.await?;
|
.await?;
|
||||||
let _ = self.notify_did_update_grid().await?;
|
|
||||||
let _ = self.notify_did_update_field(field_id).await?;
|
let _ = self.notify_grid_did_update_field(&field_id).await?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> {
|
pub async fn duplicate_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
let mut duplicated_field_meta = None;
|
let duplicated_field_id = gen_field_id();
|
||||||
let _ = self
|
let _ = self
|
||||||
.modify(|grid| {
|
.modify(|grid| Ok(grid.duplicate_field_meta(field_id, &duplicated_field_id)?))
|
||||||
let (changeset, field_meta) = grid.duplicate_field(field_id)?;
|
|
||||||
duplicated_field_meta = field_meta;
|
|
||||||
Ok(changeset)
|
|
||||||
})
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
let _ = self.notify_did_update_grid().await?;
|
let _ = self.notify_grid_did_insert_field(field_id).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn get_field_meta(&self, field_id: &str) -> Option<FieldMeta> {
|
pub async fn get_field_meta(&self, field_id: &str) -> Option<FieldMeta> {
|
||||||
let field_meta = self.pad.read().await.get_field(field_id)?.clone();
|
let field_meta = self.pad.read().await.get_field_meta(field_id)?.1.clone();
|
||||||
Some(field_meta)
|
Some(field_meta)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -310,12 +314,12 @@ impl ClientGridEditor {
|
|||||||
let cell_data_changeset = changeset.data.unwrap();
|
let cell_data_changeset = changeset.data.unwrap();
|
||||||
let cell_meta = self.get_cell_meta(&changeset.row_id, &changeset.field_id).await?;
|
let cell_meta = self.get_cell_meta(&changeset.row_id, &changeset.field_id).await?;
|
||||||
tracing::trace!("{}: {:?}", &changeset.field_id, cell_meta);
|
tracing::trace!("{}: {:?}", &changeset.field_id, cell_meta);
|
||||||
match self.pad.read().await.get_field(&changeset.field_id) {
|
match self.pad.read().await.get_field_meta(&changeset.field_id) {
|
||||||
None => {
|
None => {
|
||||||
let msg = format!("Field not found with id: {}", &changeset.field_id);
|
let msg = format!("Field not found with id: {}", &changeset.field_id);
|
||||||
Err(FlowyError::internal().context(msg))
|
Err(FlowyError::internal().context(msg))
|
||||||
}
|
}
|
||||||
Some(field_meta) => {
|
Some((_, field_meta)) => {
|
||||||
// Update the changeset.data property with the return value.
|
// Update the changeset.data property with the return value.
|
||||||
changeset.data = Some(apply_cell_data_changeset(cell_data_changeset, cell_meta, field_meta)?);
|
changeset.data = Some(apply_cell_data_changeset(cell_data_changeset, cell_meta, field_meta)?);
|
||||||
let _ = self.block_meta_manager.update_cell(changeset).await?;
|
let _ = self.block_meta_manager.update_cell(changeset).await?;
|
||||||
@ -334,11 +338,6 @@ impl ClientGridEditor {
|
|||||||
Ok(grid_blocks)
|
Ok(grid_blocks)
|
||||||
}
|
}
|
||||||
|
|
||||||
// pub async fn get_field_metas<T>(&self, field_ids: Option<Vec<T>>) -> FlowyResult<Vec<FieldMeta>>
|
|
||||||
// where
|
|
||||||
// T: Into<FieldOrder>,
|
|
||||||
// {
|
|
||||||
|
|
||||||
pub async fn delete_rows(&self, row_orders: Vec<RowOrder>) -> FlowyResult<()> {
|
pub async fn delete_rows(&self, row_orders: Vec<RowOrder>) -> FlowyResult<()> {
|
||||||
let changesets = self.block_meta_manager.delete_rows(row_orders).await?;
|
let changesets = self.block_meta_manager.delete_rows(row_orders).await?;
|
||||||
for changeset in changesets {
|
for changeset in changesets {
|
||||||
@ -445,37 +444,40 @@ impl ClientGridEditor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn notify_did_update_grid(&self) -> FlowyResult<()> {
|
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||||
// GridFieldChangeset
|
async fn notify_grid_did_insert_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
|
if let Some((index, field_meta)) = self.pad.read().await.get_field_meta(field_id) {
|
||||||
let field_metas = self.get_field_metas::<FieldOrder>(None).await?;
|
let index_field = IndexField::from_field_meta(field_meta, index);
|
||||||
let repeated_field: RepeatedField = field_metas.into_iter().map(Field::from).collect::<Vec<_>>().into();
|
let notified_changeset = GridFieldChangeset::insert(&self.grid_id, vec![index_field]);
|
||||||
send_dart_notification(&self.grid_id, GridNotification::DidUpdateGrid)
|
let _ = self.notify_did_update_grid(notified_changeset).await?;
|
||||||
.payload(repeated_field)
|
}
|
||||||
.send();
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn notify_did_update_grid2(&self, changeset: GridFieldChangeset) -> FlowyResult<()> {
|
|
||||||
send_dart_notification(&self.grid_id, GridNotification::DidUpdateGrid)
|
|
||||||
.payload(changeset)
|
|
||||||
.send();
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "trace", skip_all, err)]
|
#[tracing::instrument(level = "trace", skip_all, err)]
|
||||||
async fn notify_did_update_field(&self, field_id: &str) -> FlowyResult<()> {
|
async fn notify_grid_did_update_field(&self, field_id: &str) -> FlowyResult<()> {
|
||||||
let mut field_metas = self.get_field_metas(Some(vec![field_id])).await?;
|
let mut field_metas = self.get_field_metas(Some(vec![field_id])).await?;
|
||||||
debug_assert!(field_metas.len() == 1);
|
debug_assert!(field_metas.len() == 1);
|
||||||
|
|
||||||
if let Some(field_meta) = field_metas.pop() {
|
if let Some(field_meta) = field_metas.pop() {
|
||||||
|
let updated_field = Field::from(field_meta);
|
||||||
|
let notified_changeset = GridFieldChangeset::update(&self.grid_id, vec![updated_field.clone()]);
|
||||||
|
let _ = self.notify_did_update_grid(notified_changeset).await?;
|
||||||
|
|
||||||
send_dart_notification(field_id, GridNotification::DidUpdateField)
|
send_dart_notification(field_id, GridNotification::DidUpdateField)
|
||||||
.payload(Field::from(field_meta))
|
.payload(updated_field)
|
||||||
.send();
|
.send();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn notify_did_update_grid(&self, changeset: GridFieldChangeset) -> FlowyResult<()> {
|
||||||
|
send_dart_notification(&self.grid_id, GridNotification::DidUpdateGrid)
|
||||||
|
.payload(changeset)
|
||||||
|
.send();
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(feature = "flowy_unit_test")]
|
#[cfg(feature = "flowy_unit_test")]
|
||||||
|
@ -133,8 +133,17 @@ pub struct IndexField {
|
|||||||
#[pb(index = 1)]
|
#[pb(index = 1)]
|
||||||
pub field: Field,
|
pub field: Field,
|
||||||
|
|
||||||
#[pb(index = 2, one_of)]
|
#[pb(index = 2)]
|
||||||
pub index: Option<i32>,
|
pub index: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IndexField {
|
||||||
|
pub fn from_field_meta(field_meta: &FieldMeta, index: usize) -> Self {
|
||||||
|
Self {
|
||||||
|
field: Field::from(field_meta.clone()),
|
||||||
|
index: index as i32,
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Default, ProtoBuf)]
|
#[derive(Debug, Default, ProtoBuf)]
|
||||||
|
@ -1128,8 +1128,7 @@ impl ::protobuf::reflect::ProtobufValue for GridFieldChangeset {
|
|||||||
pub struct IndexField {
|
pub struct IndexField {
|
||||||
// message fields
|
// message fields
|
||||||
pub field: ::protobuf::SingularPtrField<Field>,
|
pub field: ::protobuf::SingularPtrField<Field>,
|
||||||
// message oneof groups
|
pub index: i32,
|
||||||
pub one_of_index: ::std::option::Option<IndexField_oneof_one_of_index>,
|
|
||||||
// special fields
|
// special fields
|
||||||
pub unknown_fields: ::protobuf::UnknownFields,
|
pub unknown_fields: ::protobuf::UnknownFields,
|
||||||
pub cached_size: ::protobuf::CachedSize,
|
pub cached_size: ::protobuf::CachedSize,
|
||||||
@ -1141,11 +1140,6 @@ impl<'a> ::std::default::Default for &'a IndexField {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone,PartialEq,Debug)]
|
|
||||||
pub enum IndexField_oneof_one_of_index {
|
|
||||||
index(i32),
|
|
||||||
}
|
|
||||||
|
|
||||||
impl IndexField {
|
impl IndexField {
|
||||||
pub fn new() -> IndexField {
|
pub fn new() -> IndexField {
|
||||||
::std::default::Default::default()
|
::std::default::Default::default()
|
||||||
@ -1188,25 +1182,15 @@ impl IndexField {
|
|||||||
|
|
||||||
|
|
||||||
pub fn get_index(&self) -> i32 {
|
pub fn get_index(&self) -> i32 {
|
||||||
match self.one_of_index {
|
self.index
|
||||||
::std::option::Option::Some(IndexField_oneof_one_of_index::index(v)) => v,
|
|
||||||
_ => 0,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
pub fn clear_index(&mut self) {
|
pub fn clear_index(&mut self) {
|
||||||
self.one_of_index = ::std::option::Option::None;
|
self.index = 0;
|
||||||
}
|
|
||||||
|
|
||||||
pub fn has_index(&self) -> bool {
|
|
||||||
match self.one_of_index {
|
|
||||||
::std::option::Option::Some(IndexField_oneof_one_of_index::index(..)) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Param is passed by value, moved
|
// Param is passed by value, moved
|
||||||
pub fn set_index(&mut self, v: i32) {
|
pub fn set_index(&mut self, v: i32) {
|
||||||
self.one_of_index = ::std::option::Option::Some(IndexField_oneof_one_of_index::index(v))
|
self.index = v;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1231,7 +1215,8 @@ impl ::protobuf::Message for IndexField {
|
|||||||
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
if wire_type != ::protobuf::wire_format::WireTypeVarint {
|
||||||
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
return ::std::result::Result::Err(::protobuf::rt::unexpected_wire_type(wire_type));
|
||||||
}
|
}
|
||||||
self.one_of_index = ::std::option::Option::Some(IndexField_oneof_one_of_index::index(is.read_int32()?));
|
let tmp = is.read_int32()?;
|
||||||
|
self.index = tmp;
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
::protobuf::rt::read_unknown_or_skip_group(field_number, wire_type, is, self.mut_unknown_fields())?;
|
||||||
@ -1249,12 +1234,8 @@ impl ::protobuf::Message for IndexField {
|
|||||||
let len = v.compute_size();
|
let len = v.compute_size();
|
||||||
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
|
my_size += 1 + ::protobuf::rt::compute_raw_varint32_size(len) + len;
|
||||||
}
|
}
|
||||||
if let ::std::option::Option::Some(ref v) = self.one_of_index {
|
if self.index != 0 {
|
||||||
match v {
|
my_size += ::protobuf::rt::value_size(2, self.index, ::protobuf::wire_format::WireTypeVarint);
|
||||||
&IndexField_oneof_one_of_index::index(v) => {
|
|
||||||
my_size += ::protobuf::rt::value_size(2, v, ::protobuf::wire_format::WireTypeVarint);
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
my_size += ::protobuf::rt::unknown_fields_size(self.get_unknown_fields());
|
||||||
self.cached_size.set(my_size);
|
self.cached_size.set(my_size);
|
||||||
@ -1267,12 +1248,8 @@ impl ::protobuf::Message for IndexField {
|
|||||||
os.write_raw_varint32(v.get_cached_size())?;
|
os.write_raw_varint32(v.get_cached_size())?;
|
||||||
v.write_to_with_cached_sizes(os)?;
|
v.write_to_with_cached_sizes(os)?;
|
||||||
}
|
}
|
||||||
if let ::std::option::Option::Some(ref v) = self.one_of_index {
|
if self.index != 0 {
|
||||||
match v {
|
os.write_int32(2, self.index)?;
|
||||||
&IndexField_oneof_one_of_index::index(v) => {
|
|
||||||
os.write_int32(2, v)?;
|
|
||||||
},
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
os.write_unknown_fields(self.get_unknown_fields())?;
|
os.write_unknown_fields(self.get_unknown_fields())?;
|
||||||
::std::result::Result::Ok(())
|
::std::result::Result::Ok(())
|
||||||
@ -1317,10 +1294,10 @@ impl ::protobuf::Message for IndexField {
|
|||||||
|m: &IndexField| { &m.field },
|
|m: &IndexField| { &m.field },
|
||||||
|m: &mut IndexField| { &mut m.field },
|
|m: &mut IndexField| { &mut m.field },
|
||||||
));
|
));
|
||||||
fields.push(::protobuf::reflect::accessor::make_singular_i32_accessor::<_>(
|
fields.push(::protobuf::reflect::accessor::make_simple_field_accessor::<_, ::protobuf::types::ProtobufTypeInt32>(
|
||||||
"index",
|
"index",
|
||||||
IndexField::has_index,
|
|m: &IndexField| { &m.index },
|
||||||
IndexField::get_index,
|
|m: &mut IndexField| { &mut m.index },
|
||||||
));
|
));
|
||||||
::protobuf::reflect::MessageDescriptor::new_pb_name::<IndexField>(
|
::protobuf::reflect::MessageDescriptor::new_pb_name::<IndexField>(
|
||||||
"IndexField",
|
"IndexField",
|
||||||
@ -1339,7 +1316,7 @@ impl ::protobuf::Message for IndexField {
|
|||||||
impl ::protobuf::Clear for IndexField {
|
impl ::protobuf::Clear for IndexField {
|
||||||
fn clear(&mut self) {
|
fn clear(&mut self) {
|
||||||
self.field.clear();
|
self.field.clear();
|
||||||
self.one_of_index = ::std::option::Option::None;
|
self.index = 0;
|
||||||
self.unknown_fields.clear();
|
self.unknown_fields.clear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7803,83 +7780,83 @@ static file_descriptor_proto_data: &'static [u8] = b"\
|
|||||||
\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x124\n\x0finserted_field\
|
\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x124\n\x0finserted_field\
|
||||||
s\x18\x02\x20\x03(\x0b2\x0b.IndexFieldR\x0einsertedFields\x122\n\x0edele\
|
s\x18\x02\x20\x03(\x0b2\x0b.IndexFieldR\x0einsertedFields\x122\n\x0edele\
|
||||||
ted_fields\x18\x03\x20\x03(\x0b2\x0b.FieldOrderR\rdeletedFields\x12-\n\
|
ted_fields\x18\x03\x20\x03(\x0b2\x0b.FieldOrderR\rdeletedFields\x12-\n\
|
||||||
\x0eupdated_fields\x18\x04\x20\x03(\x0b2\x06.FieldR\rupdatedFields\"R\n\
|
\x0eupdated_fields\x18\x04\x20\x03(\x0b2\x06.FieldR\rupdatedFields\"@\n\
|
||||||
\nIndexField\x12\x1c\n\x05field\x18\x01\x20\x01(\x0b2\x06.FieldR\x05fiel\
|
\nIndexField\x12\x1c\n\x05field\x18\x01\x20\x01(\x0b2\x06.FieldR\x05fiel\
|
||||||
d\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\x0e\n\x0cone_of_\
|
d\x12\x14\n\x05index\x18\x02\x20\x01(\x05R\x05index\"\x90\x01\n\x1aGetEd\
|
||||||
index\"\x90\x01\n\x1aGetEditFieldContextPayload\x12\x17\n\x07grid_id\x18\
|
itFieldContextPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\
|
||||||
\x01\x20\x01(\tR\x06gridId\x12\x1b\n\x08field_id\x18\x02\x20\x01(\tH\0R\
|
\x12\x1b\n\x08field_id\x18\x02\x20\x01(\tH\0R\x07fieldId\x12)\n\nfield_t\
|
||||||
\x07fieldId\x12)\n\nfield_type\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfield\
|
ype\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldTypeB\x11\n\x0fone_of_field\
|
||||||
TypeB\x11\n\x0fone_of_field_id\"q\n\x10EditFieldPayload\x12\x17\n\x07gri\
|
_id\"q\n\x10EditFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
|
||||||
d_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01\
|
\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\x12)\n\n\
|
||||||
(\tR\x07fieldId\x12)\n\nfield_type\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tf\
|
field_type\x18\x03\x20\x01(\x0e2\n.FieldTypeR\tfieldType\"|\n\x10EditFie\
|
||||||
ieldType\"|\n\x10EditFieldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\
|
ldContext\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12%\n\ngri\
|
||||||
\tR\x06gridId\x12%\n\ngrid_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridF\
|
d_field\x18\x02\x20\x01(\x0b2\x06.FieldR\tgridField\x12(\n\x10type_optio\
|
||||||
ield\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\
|
n_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\"-\n\rRepeatedField\x12\
|
||||||
\"-\n\rRepeatedField\x12\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\
|
\x1c\n\x05items\x18\x01\x20\x03(\x0b2\x06.FieldR\x05items\"7\n\x12Repeat\
|
||||||
\x05items\"7\n\x12RepeatedFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\
|
edFieldOrder\x12!\n\x05items\x18\x01\x20\x03(\x0b2\x0b.FieldOrderR\x05it\
|
||||||
\x0b2\x0b.FieldOrderR\x05items\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\
|
ems\"T\n\x08RowOrder\x12\x15\n\x06row_id\x18\x01\x20\x01(\tR\x05rowId\
|
||||||
\x01\x20\x01(\tR\x05rowId\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07b\
|
\x12\x19\n\x08block_id\x18\x02\x20\x01(\tR\x07blockId\x12\x16\n\x06heigh\
|
||||||
lockId\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\
|
t\x18\x03\x20\x01(\x05R\x06height\"\xb8\x01\n\x03Row\x12\x0e\n\x02id\x18\
|
||||||
\x03Row\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_fiel\
|
\x01\x20\x01(\tR\x02id\x12@\n\x10cell_by_field_id\x18\x02\x20\x03(\x0b2\
|
||||||
d_id\x18\x02\x20\x03(\x0b2\x17.Row.CellByFieldIdEntryR\rcellByFieldId\
|
\x17.Row.CellByFieldIdEntryR\rcellByFieldId\x12\x16\n\x06height\x18\x03\
|
||||||
\x12\x16\n\x06height\x18\x03\x20\x01(\x05R\x06height\x1aG\n\x12CellByFie\
|
\x20\x01(\x05R\x06height\x1aG\n\x12CellByFieldIdEntry\x12\x10\n\x03key\
|
||||||
ldIdEntry\x12\x10\n\x03key\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\
|
\x18\x01\x20\x01(\tR\x03key\x12\x1b\n\x05value\x18\x02\x20\x01(\x0b2\x05\
|
||||||
\x18\x02\x20\x01(\x0b2\x05.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\
|
.CellR\x05value:\x028\x01\")\n\x0bRepeatedRow\x12\x1a\n\x05items\x18\x01\
|
||||||
\x12\x1a\n\x05items\x18\x01\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11Repe\
|
\x20\x03(\x0b2\x04.RowR\x05items\"5\n\x11RepeatedGridBlock\x12\x20\n\x05\
|
||||||
atedGridBlock\x12\x20\n\x05items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05i\
|
items\x18\x01\x20\x03(\x0b2\n.GridBlockR\x05items\"U\n\x0eGridBlockOrder\
|
||||||
tems\"U\n\x0eGridBlockOrder\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\
|
\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blockId\x12(\n\nrow_orders\
|
||||||
\x07blockId\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrd\
|
\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\"_\n\rIndexRowOrder\x12&\n\
|
||||||
ers\"_\n\rIndexRowOrder\x12&\n\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrd\
|
\trow_order\x18\x01\x20\x01(\x0b2\t.RowOrderR\x08rowOrder\x12\x16\n\x05i\
|
||||||
erR\x08rowOrder\x12\x16\n\x05index\x18\x02\x20\x01(\x05H\0R\x05indexB\
|
ndex\x18\x02\x20\x01(\x05H\0R\x05indexB\x0e\n\x0cone_of_index\"\xbf\x01\
|
||||||
\x0e\n\x0cone_of_index\"\xbf\x01\n\x11GridRowsChangeset\x12\x19\n\x08blo\
|
\n\x11GridRowsChangeset\x12\x19\n\x08block_id\x18\x01\x20\x01(\tR\x07blo\
|
||||||
ck_id\x18\x01\x20\x01(\tR\x07blockId\x123\n\rinserted_rows\x18\x02\x20\
|
ckId\x123\n\rinserted_rows\x18\x02\x20\x03(\x0b2\x0e.IndexRowOrderR\x0ci\
|
||||||
\x03(\x0b2\x0e.IndexRowOrderR\x0cinsertedRows\x12,\n\x0cdeleted_rows\x18\
|
nsertedRows\x12,\n\x0cdeleted_rows\x18\x03\x20\x03(\x0b2\t.RowOrderR\x0b\
|
||||||
\x03\x20\x03(\x0b2\t.RowOrderR\x0bdeletedRows\x12,\n\x0cupdated_rows\x18\
|
deletedRows\x12,\n\x0cupdated_rows\x18\x04\x20\x03(\x0b2\t.RowOrderR\x0b\
|
||||||
\x04\x20\x03(\x0b2\t.RowOrderR\x0bupdatedRows\"E\n\tGridBlock\x12\x0e\n\
|
updatedRows\"E\n\tGridBlock\x12\x0e\n\x02id\x18\x01\x20\x01(\tR\x02id\
|
||||||
\x02id\x18\x01\x20\x01(\tR\x02id\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b\
|
\x12(\n\nrow_orders\x18\x02\x20\x03(\x0b2\t.RowOrderR\trowOrders\";\n\
|
||||||
2\t.RowOrderR\trowOrders\";\n\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\
|
\x04Cell\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x18\n\
|
||||||
\x01(\tR\x07fieldId\x12\x18\n\x07content\x18\x02\x20\x01(\tR\x07content\
|
\x07content\x18\x02\x20\x01(\tR\x07content\"\x8f\x01\n\x14CellNotificati\
|
||||||
\"\x8f\x01\n\x14CellNotificationData\x12\x17\n\x07grid_id\x18\x01\x20\
|
onData\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x19\n\x08f\
|
||||||
\x01(\tR\x06gridId\x12\x19\n\x08field_id\x18\x02\x20\x01(\tR\x07fieldId\
|
ield_id\x18\x02\x20\x01(\tR\x07fieldId\x12\x15\n\x06row_id\x18\x03\x20\
|
||||||
\x12\x15\n\x06row_id\x18\x03\x20\x01(\tR\x05rowId\x12\x1a\n\x07content\
|
\x01(\tR\x05rowId\x12\x1a\n\x07content\x18\x04\x20\x01(\tH\0R\x07content\
|
||||||
\x18\x04\x20\x01(\tH\0R\x07contentB\x10\n\x0eone_of_content\"+\n\x0cRepe\
|
B\x10\n\x0eone_of_content\"+\n\x0cRepeatedCell\x12\x1b\n\x05items\x18\
|
||||||
atedCell\x12\x1b\n\x05items\x18\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\
|
\x01\x20\x03(\x0b2\x05.CellR\x05items\"'\n\x11CreateGridPayload\x12\x12\
|
||||||
\n\x11CreateGridPayload\x12\x12\n\x04name\x18\x01\x20\x01(\tR\x04name\"\
|
\n\x04name\x18\x01\x20\x01(\tR\x04name\"\x1e\n\x06GridId\x12\x14\n\x05va\
|
||||||
\x1e\n\x06GridId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"#\n\
|
lue\x18\x01\x20\x01(\tR\x05value\"#\n\x0bGridBlockId\x12\x14\n\x05value\
|
||||||
\x0bGridBlockId\x12\x14\n\x05value\x18\x01\x20\x01(\tR\x05value\"f\n\x10\
|
\x18\x01\x20\x01(\tR\x05value\"f\n\x10CreateRowPayload\x12\x17\n\x07grid\
|
||||||
CreateRowPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\
|
_id\x18\x01\x20\x01(\tR\x06gridId\x12\"\n\x0cstart_row_id\x18\x02\x20\
|
||||||
\"\n\x0cstart_row_id\x18\x02\x20\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of\
|
\x01(\tH\0R\nstartRowIdB\x15\n\x13one_of_start_row_id\"\xb6\x01\n\x12Ins\
|
||||||
_start_row_id\"\xb6\x01\n\x12InsertFieldPayload\x12\x17\n\x07grid_id\x18\
|
ertFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\
|
||||||
\x01\x20\x01(\tR\x06gridId\x12\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.\
|
\x1c\n\x05field\x18\x02\x20\x01(\x0b2\x06.FieldR\x05field\x12(\n\x10type\
|
||||||
FieldR\x05field\x12(\n\x10type_option_data\x18\x03\x20\x01(\x0cR\x0etype\
|
_option_data\x18\x03\x20\x01(\x0cR\x0etypeOptionData\x12&\n\x0estart_fie\
|
||||||
OptionData\x12&\n\x0estart_field_id\x18\x04\x20\x01(\tH\0R\x0cstartField\
|
ld_id\x18\x04\x20\x01(\tH\0R\x0cstartFieldIdB\x17\n\x15one_of_start_fiel\
|
||||||
IdB\x17\n\x15one_of_start_field_id\"d\n\x11QueryFieldPayload\x12\x17\n\
|
d_id\"d\n\x11QueryFieldPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
|
||||||
\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x126\n\x0cfield_orders\x18\x02\
|
\x06gridId\x126\n\x0cfield_orders\x18\x02\x20\x01(\x0b2\x13.RepeatedFiel\
|
||||||
\x20\x01(\x0b2\x13.RepeatedFieldOrderR\x0bfieldOrders\"e\n\x16QueryGridB\
|
dOrderR\x0bfieldOrders\"e\n\x16QueryGridBlocksPayload\x12\x17\n\x07grid_\
|
||||||
locksPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x122\n\
|
id\x18\x01\x20\x01(\tR\x06gridId\x122\n\x0cblock_orders\x18\x02\x20\x03(\
|
||||||
\x0cblock_orders\x18\x02\x20\x03(\x0b2\x0f.GridBlockOrderR\x0bblockOrder\
|
\x0b2\x0f.GridBlockOrderR\x0bblockOrders\"\xa8\x03\n\x15FieldChangesetPa\
|
||||||
s\"\xa8\x03\n\x15FieldChangesetPayload\x12\x19\n\x08field_id\x18\x01\x20\
|
yload\x12\x19\n\x08field_id\x18\x01\x20\x01(\tR\x07fieldId\x12\x17\n\x07\
|
||||||
\x01(\tR\x07fieldId\x12\x17\n\x07grid_id\x18\x02\x20\x01(\tR\x06gridId\
|
grid_id\x18\x02\x20\x01(\tR\x06gridId\x12\x14\n\x04name\x18\x03\x20\x01(\
|
||||||
\x12\x14\n\x04name\x18\x03\x20\x01(\tH\0R\x04name\x12\x14\n\x04desc\x18\
|
\tH\0R\x04name\x12\x14\n\x04desc\x18\x04\x20\x01(\tH\x01R\x04desc\x12+\n\
|
||||||
\x04\x20\x01(\tH\x01R\x04desc\x12+\n\nfield_type\x18\x05\x20\x01(\x0e2\n\
|
\nfield_type\x18\x05\x20\x01(\x0e2\n.FieldTypeH\x02R\tfieldType\x12\x18\
|
||||||
.FieldTypeH\x02R\tfieldType\x12\x18\n\x06frozen\x18\x06\x20\x01(\x08H\
|
\n\x06frozen\x18\x06\x20\x01(\x08H\x03R\x06frozen\x12\x20\n\nvisibility\
|
||||||
\x03R\x06frozen\x12\x20\n\nvisibility\x18\x07\x20\x01(\x08H\x04R\nvisibi\
|
\x18\x07\x20\x01(\x08H\x04R\nvisibility\x12\x16\n\x05width\x18\x08\x20\
|
||||||
lity\x12\x16\n\x05width\x18\x08\x20\x01(\x05H\x05R\x05width\x12*\n\x10ty\
|
\x01(\x05H\x05R\x05width\x12*\n\x10type_option_data\x18\t\x20\x01(\x0cH\
|
||||||
pe_option_data\x18\t\x20\x01(\x0cH\x06R\x0etypeOptionDataB\r\n\x0bone_of\
|
\x06R\x0etypeOptionDataB\r\n\x0bone_of_nameB\r\n\x0bone_of_descB\x13\n\
|
||||||
_nameB\r\n\x0bone_of_descB\x13\n\x11one_of_field_typeB\x0f\n\rone_of_fro\
|
\x11one_of_field_typeB\x0f\n\rone_of_frozenB\x13\n\x11one_of_visibilityB\
|
||||||
zenB\x13\n\x11one_of_visibilityB\x0e\n\x0cone_of_widthB\x19\n\x17one_of_\
|
\x0e\n\x0cone_of_widthB\x19\n\x17one_of_type_option_data\"\x9c\x01\n\x0f\
|
||||||
type_option_data\"\x9c\x01\n\x0fMoveItemPayload\x12\x17\n\x07grid_id\x18\
|
MoveItemPayload\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\
|
||||||
\x01\x20\x01(\tR\x06gridId\x12\x17\n\x07item_id\x18\x02\x20\x01(\tR\x06i\
|
\x17\n\x07item_id\x18\x02\x20\x01(\tR\x06itemId\x12\x1d\n\nfrom_index\
|
||||||
temId\x12\x1d\n\nfrom_index\x18\x03\x20\x01(\x05R\tfromIndex\x12\x19\n\
|
\x18\x03\x20\x01(\x05R\tfromIndex\x12\x19\n\x08to_index\x18\x04\x20\x01(\
|
||||||
\x08to_index\x18\x04\x20\x01(\x05R\x07toIndex\x12\x1d\n\x02ty\x18\x05\
|
\x05R\x07toIndex\x12\x1d\n\x02ty\x18\x05\x20\x01(\x0e2\r.MoveItemTypeR\
|
||||||
\x20\x01(\x0e2\r.MoveItemTypeR\x02ty\"\x7f\n\rCellChangeset\x12\x17\n\
|
\x02ty\"\x7f\n\rCellChangeset\x12\x17\n\x07grid_id\x18\x01\x20\x01(\tR\
|
||||||
\x07grid_id\x18\x01\x20\x01(\tR\x06gridId\x12\x15\n\x06row_id\x18\x02\
|
\x06gridId\x12\x15\n\x06row_id\x18\x02\x20\x01(\tR\x05rowId\x12\x19\n\
|
||||||
\x20\x01(\tR\x05rowId\x12\x19\n\x08field_id\x18\x03\x20\x01(\tR\x07field\
|
\x08field_id\x18\x03\x20\x01(\tR\x07fieldId\x12\x14\n\x04data\x18\x04\
|
||||||
Id\x12\x14\n\x04data\x18\x04\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data*\
|
\x20\x01(\tH\0R\x04dataB\r\n\x0bone_of_data**\n\x0cMoveItemType\x12\r\n\
|
||||||
*\n\x0cMoveItemType\x12\r\n\tMoveField\x10\0\x12\x0b\n\x07MoveRow\x10\
|
\tMoveField\x10\0\x12\x0b\n\x07MoveRow\x10\x01*d\n\tFieldType\x12\x0c\n\
|
||||||
\x01*d\n\tFieldType\x12\x0c\n\x08RichText\x10\0\x12\n\n\x06Number\x10\
|
\x08RichText\x10\0\x12\n\n\x06Number\x10\x01\x12\x0c\n\x08DateTime\x10\
|
||||||
\x01\x12\x0c\n\x08DateTime\x10\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\
|
\x02\x12\x10\n\x0cSingleSelect\x10\x03\x12\x0f\n\x0bMultiSelect\x10\x04\
|
||||||
\x0f\n\x0bMultiSelect\x10\x04\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\
|
\x12\x0c\n\x08Checkbox\x10\x05b\x06proto3\
|
||||||
";
|
";
|
||||||
|
|
||||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||||
|
@ -25,7 +25,7 @@ message GridFieldChangeset {
|
|||||||
}
|
}
|
||||||
message IndexField {
|
message IndexField {
|
||||||
Field field = 1;
|
Field field = 1;
|
||||||
oneof one_of_index { int32 index = 2; };
|
int32 index = 2;
|
||||||
}
|
}
|
||||||
message GetEditFieldContextPayload {
|
message GetEditFieldContextPayload {
|
||||||
string grid_id = 1;
|
string grid_id = 1;
|
||||||
|
@ -4,11 +4,12 @@ use crate::util::{cal_diff, make_delta_from_revisions};
|
|||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use flowy_grid_data_model::entities::{
|
use flowy_grid_data_model::entities::{
|
||||||
gen_field_id, gen_grid_id, FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockMeta,
|
gen_field_id, gen_grid_id, FieldChangesetParams, FieldMeta, FieldOrder, FieldType, GridBlockMeta,
|
||||||
GridBlockMetaChangeset, GridMeta,
|
GridBlockMetaChangeset, GridMeta, IndexField,
|
||||||
};
|
};
|
||||||
use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
use lib_ot::core::{OperationTransformable, PlainTextAttributes, PlainTextDelta, PlainTextDeltaBuilder};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use futures::StreamExt;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub type GridMetaDelta = PlainTextDelta;
|
pub type GridMetaDelta = PlainTextDelta;
|
||||||
@ -41,7 +42,7 @@ impl GridMetaPad {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tracing::instrument(level = "debug", skip_all, err)]
|
#[tracing::instrument(level = "debug", skip_all, err)]
|
||||||
pub fn create_field(
|
pub fn create_field_meta(
|
||||||
&mut self,
|
&mut self,
|
||||||
new_field_meta: FieldMeta,
|
new_field_meta: FieldMeta,
|
||||||
start_field_id: Option<String>,
|
start_field_id: Option<String>,
|
||||||
@ -70,7 +71,7 @@ impl GridMetaPad {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn delete_field(&mut self, field_id: &str) -> CollaborateResult<Option<GridChangeset>> {
|
pub fn delete_field_meta(&mut self, field_id: &str) -> CollaborateResult<Option<GridChangeset>> {
|
||||||
self.modify_grid(
|
self.modify_grid(
|
||||||
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
|
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
@ -82,23 +83,23 @@ impl GridMetaPad {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn duplicate_field(&mut self, field_id: &str) -> CollaborateResult<(Option<GridChangeset>, Option<FieldMeta>)> {
|
pub fn duplicate_field_meta(
|
||||||
let mut field_meta = None;
|
&mut self,
|
||||||
let changeset =
|
field_id: &str,
|
||||||
self.modify_grid(
|
duplicated_field_id: &str,
|
||||||
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
|
) -> CollaborateResult<Option<GridChangeset>> {
|
||||||
None => Ok(None),
|
self.modify_grid(
|
||||||
Some(index) => {
|
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_id) {
|
||||||
let mut duplicate_field_meta = grid_meta.fields[index].clone();
|
None => Ok(None),
|
||||||
duplicate_field_meta.id = gen_field_id();
|
Some(index) => {
|
||||||
duplicate_field_meta.name = format!("{} (copy)", duplicate_field_meta.name);
|
let mut duplicate_field_meta = grid_meta.fields[index].clone();
|
||||||
field_meta = Some(duplicate_field_meta.clone());
|
duplicate_field_meta.id = duplicated_field_id.to_string();
|
||||||
grid_meta.fields.insert(index + 1, duplicate_field_meta);
|
duplicate_field_meta.name = format!("{} (copy)", duplicate_field_meta.name);
|
||||||
Ok(Some(()))
|
grid_meta.fields.insert(index + 1, duplicate_field_meta);
|
||||||
}
|
Ok(Some(()))
|
||||||
},
|
}
|
||||||
)?;
|
},
|
||||||
Ok((changeset, field_meta))
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn switch_to_field<B>(
|
pub fn switch_to_field<B>(
|
||||||
@ -130,7 +131,7 @@ impl GridMetaPad {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn update_field<T: JsonDeserializer>(
|
pub fn update_field_meta<T: JsonDeserializer>(
|
||||||
&mut self,
|
&mut self,
|
||||||
changeset: FieldChangesetParams,
|
changeset: FieldChangesetParams,
|
||||||
deserializer: T,
|
deserializer: T,
|
||||||
@ -185,11 +186,15 @@ impl GridMetaPad {
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn get_field(&self, field_id: &str) -> Option<&FieldMeta> {
|
pub fn get_field_meta(&self, field_id: &str) -> Option<(usize, &FieldMeta)> {
|
||||||
self.grid_meta.fields.iter().find(|field| field.id == field_id)
|
self.grid_meta
|
||||||
|
.fields
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.find(|(_, field)| field.id == field_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn replace_field(&mut self, field_meta: FieldMeta) -> CollaborateResult<Option<GridChangeset>> {
|
pub fn replace_field_meta(&mut self, field_meta: FieldMeta) -> CollaborateResult<Option<GridChangeset>> {
|
||||||
self.modify_grid(
|
self.modify_grid(
|
||||||
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_meta.id) {
|
|grid_meta| match grid_meta.fields.iter().position(|field| field.id == field_meta.id) {
|
||||||
None => Ok(None),
|
None => Ok(None),
|
||||||
|
Loading…
x
Reference in New Issue
Block a user