mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: config row action sheet
This commit is contained in:
parent
ed10ebac7a
commit
b93feb49c3
@ -174,6 +174,10 @@
|
||||
"addOption": "Add option",
|
||||
"editProperty": "Edit property"
|
||||
},
|
||||
"row": {
|
||||
"duplicate": "Duplicate",
|
||||
"delete": "Delete"
|
||||
},
|
||||
"selectOption": {
|
||||
"purpleColor": "Purple",
|
||||
"pinkColor": "Pink",
|
||||
|
@ -154,7 +154,6 @@ void _resolveGridDeps(GetIt getIt) {
|
||||
getIt.registerFactoryParam<RowBloc, RowData, void>(
|
||||
(data, _) => RowBloc(
|
||||
rowData: data,
|
||||
rowlistener: RowListener(rowId: data.rowId),
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -5,14 +5,14 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:async';
|
||||
import 'field_service.dart';
|
||||
|
||||
part 'action_sheet_bloc.freezed.dart';
|
||||
part 'field_action_sheet_bloc.freezed.dart';
|
||||
|
||||
class FieldActionSheetBloc extends Bloc<ActionSheetEvent, ActionSheetState> {
|
||||
class FieldActionSheetBloc extends Bloc<FieldActionSheetEvent, FieldActionSheetState> {
|
||||
final FieldService service;
|
||||
|
||||
FieldActionSheetBloc({required Field field, required this.service})
|
||||
: super(ActionSheetState.initial(EditFieldContext.create()..gridField = field)) {
|
||||
on<ActionSheetEvent>(
|
||||
: super(FieldActionSheetState.initial(EditFieldContext.create()..gridField = field)) {
|
||||
on<FieldActionSheetEvent>(
|
||||
(event, emit) async {
|
||||
await event.map(
|
||||
updateFieldName: (_UpdateFieldName value) async {
|
||||
@ -56,23 +56,23 @@ class FieldActionSheetBloc extends Bloc<ActionSheetEvent, ActionSheetState> {
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ActionSheetEvent with _$ActionSheetEvent {
|
||||
const factory ActionSheetEvent.updateFieldName(String name) = _UpdateFieldName;
|
||||
const factory ActionSheetEvent.hideField() = _HideField;
|
||||
const factory ActionSheetEvent.duplicateField() = _DuplicateField;
|
||||
const factory ActionSheetEvent.deleteField() = _DeleteField;
|
||||
const factory ActionSheetEvent.saveField() = _SaveField;
|
||||
class FieldActionSheetEvent with _$FieldActionSheetEvent {
|
||||
const factory FieldActionSheetEvent.updateFieldName(String name) = _UpdateFieldName;
|
||||
const factory FieldActionSheetEvent.hideField() = _HideField;
|
||||
const factory FieldActionSheetEvent.duplicateField() = _DuplicateField;
|
||||
const factory FieldActionSheetEvent.deleteField() = _DeleteField;
|
||||
const factory FieldActionSheetEvent.saveField() = _SaveField;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ActionSheetState with _$ActionSheetState {
|
||||
const factory ActionSheetState({
|
||||
class FieldActionSheetState with _$FieldActionSheetState {
|
||||
const factory FieldActionSheetState({
|
||||
required EditFieldContext editContext,
|
||||
required String errorText,
|
||||
required String fieldName,
|
||||
}) = _ActionSheetState;
|
||||
}) = _FieldActionSheetState;
|
||||
|
||||
factory ActionSheetState.initial(EditFieldContext editContext) => ActionSheetState(
|
||||
factory FieldActionSheetState.initial(EditFieldContext editContext) => FieldActionSheetState(
|
||||
editContext: editContext,
|
||||
errorText: '',
|
||||
fieldName: editContext.gridField.name,
|
@ -111,7 +111,6 @@ class GridBloc extends Bloc<GridEvent, GridState> {
|
||||
rows.addAll(gridBlock.rowOrders.map(
|
||||
(rowOrder) => GridBlockRow(
|
||||
gridId: view.id,
|
||||
blockId: gridBlock.id,
|
||||
rowId: rowOrder.rowId,
|
||||
height: rowOrder.height.toDouble(),
|
||||
),
|
||||
|
@ -7,7 +7,7 @@ export 'data.dart';
|
||||
// Field
|
||||
export 'field/field_service.dart';
|
||||
export 'field/grid_header_bloc.dart';
|
||||
export 'field/action_sheet_bloc.dart';
|
||||
export 'field/field_action_sheet_bloc.dart';
|
||||
export 'field/field_editor_bloc.dart';
|
||||
export 'field/field_switch_bloc.dart';
|
||||
|
||||
|
@ -0,0 +1,58 @@
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:async';
|
||||
import 'package:dartz/dartz.dart';
|
||||
|
||||
part 'row_action_sheet_bloc.freezed.dart';
|
||||
|
||||
class RowActionSheetBloc extends Bloc<RowActionSheetEvent, RowActionSheetState> {
|
||||
final RowService _rowService;
|
||||
|
||||
RowActionSheetBloc({required RowData rowData})
|
||||
: _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
||||
super(RowActionSheetState.initial(rowData)) {
|
||||
on<RowActionSheetEvent>(
|
||||
(event, emit) async {
|
||||
await event.map(
|
||||
deleteRow: (_DeleteRow value) async {
|
||||
final result = await _rowService.deleteRow();
|
||||
logResult(result);
|
||||
},
|
||||
duplicateRow: (_DuplicateRow value) async {
|
||||
final result = await _rowService.duplicateRow();
|
||||
logResult(result);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
return super.close();
|
||||
}
|
||||
|
||||
void logResult(Either<Unit, FlowyError> result) {
|
||||
result.fold((l) => null, (err) => Log.error(err));
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class RowActionSheetEvent with _$RowActionSheetEvent {
|
||||
const factory RowActionSheetEvent.duplicateRow() = _DuplicateRow;
|
||||
const factory RowActionSheetEvent.deleteRow() = _DeleteRow;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class RowActionSheetState with _$RowActionSheetState {
|
||||
const factory RowActionSheetState({
|
||||
required RowData rowData,
|
||||
}) = _RowActionSheetState;
|
||||
|
||||
factory RowActionSheetState.initial(RowData rowData) => RowActionSheetState(
|
||||
rowData: rowData,
|
||||
);
|
||||
}
|
@ -1,7 +1,6 @@
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:app_flowy/workspace/application/grid/field/grid_listenr.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/grid_bloc.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';
|
||||
@ -16,19 +15,14 @@ part 'row_bloc.freezed.dart';
|
||||
typedef CellDataMap = LinkedHashMap<String, CellData>;
|
||||
|
||||
class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
final RowService rowService;
|
||||
final RowListener rowlistener;
|
||||
final GridFieldsListener fieldListener;
|
||||
final RowService _rowService;
|
||||
final RowListener _rowlistener;
|
||||
final GridFieldsListener _fieldListener;
|
||||
|
||||
RowBloc({required RowData rowData, required this.rowlistener})
|
||||
: rowService = RowService(
|
||||
gridId: rowData.gridId,
|
||||
blockId: rowData.blockId,
|
||||
rowId: rowData.rowId,
|
||||
),
|
||||
fieldListener = GridFieldsListener(
|
||||
gridId: rowData.gridId,
|
||||
),
|
||||
RowBloc({required RowData rowData})
|
||||
: _rowService = RowService(gridId: rowData.gridId, rowId: rowData.rowId),
|
||||
_fieldListener = GridFieldsListener(gridId: rowData.gridId),
|
||||
_rowlistener = RowListener(rowId: rowData.rowId),
|
||||
super(RowState.initial(rowData)) {
|
||||
on<RowEvent>(
|
||||
(event, emit) async {
|
||||
@ -38,7 +32,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
await _loadRow(emit);
|
||||
},
|
||||
createRow: (_CreateRow value) {
|
||||
rowService.createRow();
|
||||
_rowService.createRow();
|
||||
},
|
||||
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) async {
|
||||
await _handleFieldUpdate(emit, value);
|
||||
@ -52,7 +46,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
}
|
||||
|
||||
void _handleRowUpdate(_DidUpdateRow value, Emitter<RowState> emit) {
|
||||
final CellDataMap cellDataMap = _makeCellDatas(value.row, state.fields);
|
||||
final CellDataMap cellDataMap = _makeCellDatas(value.row, state.rowData.fields);
|
||||
emit(state.copyWith(
|
||||
row: Future(() => Some(value.row)),
|
||||
cellDataMap: Some(cellDataMap),
|
||||
@ -67,39 +61,39 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
);
|
||||
|
||||
emit(state.copyWith(
|
||||
fields: value.fields,
|
||||
rowData: state.rowData.copyWith(fields: value.fields),
|
||||
cellDataMap: Some(cellDataMap),
|
||||
));
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
await rowlistener.stop();
|
||||
await fieldListener.stop();
|
||||
await _rowlistener.stop();
|
||||
await _fieldListener.stop();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
Future<void> _startListening() async {
|
||||
rowlistener.updateRowNotifier.addPublishListener((result) {
|
||||
_rowlistener.updateRowNotifier.addPublishListener((result) {
|
||||
result.fold(
|
||||
(row) => add(RowEvent.didUpdateRow(row)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
|
||||
fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
||||
_fieldListener.updateFieldsNotifier.addPublishListener((result) {
|
||||
result.fold(
|
||||
(fields) => add(RowEvent.didReceiveFieldUpdate(fields)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
|
||||
rowlistener.start();
|
||||
fieldListener.start();
|
||||
_rowlistener.start();
|
||||
_fieldListener.start();
|
||||
}
|
||||
|
||||
Future<void> _loadRow(Emitter<RowState> emit) async {
|
||||
rowService.getRow().then((result) {
|
||||
_rowService.getRow().then((result) {
|
||||
return result.fold(
|
||||
(row) => add(RowEvent.didUpdateRow(row)),
|
||||
(err) => Log.error(err),
|
||||
@ -113,7 +107,7 @@ class RowBloc extends Bloc<RowEvent, RowState> {
|
||||
if (field.visibility) {
|
||||
map[field.id] = CellData(
|
||||
rowId: row.id,
|
||||
gridId: rowService.gridId,
|
||||
gridId: _rowService.gridId,
|
||||
cell: row.cellByFieldId[field.id],
|
||||
field: field,
|
||||
);
|
||||
@ -134,17 +128,13 @@ class RowEvent with _$RowEvent {
|
||||
@freezed
|
||||
class RowState with _$RowState {
|
||||
const factory RowState({
|
||||
required String rowId,
|
||||
required double rowHeight,
|
||||
required List<Field> fields,
|
||||
required RowData rowData,
|
||||
required Future<Option<Row>> row,
|
||||
required Option<CellDataMap> cellDataMap,
|
||||
}) = _RowState;
|
||||
|
||||
factory RowState.initial(RowData data) => RowState(
|
||||
rowId: data.rowId,
|
||||
rowHeight: data.height,
|
||||
fields: data.fields,
|
||||
factory RowState.initial(RowData rowData) => RowState(
|
||||
rowData: rowData,
|
||||
row: Future(() => none()),
|
||||
cellDataMap: none(),
|
||||
);
|
||||
|
@ -10,9 +10,8 @@ part 'row_service.freezed.dart';
|
||||
class RowService {
|
||||
final String gridId;
|
||||
final String rowId;
|
||||
final String blockId;
|
||||
|
||||
RowService({required this.gridId, required this.rowId, required this.blockId});
|
||||
RowService({required this.gridId, required this.rowId});
|
||||
|
||||
Future<Either<Row, FlowyError>> createRow() {
|
||||
CreateRowPayload payload = CreateRowPayload.create()
|
||||
@ -29,6 +28,22 @@ class RowService {
|
||||
|
||||
return GridEventGetRow(payload).send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, FlowyError>> deleteRow() {
|
||||
final payload = RowIdentifierPayload.create()
|
||||
..gridId = gridId
|
||||
..rowId = rowId;
|
||||
|
||||
return GridEventDeleteRow(payload).send();
|
||||
}
|
||||
|
||||
Future<Either<Unit, FlowyError>> duplicateRow() {
|
||||
final payload = RowIdentifierPayload.create()
|
||||
..gridId = gridId
|
||||
..rowId = rowId;
|
||||
|
||||
return GridEventDuplicateRow(payload).send();
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
@ -46,7 +61,6 @@ class RowData with _$RowData {
|
||||
const factory RowData({
|
||||
required String gridId,
|
||||
required String rowId,
|
||||
required String blockId,
|
||||
required List<Field> fields,
|
||||
required double height,
|
||||
}) = _RowData;
|
||||
@ -55,7 +69,6 @@ class RowData with _$RowData {
|
||||
return RowData(
|
||||
gridId: row.gridId,
|
||||
rowId: row.rowId,
|
||||
blockId: row.blockId,
|
||||
fields: fields,
|
||||
height: row.height,
|
||||
);
|
||||
@ -67,7 +80,6 @@ class GridBlockRow with _$GridBlockRow {
|
||||
const factory GridBlockRow({
|
||||
required String gridId,
|
||||
required String rowId,
|
||||
required String blockId,
|
||||
required double height,
|
||||
}) = _GridBlockRow;
|
||||
}
|
||||
|
@ -73,6 +73,7 @@ class FlowyGrid extends StatefulWidget {
|
||||
|
||||
class _FlowyGridState extends State<FlowyGrid> {
|
||||
final _scrollController = GridScrollController();
|
||||
final _key = GlobalKey<SliverAnimatedListState>();
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
@ -91,6 +92,7 @@ class _FlowyGridState extends State<FlowyGrid> {
|
||||
return const Center(child: CircularProgressIndicator.adaptive());
|
||||
}
|
||||
|
||||
// _key.currentState.insertItem(index)
|
||||
final child = BlocBuilder<GridBloc, GridState>(
|
||||
builder: (context, state) {
|
||||
return SizedBox(
|
||||
@ -153,20 +155,24 @@ class _FlowyGridState extends State<FlowyGrid> {
|
||||
return rowChanged;
|
||||
},
|
||||
builder: (context, state) {
|
||||
return SliverList(
|
||||
delegate: SliverChildBuilderDelegate(
|
||||
(context, index) {
|
||||
final blockRow = context.read<GridBloc>().state.rows[index];
|
||||
final fields = context.read<GridBloc>().state.fields;
|
||||
final rowData = RowData.fromBlockRow(blockRow, fields);
|
||||
return GridRowWidget(data: rowData, key: ValueKey(rowData.rowId));
|
||||
},
|
||||
childCount: context.read<GridBloc>().state.rows.length,
|
||||
addRepaintBoundaries: true,
|
||||
addAutomaticKeepAlives: true,
|
||||
),
|
||||
return SliverAnimatedList(
|
||||
key: _key,
|
||||
initialItemCount: context.read<GridBloc>().state.rows.length,
|
||||
itemBuilder: (BuildContext context, int index, Animation<double> animation) {
|
||||
final blockRow = context.read<GridBloc>().state.rows[index];
|
||||
final fields = context.read<GridBloc>().state.fields;
|
||||
final rowData = RowData.fromBlockRow(blockRow, fields);
|
||||
return _renderRow(rowData, animation);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _renderRow(RowData rowData, Animation<double> animation) {
|
||||
return SizeTransition(
|
||||
sizeFactor: animation,
|
||||
child: GridRowWidget(data: rowData, key: ValueKey(rowData.rowId)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ class GridSize {
|
||||
static double get scrollBarSize => 12 * scale;
|
||||
static double get headerHeight => 40 * scale;
|
||||
static double get footerHeight => 40 * scale;
|
||||
static double get leadingHeaderPadding => 30 * scale;
|
||||
static double get leadingHeaderPadding => 50 * scale;
|
||||
static double get trailHeaderPadding => 140 * scale;
|
||||
static double get headerContainerPadding => 0 * scale;
|
||||
static double get cellHPadding => 10 * scale;
|
||||
|
@ -23,7 +23,7 @@ class GridFieldCellActionSheet extends StatelessWidget with FlowyOverlayDelegate
|
||||
child: this,
|
||||
constraints: BoxConstraints.loose(const Size(240, 200)),
|
||||
),
|
||||
identifier: identifier(),
|
||||
identifier: GridFieldCellActionSheet.identifier(),
|
||||
anchorContext: overlayContext,
|
||||
anchorDirection: AnchorDirection.bottomWithLeftAligned,
|
||||
delegate: this,
|
||||
@ -68,7 +68,7 @@ class _EditFieldButton extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return BlocBuilder<FieldActionSheetBloc, ActionSheetState>(
|
||||
return BlocBuilder<FieldActionSheetBloc, FieldActionSheetState>(
|
||||
builder: (context, state) {
|
||||
return SizedBox(
|
||||
height: GridSize.typeOptionItemHeight,
|
||||
@ -100,16 +100,6 @@ class _FieldOperationList extends StatelessWidget {
|
||||
)
|
||||
.toList();
|
||||
|
||||
return FieldOperationList(actions: actions);
|
||||
}
|
||||
}
|
||||
|
||||
class FieldOperationList extends StatelessWidget {
|
||||
final List<FieldActionCell> actions;
|
||||
const FieldOperationList({required this.actions, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return GridView(
|
||||
// https://api.flutter.dev/flutter/widgets/AnimatedList/shrinkWrap.html
|
||||
shrinkWrap: true,
|
||||
@ -182,13 +172,13 @@ extension _FieldActionExtension on FieldAction {
|
||||
void run(BuildContext context) {
|
||||
switch (this) {
|
||||
case FieldAction.hide:
|
||||
context.read<FieldActionSheetBloc>().add(const ActionSheetEvent.hideField());
|
||||
context.read<FieldActionSheetBloc>().add(const FieldActionSheetEvent.hideField());
|
||||
break;
|
||||
case FieldAction.duplicate:
|
||||
context.read<FieldActionSheetBloc>().add(const ActionSheetEvent.duplicateField());
|
||||
context.read<FieldActionSheetBloc>().add(const FieldActionSheetEvent.duplicateField());
|
||||
break;
|
||||
case FieldAction.delete:
|
||||
context.read<FieldActionSheetBloc>().add(const ActionSheetEvent.deleteField());
|
||||
context.read<FieldActionSheetBloc>().add(const FieldActionSheetEvent.deleteField());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -5,10 +5,13 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/widgets/cell/p
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
import 'row_action_sheet.dart';
|
||||
|
||||
class GridRowWidget extends StatefulWidget {
|
||||
final RowData data;
|
||||
const GridRowWidget({required this.data, Key? key}) : super(key: key);
|
||||
@ -39,10 +42,10 @@ class _GridRowWidgetState extends State<GridRowWidget> {
|
||||
onEnter: (p) => _rowStateNotifier.onEnter = true,
|
||||
onExit: (p) => _rowStateNotifier.onEnter = false,
|
||||
child: BlocBuilder<RowBloc, RowState>(
|
||||
buildWhen: (p, c) => p.rowHeight != c.rowHeight,
|
||||
buildWhen: (p, c) => p.rowData.height != c.rowData.height,
|
||||
builder: (context, state) {
|
||||
return SizedBox(
|
||||
height: _rowBloc.state.rowHeight,
|
||||
height: _rowBloc.state.rowData.height,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: const [
|
||||
@ -83,7 +86,8 @@ class _RowLeading extends StatelessWidget {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: const [
|
||||
AppendRowButton(),
|
||||
_InsertRowButton(),
|
||||
_DeleteRowButton(),
|
||||
],
|
||||
);
|
||||
}
|
||||
@ -98,15 +102,16 @@ class _RowTrailing extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class AppendRowButton extends StatelessWidget {
|
||||
const AppendRowButton({Key? key}) : super(key: key);
|
||||
class _InsertRowButton extends StatelessWidget {
|
||||
const _InsertRowButton({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return FlowyIconButton(
|
||||
hoverColor: theme.hover,
|
||||
width: 22,
|
||||
width: 20,
|
||||
height: 30,
|
||||
onPressed: () => context.read<RowBloc>().add(const RowEvent.createRow()),
|
||||
iconPadding: const EdgeInsets.all(3),
|
||||
icon: svgWidget("home/add"),
|
||||
@ -114,6 +119,25 @@ class AppendRowButton extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _DeleteRowButton extends StatelessWidget {
|
||||
const _DeleteRowButton({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
return FlowyIconButton(
|
||||
hoverColor: theme.hover,
|
||||
width: 20,
|
||||
height: 30,
|
||||
onPressed: () => GridRowActionSheet(
|
||||
rowData: context.read<RowBloc>().state.rowData,
|
||||
).show(context),
|
||||
iconPadding: const EdgeInsets.all(3),
|
||||
icon: svgWidget("editor/details"),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _RowCells extends StatelessWidget {
|
||||
const _RowCells({Key? key}) : super(key: key);
|
||||
|
||||
|
@ -0,0 +1,133 @@
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_action_sheet_bloc.dart';
|
||||
import 'package:app_flowy/workspace/application/grid/row/row_service.dart';
|
||||
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra/theme.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class GridRowActionSheet extends StatelessWidget {
|
||||
final RowData rowData;
|
||||
const GridRowActionSheet({required this.rowData, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider(
|
||||
create: (context) => RowActionSheetBloc(rowData: rowData),
|
||||
child: BlocBuilder<RowActionSheetBloc, RowActionSheetState>(
|
||||
builder: (context, state) {
|
||||
final cells = _RowAction.values
|
||||
.map(
|
||||
(action) => _RowActionCell(
|
||||
action: action,
|
||||
onDismissed: () => remove(context),
|
||||
),
|
||||
)
|
||||
.toList();
|
||||
|
||||
//
|
||||
final list = ListView.separated(
|
||||
shrinkWrap: true,
|
||||
controller: ScrollController(),
|
||||
itemCount: cells.length,
|
||||
separatorBuilder: (context, index) {
|
||||
return VSpace(GridSize.typeOptionSeparatorHeight);
|
||||
},
|
||||
physics: StyledScrollPhysics(),
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return cells[index];
|
||||
},
|
||||
);
|
||||
return list;
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void show(BuildContext overlayContext) {
|
||||
FlowyOverlay.of(overlayContext).insertWithAnchor(
|
||||
widget: OverlayContainer(
|
||||
child: this,
|
||||
constraints: BoxConstraints.loose(const Size(140, 200)),
|
||||
),
|
||||
identifier: GridRowActionSheet.identifier(),
|
||||
anchorContext: overlayContext,
|
||||
anchorDirection: AnchorDirection.leftWithCenterAligned,
|
||||
);
|
||||
}
|
||||
|
||||
void remove(BuildContext overlayContext) {
|
||||
FlowyOverlay.of(overlayContext).remove(GridRowActionSheet.identifier());
|
||||
}
|
||||
|
||||
static String identifier() {
|
||||
return (GridRowActionSheet).toString();
|
||||
}
|
||||
}
|
||||
|
||||
class _RowActionCell extends StatelessWidget {
|
||||
final _RowAction action;
|
||||
final VoidCallback onDismissed;
|
||||
const _RowActionCell({required this.action, required this.onDismissed, Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = context.watch<AppTheme>();
|
||||
|
||||
return SizedBox(
|
||||
height: GridSize.typeOptionItemHeight,
|
||||
child: FlowyButton(
|
||||
text: FlowyText.medium(action.title(), fontSize: 12),
|
||||
hoverColor: theme.hover,
|
||||
onTap: () {
|
||||
action.performAction(context);
|
||||
onDismissed();
|
||||
},
|
||||
leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum _RowAction {
|
||||
delete,
|
||||
duplicate,
|
||||
}
|
||||
|
||||
extension _RowActionExtension on _RowAction {
|
||||
String iconName() {
|
||||
switch (this) {
|
||||
case _RowAction.duplicate:
|
||||
return 'grid/duplicate';
|
||||
case _RowAction.delete:
|
||||
return 'grid/delete';
|
||||
}
|
||||
}
|
||||
|
||||
String title() {
|
||||
switch (this) {
|
||||
case _RowAction.duplicate:
|
||||
return LocaleKeys.grid_row_duplicate.tr();
|
||||
case _RowAction.delete:
|
||||
return LocaleKeys.grid_row_delete.tr();
|
||||
}
|
||||
}
|
||||
|
||||
void performAction(BuildContext context) {
|
||||
switch (this) {
|
||||
case _RowAction.duplicate:
|
||||
// context.read<RowActionSheetBloc>().add(const RowActionSheetEvent.duplicateRow());
|
||||
break;
|
||||
case _RowAction.delete:
|
||||
// context.read<RowActionSheetBloc>().add(const RowActionSheetEvent.deleteRow());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
@ -239,6 +239,40 @@ class GridEventGetRow {
|
||||
}
|
||||
}
|
||||
|
||||
class GridEventDeleteRow {
|
||||
RowIdentifierPayload request;
|
||||
GridEventDeleteRow(this.request);
|
||||
|
||||
Future<Either<Unit, FlowyError>> send() {
|
||||
final request = FFIRequest.create()
|
||||
..event = GridEvent.DeleteRow.toString()
|
||||
..payload = requestToBytes(this.request);
|
||||
|
||||
return Dispatch.asyncRequest(request)
|
||||
.then((bytesResult) => bytesResult.fold(
|
||||
(bytes) => left(unit),
|
||||
(errBytes) => right(FlowyError.fromBuffer(errBytes)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class GridEventDuplicateRow {
|
||||
RowIdentifierPayload request;
|
||||
GridEventDuplicateRow(this.request);
|
||||
|
||||
Future<Either<Unit, FlowyError>> send() {
|
||||
final request = FFIRequest.create()
|
||||
..event = GridEvent.DuplicateRow.toString()
|
||||
..payload = requestToBytes(this.request);
|
||||
|
||||
return Dispatch.asyncRequest(request)
|
||||
.then((bytesResult) => bytesResult.fold(
|
||||
(bytes) => left(unit),
|
||||
(errBytes) => right(FlowyError.fromBuffer(errBytes)),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
class GridEventGetCell {
|
||||
CellIdentifierPayload request;
|
||||
GridEventGetCell(this.request);
|
||||
|
@ -24,6 +24,8 @@ class GridEvent extends $pb.ProtobufEnum {
|
||||
static const GridEvent ApplySelectOptionChangeset = GridEvent._(32, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionChangeset');
|
||||
static const GridEvent CreateRow = GridEvent._(50, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'CreateRow');
|
||||
static const GridEvent GetRow = GridEvent._(51, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetRow');
|
||||
static const GridEvent DeleteRow = GridEvent._(52, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DeleteRow');
|
||||
static const GridEvent DuplicateRow = GridEvent._(53, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'DuplicateRow');
|
||||
static const GridEvent GetCell = GridEvent._(70, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'GetCell');
|
||||
static const GridEvent UpdateCell = GridEvent._(71, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'UpdateCell');
|
||||
static const GridEvent ApplySelectOptionCellChangeset = GridEvent._(72, const $core.bool.fromEnvironment('protobuf.omit_enum_names') ? '' : 'ApplySelectOptionCellChangeset');
|
||||
@ -43,6 +45,8 @@ class GridEvent extends $pb.ProtobufEnum {
|
||||
ApplySelectOptionChangeset,
|
||||
CreateRow,
|
||||
GetRow,
|
||||
DeleteRow,
|
||||
DuplicateRow,
|
||||
GetCell,
|
||||
UpdateCell,
|
||||
ApplySelectOptionCellChangeset,
|
||||
|
@ -26,6 +26,8 @@ const GridEvent$json = const {
|
||||
const {'1': 'ApplySelectOptionChangeset', '2': 32},
|
||||
const {'1': 'CreateRow', '2': 50},
|
||||
const {'1': 'GetRow', '2': 51},
|
||||
const {'1': 'DeleteRow', '2': 52},
|
||||
const {'1': 'DuplicateRow', '2': 53},
|
||||
const {'1': 'GetCell', '2': 70},
|
||||
const {'1': 'UpdateCell', '2': 71},
|
||||
const {'1': 'ApplySelectOptionCellChangeset', '2': 72},
|
||||
@ -33,4 +35,4 @@ const GridEvent$json = const {
|
||||
};
|
||||
|
||||
/// Descriptor for `GridEvent`. Decode as a `google.protobuf.EnumDescriptorProto`.
|
||||
final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSIgoeQXBwbHlTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0EEg=');
|
||||
final $typed_data.Uint8List gridEventDescriptor = $convert.base64Decode('CglHcmlkRXZlbnQSDwoLR2V0R3JpZERhdGEQABIRCg1HZXRHcmlkQmxvY2tzEAESDQoJR2V0RmllbGRzEAoSDwoLVXBkYXRlRmllbGQQCxIPCgtDcmVhdGVGaWVsZBAMEg8KC0RlbGV0ZUZpZWxkEA0SEQoNU3dpdGNoVG9GaWVsZBAOEhIKDkR1cGxpY2F0ZUZpZWxkEA8SFwoTR2V0RWRpdEZpZWxkQ29udGV4dBAQEhMKD05ld1NlbGVjdE9wdGlvbhAeEhoKFkdldFNlbGVjdE9wdGlvbkNvbnRleHQQHxIeChpBcHBseVNlbGVjdE9wdGlvbkNoYW5nZXNldBAgEg0KCUNyZWF0ZVJvdxAyEgoKBkdldFJvdxAzEg0KCURlbGV0ZVJvdxA0EhAKDER1cGxpY2F0ZVJvdxA1EgsKB0dldENlbGwQRhIOCgpVcGRhdGVDZWxsEEcSIgoeQXBwbHlTZWxlY3RPcHRpb25DZWxsQ2hhbmdlc2V0EEg=');
|
||||
|
@ -179,6 +179,22 @@ pub(crate) async fn get_row_handler(
|
||||
}
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, manager), err)]
|
||||
pub(crate) async fn delete_row_handler(
|
||||
data: Data<RowIdentifierPayload>,
|
||||
manager: AppData<Arc<GridManager>>,
|
||||
) -> DataResult<Row, FlowyError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, manager), err)]
|
||||
pub(crate) async fn duplicate_row_handler(
|
||||
data: Data<RowIdentifierPayload>,
|
||||
manager: AppData<Arc<GridManager>>,
|
||||
) -> DataResult<Row, FlowyError> {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[tracing::instrument(level = "debug", skip(data, manager), err)]
|
||||
pub(crate) async fn create_row_handler(
|
||||
data: Data<CreateRowPayload>,
|
||||
|
@ -20,6 +20,8 @@ pub fn create(grid_manager: Arc<GridManager>) -> Module {
|
||||
// Row
|
||||
.event(GridEvent::CreateRow, create_row_handler)
|
||||
.event(GridEvent::GetRow, get_row_handler)
|
||||
.event(GridEvent::DeleteRow, delete_row_handler)
|
||||
.event(GridEvent::DuplicateRow, duplicate_row_handler)
|
||||
// Cell
|
||||
.event(GridEvent::GetCell, get_cell_handler)
|
||||
.event(GridEvent::UpdateCell, update_cell_handler)
|
||||
@ -81,6 +83,12 @@ pub enum GridEvent {
|
||||
#[event(input = "RowIdentifierPayload", output = "Row")]
|
||||
GetRow = 51,
|
||||
|
||||
#[event(input = "RowIdentifierPayload")]
|
||||
DeleteRow = 52,
|
||||
|
||||
#[event(input = "RowIdentifierPayload")]
|
||||
DuplicateRow = 53,
|
||||
|
||||
#[event(input = "CellIdentifierPayload", output = "Cell")]
|
||||
GetCell = 70,
|
||||
|
||||
|
@ -39,6 +39,8 @@ pub enum GridEvent {
|
||||
ApplySelectOptionChangeset = 32,
|
||||
CreateRow = 50,
|
||||
GetRow = 51,
|
||||
DeleteRow = 52,
|
||||
DuplicateRow = 53,
|
||||
GetCell = 70,
|
||||
UpdateCell = 71,
|
||||
ApplySelectOptionCellChangeset = 72,
|
||||
@ -65,6 +67,8 @@ impl ::protobuf::ProtobufEnum for GridEvent {
|
||||
32 => ::std::option::Option::Some(GridEvent::ApplySelectOptionChangeset),
|
||||
50 => ::std::option::Option::Some(GridEvent::CreateRow),
|
||||
51 => ::std::option::Option::Some(GridEvent::GetRow),
|
||||
52 => ::std::option::Option::Some(GridEvent::DeleteRow),
|
||||
53 => ::std::option::Option::Some(GridEvent::DuplicateRow),
|
||||
70 => ::std::option::Option::Some(GridEvent::GetCell),
|
||||
71 => ::std::option::Option::Some(GridEvent::UpdateCell),
|
||||
72 => ::std::option::Option::Some(GridEvent::ApplySelectOptionCellChangeset),
|
||||
@ -88,6 +92,8 @@ impl ::protobuf::ProtobufEnum for GridEvent {
|
||||
GridEvent::ApplySelectOptionChangeset,
|
||||
GridEvent::CreateRow,
|
||||
GridEvent::GetRow,
|
||||
GridEvent::DeleteRow,
|
||||
GridEvent::DuplicateRow,
|
||||
GridEvent::GetCell,
|
||||
GridEvent::UpdateCell,
|
||||
GridEvent::ApplySelectOptionCellChangeset,
|
||||
@ -119,15 +125,16 @@ impl ::protobuf::reflect::ProtobufValue for GridEvent {
|
||||
}
|
||||
|
||||
static file_descriptor_proto_data: &'static [u8] = b"\
|
||||
\n\x0fevent_map.proto*\xde\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
|
||||
\n\x0fevent_map.proto*\xff\x02\n\tGridEvent\x12\x0f\n\x0bGetGridData\x10\
|
||||
\0\x12\x11\n\rGetGridBlocks\x10\x01\x12\r\n\tGetFields\x10\n\x12\x0f\n\
|
||||
\x0bUpdateField\x10\x0b\x12\x0f\n\x0bCreateField\x10\x0c\x12\x0f\n\x0bDe\
|
||||
leteField\x10\r\x12\x11\n\rSwitchToField\x10\x0e\x12\x12\n\x0eDuplicateF\
|
||||
ield\x10\x0f\x12\x17\n\x13GetEditFieldContext\x10\x10\x12\x13\n\x0fNewSe\
|
||||
lectOption\x10\x1e\x12\x1a\n\x16GetSelectOptionContext\x10\x1f\x12\x1e\n\
|
||||
\x1aApplySelectOptionChangeset\x10\x20\x12\r\n\tCreateRow\x102\x12\n\n\
|
||||
\x06GetRow\x103\x12\x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\
|
||||
\"\n\x1eApplySelectOptionCellChangeset\x10Hb\x06proto3\
|
||||
\x06GetRow\x103\x12\r\n\tDeleteRow\x104\x12\x10\n\x0cDuplicateRow\x105\
|
||||
\x12\x0b\n\x07GetCell\x10F\x12\x0e\n\nUpdateCell\x10G\x12\"\n\x1eApplySe\
|
||||
lectOptionCellChangeset\x10Hb\x06proto3\
|
||||
";
|
||||
|
||||
static file_descriptor_proto_lazy: ::protobuf::rt::LazyV2<::protobuf::descriptor::FileDescriptorProto> = ::protobuf::rt::LazyV2::INIT;
|
||||
|
@ -15,6 +15,8 @@ enum GridEvent {
|
||||
ApplySelectOptionChangeset = 32;
|
||||
CreateRow = 50;
|
||||
GetRow = 51;
|
||||
DeleteRow = 52;
|
||||
DuplicateRow = 53;
|
||||
GetCell = 70;
|
||||
UpdateCell = 71;
|
||||
ApplySelectOptionCellChangeset = 72;
|
||||
|
Loading…
Reference in New Issue
Block a user