mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
feat: implement checklist UI
This commit is contained in:
@ -358,7 +358,7 @@ Widget? _buildHeaderIcon(GroupData customData) {
|
||||
break;
|
||||
case FieldType.URL:
|
||||
break;
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -59,7 +59,7 @@ class BoardCellBuilder {
|
||||
editableNotifier: cellNotifier,
|
||||
key: key,
|
||||
);
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return BoardChecklistCell(
|
||||
key: key,
|
||||
);
|
||||
|
@ -5,6 +5,8 @@ typedef GridCheckboxCellController = IGridCellController<String, String>;
|
||||
typedef GridNumberCellController = IGridCellController<String, String>;
|
||||
typedef GridSelectOptionCellController
|
||||
= IGridCellController<SelectOptionCellDataPB, String>;
|
||||
typedef GridChecklistCellController
|
||||
= IGridCellController<SelectOptionCellDataPB, String>;
|
||||
typedef GridDateCellController
|
||||
= IGridCellController<DateCellDataPB, CalendarData>;
|
||||
typedef GridURLCellController = IGridCellController<URLCellDataPB, String>;
|
||||
@ -81,7 +83,7 @@ class GridCellControllerBuilder {
|
||||
);
|
||||
case FieldType.MultiSelect:
|
||||
case FieldType.SingleSelect:
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
final cellDataLoader = GridCellDataLoader(
|
||||
cellId: _cellId,
|
||||
parser: SelectOptionCellDataParser(),
|
||||
|
@ -0,0 +1,93 @@
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:async';
|
||||
import 'cell_service/cell_service.dart';
|
||||
import 'select_option_service.dart';
|
||||
part 'checklist_cell_bloc.freezed.dart';
|
||||
|
||||
class ChecklistCellBloc extends Bloc<ChecklistCellEvent, ChecklistCellState> {
|
||||
final GridChecklistCellController cellController;
|
||||
final SelectOptionFFIService _selectOptionService;
|
||||
void Function()? _onCellChangedFn;
|
||||
ChecklistCellBloc({
|
||||
required this.cellController,
|
||||
}) : _selectOptionService =
|
||||
SelectOptionFFIService(cellId: cellController.cellId),
|
||||
super(ChecklistCellState.initial(cellController)) {
|
||||
on<ChecklistCellEvent>(
|
||||
(event, emit) async {
|
||||
await event.when(
|
||||
initial: () async {
|
||||
_startListening();
|
||||
_loadOptions();
|
||||
},
|
||||
didReceiveOptions: (data) {
|
||||
emit(state.copyWith(
|
||||
allOptions: data.options,
|
||||
selectedOptions: data.selectOptions,
|
||||
percent: data.selectOptions.length.toDouble() /
|
||||
data.options.length.toDouble(),
|
||||
));
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
if (_onCellChangedFn != null) {
|
||||
cellController.removeListener(_onCellChangedFn!);
|
||||
_onCellChangedFn = null;
|
||||
}
|
||||
await cellController.dispose();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
_onCellChangedFn = cellController.startListening(
|
||||
onCellFieldChanged: () {
|
||||
_loadOptions();
|
||||
},
|
||||
onCellChanged: (_) {},
|
||||
);
|
||||
}
|
||||
|
||||
void _loadOptions() {
|
||||
_selectOptionService.getOptionContext().then((result) {
|
||||
if (isClosed) return;
|
||||
|
||||
return result.fold(
|
||||
(data) => add(ChecklistCellEvent.didReceiveOptions(data)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ChecklistCellEvent with _$ChecklistCellEvent {
|
||||
const factory ChecklistCellEvent.initial() = _InitialCell;
|
||||
const factory ChecklistCellEvent.didReceiveOptions(
|
||||
SelectOptionCellDataPB data) = _DidReceiveCellUpdate;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ChecklistCellState with _$ChecklistCellState {
|
||||
const factory ChecklistCellState({
|
||||
required List<SelectOptionPB> allOptions,
|
||||
required List<SelectOptionPB> selectedOptions,
|
||||
required double percent,
|
||||
}) = _ChecklistCellState;
|
||||
|
||||
factory ChecklistCellState.initial(
|
||||
GridChecklistCellController cellController) {
|
||||
return const ChecklistCellState(
|
||||
allOptions: [],
|
||||
selectedOptions: [],
|
||||
percent: 0,
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,194 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'select_option_service.dart';
|
||||
|
||||
part 'checklist_cell_editor_bloc.freezed.dart';
|
||||
|
||||
class ChecklistCellEditorBloc
|
||||
extends Bloc<ChecklistCellEditorEvent, ChecklistCellEditorState> {
|
||||
final SelectOptionFFIService _selectOptionService;
|
||||
final GridChecklistCellController cellController;
|
||||
Timer? _delayOperation;
|
||||
|
||||
ChecklistCellEditorBloc({
|
||||
required this.cellController,
|
||||
}) : _selectOptionService =
|
||||
SelectOptionFFIService(cellId: cellController.cellId),
|
||||
super(ChecklistCellEditorState.initial(cellController)) {
|
||||
on<ChecklistCellEditorEvent>(
|
||||
(event, emit) async {
|
||||
await event.when(
|
||||
initial: () async {
|
||||
_startListening();
|
||||
_loadOptions();
|
||||
},
|
||||
didReceiveOptions: (data) {
|
||||
emit(state.copyWith(
|
||||
allOptions: _makeChecklistSelectOptions(data, state.predicate),
|
||||
percent: _percentFromSelectOptionCellData(data),
|
||||
));
|
||||
},
|
||||
newOption: (optionName) {
|
||||
_createOption(optionName);
|
||||
emit(state.copyWith(
|
||||
predicate: '',
|
||||
));
|
||||
},
|
||||
deleteOption: (option) {
|
||||
_deleteOption([option]);
|
||||
},
|
||||
updateOption: (option) {
|
||||
_updateOption(option);
|
||||
},
|
||||
selectOption: (optionId) {
|
||||
_selectOptionService.select(optionIds: [optionId]);
|
||||
},
|
||||
unSelectOption: (optionId) {
|
||||
_selectOptionService.unSelect(optionIds: [optionId]);
|
||||
},
|
||||
filterOption: (String predicate) {},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> close() async {
|
||||
_delayOperation?.cancel();
|
||||
await cellController.dispose();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
void _createOption(String name) async {
|
||||
final result = await _selectOptionService.create(
|
||||
name: name,
|
||||
isSelected: false,
|
||||
);
|
||||
result.fold((l) => {}, (err) => Log.error(err));
|
||||
}
|
||||
|
||||
void _deleteOption(List<SelectOptionPB> options) async {
|
||||
final result = await _selectOptionService.delete(options: options);
|
||||
result.fold((l) => null, (err) => Log.error(err));
|
||||
}
|
||||
|
||||
void _updateOption(SelectOptionPB option) async {
|
||||
final result = await _selectOptionService.update(
|
||||
option: option,
|
||||
);
|
||||
|
||||
result.fold((l) => null, (err) => Log.error(err));
|
||||
}
|
||||
|
||||
void _loadOptions() {
|
||||
_selectOptionService.getOptionContext().then((result) {
|
||||
if (isClosed) return;
|
||||
|
||||
return result.fold(
|
||||
(data) => add(ChecklistCellEditorEvent.didReceiveOptions(data)),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void _startListening() {
|
||||
cellController.startListening(
|
||||
onCellChanged: ((data) {
|
||||
if (!isClosed && data != null) {
|
||||
add(ChecklistCellEditorEvent.didReceiveOptions(data));
|
||||
}
|
||||
}),
|
||||
onCellFieldChanged: () {
|
||||
_loadOptions();
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ChecklistCellEditorEvent with _$ChecklistCellEditorEvent {
|
||||
const factory ChecklistCellEditorEvent.initial() = _Initial;
|
||||
const factory ChecklistCellEditorEvent.didReceiveOptions(
|
||||
SelectOptionCellDataPB data) = _DidReceiveOptions;
|
||||
const factory ChecklistCellEditorEvent.newOption(String optionName) =
|
||||
_NewOption;
|
||||
const factory ChecklistCellEditorEvent.selectOption(String optionId) =
|
||||
_SelectOption;
|
||||
const factory ChecklistCellEditorEvent.unSelectOption(String optionId) =
|
||||
_UnSelectOption;
|
||||
const factory ChecklistCellEditorEvent.updateOption(SelectOptionPB option) =
|
||||
_UpdateOption;
|
||||
const factory ChecklistCellEditorEvent.deleteOption(SelectOptionPB option) =
|
||||
_DeleteOption;
|
||||
const factory ChecklistCellEditorEvent.filterOption(String predicate) =
|
||||
_FilterOption;
|
||||
}
|
||||
|
||||
@freezed
|
||||
class ChecklistCellEditorState with _$ChecklistCellEditorState {
|
||||
const factory ChecklistCellEditorState({
|
||||
required List<ChecklistSelectOption> allOptions,
|
||||
required Option<String> createOption,
|
||||
required double percent,
|
||||
required String predicate,
|
||||
}) = _ChecklistCellEditorState;
|
||||
|
||||
factory ChecklistCellEditorState.initial(
|
||||
GridSelectOptionCellController context) {
|
||||
final data = context.getCellData(loadIfNotExist: true);
|
||||
|
||||
return ChecklistCellEditorState(
|
||||
allOptions: _makeChecklistSelectOptions(data, ''),
|
||||
createOption: none(),
|
||||
percent: _percentFromSelectOptionCellData(data),
|
||||
predicate: '',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
double _percentFromSelectOptionCellData(SelectOptionCellDataPB? data) {
|
||||
if (data == null) return 0;
|
||||
|
||||
final a = data.selectOptions.length.toDouble();
|
||||
final b = data.options.length.toDouble();
|
||||
|
||||
if (a > b) return 1.0;
|
||||
|
||||
return a / b;
|
||||
}
|
||||
|
||||
List<ChecklistSelectOption> _makeChecklistSelectOptions(
|
||||
SelectOptionCellDataPB? data, String predicate) {
|
||||
if (data == null) {
|
||||
return [];
|
||||
}
|
||||
|
||||
final List<ChecklistSelectOption> options = [];
|
||||
final List<SelectOptionPB> allOptions = List.from(data.options);
|
||||
if (predicate.isNotEmpty) {
|
||||
allOptions.retainWhere((element) => element.name.contains(predicate));
|
||||
}
|
||||
final selectedOptionIds = data.selectOptions.map((e) => e.id).toList();
|
||||
|
||||
for (final option in allOptions) {
|
||||
options.add(
|
||||
ChecklistSelectOption(selectedOptionIds.contains(option.id), option),
|
||||
);
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
class ChecklistSelectOption {
|
||||
final bool isSelected;
|
||||
final SelectOptionPB data;
|
||||
|
||||
ChecklistSelectOption(this.isSelected, this.data);
|
||||
}
|
@ -1,26 +1,24 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||
import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'select_option_service.dart';
|
||||
|
||||
part 'select_option_editor_bloc.freezed.dart';
|
||||
|
||||
class SelectOptionCellEditorBloc
|
||||
extends Bloc<SelectOptionEditorEvent, SelectOptionEditorState> {
|
||||
final SelectOptionService _selectOptionService;
|
||||
final SelectOptionFFIService _selectOptionService;
|
||||
final GridSelectOptionCellController cellController;
|
||||
Timer? _delayOperation;
|
||||
|
||||
SelectOptionCellEditorBloc({
|
||||
required this.cellController,
|
||||
}) : _selectOptionService =
|
||||
SelectOptionService(cellId: cellController.cellId),
|
||||
SelectOptionFFIService(cellId: cellController.cellId),
|
||||
super(SelectOptionEditorState.initial(cellController)) {
|
||||
on<SelectOptionEditorEvent>(
|
||||
(event, emit) async {
|
||||
|
@ -6,15 +6,16 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||
import 'cell_service/cell_service.dart';
|
||||
|
||||
class SelectOptionService {
|
||||
class SelectOptionFFIService {
|
||||
final GridCellIdentifier cellId;
|
||||
SelectOptionService({required this.cellId});
|
||||
SelectOptionFFIService({required this.cellId});
|
||||
|
||||
String get gridId => cellId.gridId;
|
||||
String get fieldId => cellId.fieldInfo.id;
|
||||
String get rowId => cellId.rowId;
|
||||
|
||||
Future<Either<Unit, FlowyError>> create({required String name}) {
|
||||
Future<Either<Unit, FlowyError>> create(
|
||||
{required String name, bool isSelected = true}) {
|
||||
return TypeOptionFFIService(gridId: gridId, fieldId: fieldId)
|
||||
.newOption(name: name)
|
||||
.then(
|
||||
@ -26,8 +27,13 @@ class SelectOptionService {
|
||||
..fieldId = fieldId
|
||||
..rowId = rowId;
|
||||
final payload = SelectOptionChangesetPB.create()
|
||||
..insertOptions.add(option)
|
||||
..cellIdentifier = cellIdentifier;
|
||||
|
||||
if (isSelected) {
|
||||
payload.insertOptions.add(option);
|
||||
} else {
|
||||
payload.updateOptions.add(option);
|
||||
}
|
||||
return GridEventUpdateSelectOption(payload).send();
|
||||
},
|
||||
(r) => right(r),
|
||||
|
@ -503,7 +503,7 @@ class FieldInfo {
|
||||
|
||||
bool get hasFilter => _hasFilter;
|
||||
|
||||
bool get canGroup {
|
||||
bool get canBeGroup {
|
||||
switch (_field.fieldType) {
|
||||
case FieldType.Checkbox:
|
||||
case FieldType.MultiSelect:
|
||||
|
@ -105,7 +105,7 @@ class GridCreateFilterBloc
|
||||
condition: SelectOptionCondition.OptionIs,
|
||||
fieldType: FieldType.MultiSelect,
|
||||
);
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return _ffiService.insertChecklistFilter(
|
||||
fieldId: fieldId,
|
||||
condition: ChecklistFilterCondition.IsIncomplete,
|
||||
|
@ -152,14 +152,12 @@ class FilterFFIService {
|
||||
String? filterId,
|
||||
List<String> optionIds = const [],
|
||||
}) {
|
||||
final filter = ChecklistFilterPB()
|
||||
..condition = condition
|
||||
..optionIds.addAll(optionIds);
|
||||
final filter = ChecklistFilterPB()..condition = condition;
|
||||
|
||||
return insertFilter(
|
||||
fieldId: fieldId,
|
||||
filterId: filterId,
|
||||
fieldType: FieldType.CheckList,
|
||||
fieldType: FieldType.Checklist,
|
||||
data: filter.writeToBuffer(),
|
||||
);
|
||||
}
|
||||
|
@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'cell_accessory.dart';
|
||||
import 'cell_shortcuts.dart';
|
||||
import 'checkbox_cell.dart';
|
||||
import 'checklist_cell.dart';
|
||||
import 'checklist_cell/checklist_cell.dart';
|
||||
import 'date_cell/date_cell.dart';
|
||||
import 'number_cell.dart';
|
||||
import 'select_option_cell/select_option_cell.dart';
|
||||
@ -56,8 +56,9 @@ class GridCellBuilder {
|
||||
style: style,
|
||||
key: key,
|
||||
);
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return GridChecklistCell(
|
||||
cellControllerBuilder: cellControllerBuilder,
|
||||
key: key,
|
||||
);
|
||||
case FieldType.Number:
|
||||
|
@ -1,17 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'cell_builder.dart';
|
||||
|
||||
class GridChecklistCell extends GridCellWidget {
|
||||
GridChecklistCell({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
ChecklistCellState createState() => ChecklistCellState();
|
||||
}
|
||||
|
||||
class ChecklistCellState extends State<GridChecklistCell> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container();
|
||||
}
|
||||
}
|
@ -0,0 +1,91 @@
|
||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_bloc.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../cell_builder.dart';
|
||||
import 'checklist_cell_editor.dart';
|
||||
import 'checklist_prograss_bar.dart';
|
||||
|
||||
class GridChecklistCell extends GridCellWidget {
|
||||
final GridCellControllerBuilder cellControllerBuilder;
|
||||
GridChecklistCell({required this.cellControllerBuilder, Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
GridChecklistCellState createState() => GridChecklistCellState();
|
||||
}
|
||||
|
||||
class GridChecklistCellState extends State<GridChecklistCell> {
|
||||
late PopoverController _popover;
|
||||
late ChecklistCellBloc _cellBloc;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
_popover = PopoverController();
|
||||
final cellController =
|
||||
widget.cellControllerBuilder.build() as GridChecklistCellController;
|
||||
_cellBloc = ChecklistCellBloc(cellController: cellController);
|
||||
_cellBloc.add(const ChecklistCellEvent.initial());
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider.value(
|
||||
value: _cellBloc,
|
||||
child: BlocBuilder<ChecklistCellBloc, ChecklistCellState>(
|
||||
builder: (context, state) {
|
||||
return Stack(
|
||||
alignment: AlignmentDirectional.center,
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Padding(
|
||||
padding: GridSize.cellContentInsets,
|
||||
child: _wrapPopover(const ChecklistProgressBar()),
|
||||
),
|
||||
InkWell(onTap: () => _popover.show()),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _wrapPopover(Widget child) {
|
||||
return AppFlowyPopover(
|
||||
controller: _popover,
|
||||
constraints: BoxConstraints.loose(const Size(260, 400)),
|
||||
direction: PopoverDirection.bottomWithLeftAligned,
|
||||
triggerActions: PopoverTriggerFlags.none,
|
||||
popupBuilder: (BuildContext context) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
widget.onCellEditing.value = true;
|
||||
});
|
||||
return GridChecklistCellEditor(
|
||||
cellController: widget.cellControllerBuilder.build()
|
||||
as GridChecklistCellController,
|
||||
);
|
||||
},
|
||||
onClose: () => widget.onCellEditing.value = false,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ChecklistProgressBar extends StatelessWidget {
|
||||
const ChecklistProgressBar({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocBuilder<ChecklistCellBloc, ChecklistCellState>(
|
||||
builder: (context, state) {
|
||||
return ChecklistPrograssBar(
|
||||
percent: state.percent,
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
@ -0,0 +1,81 @@
|
||||
import 'package:app_flowy/plugins/grid/application/cell/cell_service/cell_service.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_editor_bloc.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/cell/checklist_cell/checklist_prograss_bar.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
||||
class GridChecklistCellEditor extends StatefulWidget {
|
||||
final GridChecklistCellController cellController;
|
||||
const GridChecklistCellEditor({required this.cellController, Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
State<GridChecklistCellEditor> createState() =>
|
||||
_GridChecklistCellEditorState();
|
||||
}
|
||||
|
||||
class _GridChecklistCellEditorState extends State<GridChecklistCellEditor> {
|
||||
late ChecklistCellEditorBloc bloc;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
bloc = ChecklistCellEditorBloc(cellController: widget.cellController);
|
||||
bloc.add(const ChecklistCellEditorEvent.initial());
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
bloc.close();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return BlocProvider.value(
|
||||
value: bloc,
|
||||
child: BlocBuilder<ChecklistCellEditorBloc, ChecklistCellEditorState>(
|
||||
builder: (context, state) {
|
||||
final List<Widget> slivers = [
|
||||
const SliverChecklistPrograssBar(),
|
||||
SliverToBoxAdapter(
|
||||
child: ListView.separated(
|
||||
controller: ScrollController(),
|
||||
shrinkWrap: true,
|
||||
itemCount: state.allOptions.length,
|
||||
itemBuilder: (BuildContext context, int index) {
|
||||
return _ChecklistOptionCell(option: state.allOptions[index]);
|
||||
},
|
||||
separatorBuilder: (BuildContext context, int index) {
|
||||
return VSpace(GridSize.typeOptionSeparatorHeight);
|
||||
},
|
||||
),
|
||||
),
|
||||
];
|
||||
return CustomScrollView(
|
||||
shrinkWrap: true,
|
||||
slivers: slivers,
|
||||
controller: ScrollController(),
|
||||
physics: StyledScrollPhysics(),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ChecklistOptionCell extends StatelessWidget {
|
||||
final ChecklistSelectOption option;
|
||||
const _ChecklistOptionCell({
|
||||
required this.option,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(height: 20, width: 100, color: Colors.red);
|
||||
}
|
||||
}
|
@ -0,0 +1,89 @@
|
||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/cell/checklist_cell_editor_bloc.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/color_extension.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:percent_indicator/percent_indicator.dart';
|
||||
|
||||
class ChecklistPrograssBar extends StatelessWidget {
|
||||
final double percent;
|
||||
const ChecklistPrograssBar({required this.percent, Key? key})
|
||||
: super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return LinearPercentIndicator(
|
||||
lineHeight: 10.0,
|
||||
percent: percent,
|
||||
progressColor: Theme.of(context).colorScheme.primary,
|
||||
backgroundColor: AFThemeExtension.of(context).tint9,
|
||||
barRadius: const Radius.circular(5),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SliverChecklistPrograssBar extends StatelessWidget {
|
||||
const SliverChecklistPrograssBar({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SliverPersistentHeader(
|
||||
pinned: true,
|
||||
delegate: _SliverChecklistPrograssBarDelegate(),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _SliverChecklistPrograssBarDelegate
|
||||
extends SliverPersistentHeaderDelegate {
|
||||
_SliverChecklistPrograssBarDelegate();
|
||||
|
||||
double fixHeight = 80;
|
||||
|
||||
@override
|
||||
Widget build(
|
||||
BuildContext context, double shrinkOffset, bool overlapsContent) {
|
||||
return BlocBuilder<ChecklistCellEditorBloc, ChecklistCellEditorState>(
|
||||
builder: (context, state) {
|
||||
return Column(
|
||||
children: [
|
||||
if (state.percent != 0)
|
||||
Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 8.0),
|
||||
child: ChecklistPrograssBar(percent: state.percent),
|
||||
),
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: FlowyTextField(
|
||||
hintText: LocaleKeys.grid_checklist_panelTitle.tr(),
|
||||
onChanged: (text) {
|
||||
context
|
||||
.read<ChecklistCellEditorBloc>()
|
||||
.add(ChecklistCellEditorEvent.filterOption(text));
|
||||
},
|
||||
onSubmitted: (text) {
|
||||
context
|
||||
.read<ChecklistCellEditorBloc>()
|
||||
.add(ChecklistCellEditorEvent.newOption(text));
|
||||
},
|
||||
),
|
||||
)
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
double get maxExtent => fixHeight;
|
||||
|
||||
@override
|
||||
double get minExtent => fixHeight;
|
||||
|
||||
@override
|
||||
bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate) {
|
||||
return false;
|
||||
}
|
||||
}
|
@ -1,5 +1,4 @@
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:app_flowy/startup/startup.dart';
|
||||
|
@ -11,7 +11,6 @@ import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra/size.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/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/rounded_input_field.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
|
@ -3,7 +3,6 @@ import 'package:app_flowy/plugins/grid/application/prelude.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
// ignore: unused_import
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||
|
@ -9,7 +9,6 @@ import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
@ -8,7 +8,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_filter.pbenum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -4,7 +4,6 @@ import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.d
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.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:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_option_filter.pb.dart';
|
||||
|
@ -3,13 +3,11 @@ import 'package:app_flowy/plugins/grid/application/filter/text_filter_editor_blo
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/condition_button.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/disclosure_button.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/filter_info.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/text_field.dart';
|
||||
import 'package:app_flowy/workspace/presentation/widgets/pop_up_action.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/image.dart';
|
||||
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/text_filter.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -151,7 +149,7 @@ class _TextFilterEditorState extends State<TextFilterEditor> {
|
||||
|
||||
Widget _buildFilterTextField(
|
||||
BuildContext context, TextFilterEditorState state) {
|
||||
return FilterTextField(
|
||||
return FlowyTextField(
|
||||
text: state.filter.content,
|
||||
hintText: LocaleKeys.grid_settings_typeAValue.tr(),
|
||||
autoFucous: false,
|
||||
|
@ -2,13 +2,13 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/filter/filter_create_bloc.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/layout/sizes.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/filter/text_field.dart';
|
||||
import 'package:app_flowy/plugins/grid/presentation/widgets/header/field_type_extension.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flowy_infra/image.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/style_widget/text_field.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
@ -121,7 +121,7 @@ class _FilterTextFieldDelegate extends SliverPersistentHeaderDelegate {
|
||||
child: Container(
|
||||
color: Theme.of(context).colorScheme.background,
|
||||
height: fixHeight,
|
||||
child: FilterTextField(
|
||||
child: FlowyTextField(
|
||||
hintText: LocaleKeys.grid_settings_filterBy.tr(),
|
||||
onChanged: (text) {
|
||||
context
|
||||
|
@ -7,7 +7,6 @@ import 'package:flowy_infra/color_extension.dart';
|
||||
import 'package:flowy_infra/image.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/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
@ -36,7 +36,7 @@ Widget buildFilterChoicechip(FilterInfo filterInfo) {
|
||||
return SelectOptionFilterChoicechip(filterInfo: filterInfo);
|
||||
case FieldType.URL:
|
||||
return URLFilterChoicechip(filterInfo: filterInfo);
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return ChecklistFilterChoicechip(filterInfo: filterInfo);
|
||||
default:
|
||||
return const SizedBox();
|
||||
|
@ -1,74 +0,0 @@
|
||||
import 'package:flowy_infra/size.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class FilterTextField extends StatefulWidget {
|
||||
final String hintText;
|
||||
final String text;
|
||||
final void Function(String)? onChanged;
|
||||
final void Function(String)? onSubmitted;
|
||||
final bool autoFucous;
|
||||
const FilterTextField({
|
||||
this.hintText = "",
|
||||
this.text = "",
|
||||
this.onChanged,
|
||||
this.onSubmitted,
|
||||
this.autoFucous = true,
|
||||
Key? key,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
State<FilterTextField> createState() => FilterTextFieldState();
|
||||
}
|
||||
|
||||
class FilterTextFieldState extends State<FilterTextField> {
|
||||
late FocusNode focusNode;
|
||||
late TextEditingController controller;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
focusNode = FocusNode();
|
||||
controller = TextEditingController();
|
||||
controller.text = widget.text;
|
||||
if (widget.autoFucous) {
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
focusNode.requestFocus();
|
||||
});
|
||||
}
|
||||
super.initState();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return TextField(
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
onChanged: (text) {
|
||||
widget.onChanged?.call(text);
|
||||
},
|
||||
onSubmitted: (text) {
|
||||
widget.onSubmitted?.call(text);
|
||||
},
|
||||
maxLines: 1,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
decoration: InputDecoration(
|
||||
contentPadding: const EdgeInsets.all(10),
|
||||
enabledBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: Corners.s10Border,
|
||||
),
|
||||
isDense: true,
|
||||
hintText: widget.hintText,
|
||||
focusedBorder: OutlineInputBorder(
|
||||
borderSide: BorderSide(
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
width: 1.0,
|
||||
),
|
||||
borderRadius: Corners.s8Border,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -6,7 +6,6 @@ import 'package:flowy_infra/image.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/hover.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
@ -19,7 +19,7 @@ extension FieldTypeListExtension on FieldType {
|
||||
return "grid/field/single_select";
|
||||
case FieldType.URL:
|
||||
return "grid/field/url";
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return "grid/field/checklist";
|
||||
}
|
||||
throw UnimplementedError;
|
||||
@ -41,7 +41,7 @@ extension FieldTypeListExtension on FieldType {
|
||||
return LocaleKeys.grid_field_singleSelectFieldName.tr();
|
||||
case FieldType.URL:
|
||||
return LocaleKeys.grid_field_urlFieldName.tr();
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return LocaleKeys.grid_field_checklistFieldName.tr();
|
||||
}
|
||||
throw UnimplementedError;
|
||||
|
@ -3,7 +3,6 @@ import 'package:flowy_infra/image.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:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -5,7 +5,6 @@ import 'package:dartz/dartz.dart' show Either;
|
||||
import 'package:flowy_infra/image.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/text.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -9,7 +9,6 @@ import 'package:flowy_infra/color_extension.dart';
|
||||
import 'package:flowy_infra/image.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/text.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
|
@ -5,10 +5,10 @@ import 'package:app_flowy/plugins/grid/application/field/type_option/type_option
|
||||
import 'package:app_flowy/plugins/grid/application/field/type_option/type_option_data_controller.dart';
|
||||
import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/checkbox_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/checklist_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/multi_select_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/number_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/single_select_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/text_type_option.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/url_type_option.pb.dart';
|
||||
@ -127,7 +127,7 @@ TypeOptionWidgetBuilder makeTypeOptionWidgetBuilder({
|
||||
),
|
||||
);
|
||||
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return ChecklistTypeOptionWidgetBuilder(
|
||||
makeTypeOptionContextWithDataController<ChecklistTypeOptionPB>(
|
||||
gridId: gridId,
|
||||
@ -217,7 +217,7 @@ TypeOptionContext<T>
|
||||
dataController: dataController,
|
||||
dataParser: MultiSelectTypeOptionWidgetDataParser(),
|
||||
) as TypeOptionContext<T>;
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return ChecklistTypeOptionContext(
|
||||
dataController: dataController,
|
||||
dataParser: ChecklistTypeOptionWidgetDataParser(),
|
||||
|
@ -7,7 +7,6 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
import 'package:flowy_infra/image.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/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/date_type_option_entities.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -5,7 +5,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra/image.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/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/format.pbenum.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -3,7 +3,6 @@ import 'package:appflowy_popover/appflowy_popover.dart';
|
||||
import 'package:flowy_infra/image.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/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/select_type_option.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
@ -9,7 +9,6 @@ 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/icon_button.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/scrolling/styled_scroll_bar.dart';
|
||||
import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/spacing.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:app_flowy/generated/locale_keys.g.dart';
|
||||
@ -331,7 +330,7 @@ GridCellStyle? _customCellStyle(FieldType fieldType) {
|
||||
return SelectOptionCellStyle(
|
||||
placeholder: LocaleKeys.grid_row_textPlaceholder.tr(),
|
||||
);
|
||||
case FieldType.CheckList:
|
||||
case FieldType.Checklist:
|
||||
return SelectOptionCellStyle(
|
||||
placeholder: LocaleKeys.grid_row_textPlaceholder.tr(),
|
||||
);
|
||||
|
@ -37,7 +37,7 @@ class GridGroupList extends StatelessWidget {
|
||||
key: ValueKey(fieldInfo.id),
|
||||
);
|
||||
|
||||
if (!fieldInfo.canGroup) {
|
||||
if (!fieldInfo.canBeGroup) {
|
||||
cell = IgnorePointer(child: Opacity(opacity: 0.3, child: cell));
|
||||
}
|
||||
return cell;
|
||||
|
@ -8,7 +8,6 @@ import 'package:flowy_infra/image.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/icon_button.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';
|
||||
|
Reference in New Issue
Block a user