mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
chore: config checkbox ui
This commit is contained in:
parent
6384edf0e6
commit
5b92805e93
@ -1,4 +1,6 @@
|
||||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'package:app_flowy/plugins/grid/application/block/block_cache.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/field/field_controller.dart';
|
||||
import 'package:app_flowy/plugins/grid/application/row/row_cache.dart';
|
||||
@ -12,7 +14,6 @@ import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/protobuf.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'dart:collection';
|
||||
|
||||
import 'board_data_controller.dart';
|
||||
import 'group_controller.dart';
|
||||
@ -164,12 +165,17 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
boardController.clear();
|
||||
|
||||
//
|
||||
List<AFBoardColumnData> columns = groups.map((group) {
|
||||
List<AFBoardColumnData> columns = groups
|
||||
.where((group) => fieldController.getField(group.fieldId) != null)
|
||||
.map((group) {
|
||||
return AFBoardColumnData(
|
||||
id: group.groupId,
|
||||
name: group.desc,
|
||||
items: _buildRows(group),
|
||||
customData: group,
|
||||
customData: BoardCustomData(
|
||||
group: group,
|
||||
fieldContext: fieldController.getField(group.fieldId)!,
|
||||
),
|
||||
);
|
||||
}).toList();
|
||||
boardController.addColumns(columns);
|
||||
@ -177,6 +183,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
for (final group in groups) {
|
||||
final delegate = GroupControllerDelegateImpl(
|
||||
controller: boardController,
|
||||
fieldController: fieldController,
|
||||
onNewColumnItem: (groupId, row, index) {
|
||||
add(BoardEvent.didCreateRow(groupId, row, index));
|
||||
},
|
||||
@ -238,10 +245,8 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
|
||||
|
||||
List<AFColumnItem> _buildRows(GroupPB group) {
|
||||
final items = group.rows.map((row) {
|
||||
return BoardColumnItem(
|
||||
row: row,
|
||||
fieldId: group.fieldId,
|
||||
);
|
||||
final fieldContext = fieldController.getField(group.fieldId);
|
||||
return BoardColumnItem(row: row, fieldContext: fieldContext!);
|
||||
}).toList();
|
||||
|
||||
return <AFColumnItem>[...items];
|
||||
@ -332,15 +337,11 @@ class GridFieldEquatable extends Equatable {
|
||||
|
||||
class BoardColumnItem extends AFColumnItem {
|
||||
final RowPB row;
|
||||
|
||||
final String fieldId;
|
||||
|
||||
final bool requestFocus;
|
||||
final GridFieldContext fieldContext;
|
||||
|
||||
BoardColumnItem({
|
||||
required this.row,
|
||||
required this.fieldId,
|
||||
this.requestFocus = false,
|
||||
required this.fieldContext,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -348,24 +349,29 @@ class BoardColumnItem extends AFColumnItem {
|
||||
}
|
||||
|
||||
class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
||||
final GridFieldController fieldController;
|
||||
final AFBoardDataController controller;
|
||||
final void Function(String, RowPB, int?) onNewColumnItem;
|
||||
|
||||
GroupControllerDelegateImpl({
|
||||
required this.controller,
|
||||
required this.fieldController,
|
||||
required this.onNewColumnItem,
|
||||
});
|
||||
|
||||
@override
|
||||
void insertRow(GroupPB group, RowPB row, int? index) {
|
||||
final fieldContext = fieldController.getField(group.fieldId);
|
||||
if (fieldContext == null) {
|
||||
Log.warn("FieldContext should not be null");
|
||||
return;
|
||||
}
|
||||
|
||||
if (index != null) {
|
||||
final item = BoardColumnItem(row: row, fieldId: group.fieldId);
|
||||
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
||||
controller.insertColumnItem(group.groupId, index, item);
|
||||
} else {
|
||||
final item = BoardColumnItem(
|
||||
row: row,
|
||||
fieldId: group.fieldId,
|
||||
);
|
||||
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
||||
controller.addColumnItem(group.groupId, item);
|
||||
}
|
||||
}
|
||||
@ -377,22 +383,25 @@ class GroupControllerDelegateImpl extends GroupControllerDelegate {
|
||||
|
||||
@override
|
||||
void updateRow(GroupPB group, RowPB row) {
|
||||
final fieldContext = fieldController.getField(group.fieldId);
|
||||
if (fieldContext == null) {
|
||||
Log.warn("FieldContext should not be null");
|
||||
return;
|
||||
}
|
||||
controller.updateColumnItem(
|
||||
group.groupId,
|
||||
BoardColumnItem(
|
||||
row: row,
|
||||
fieldId: group.fieldId,
|
||||
),
|
||||
BoardColumnItem(row: row, fieldContext: fieldContext),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
void addNewRow(GroupPB group, RowPB row, int? index) {
|
||||
final item = BoardColumnItem(
|
||||
row: row,
|
||||
fieldId: group.fieldId,
|
||||
requestFocus: true,
|
||||
);
|
||||
final fieldContext = fieldController.getField(group.fieldId);
|
||||
if (fieldContext == null) {
|
||||
Log.warn("FieldContext should not be null");
|
||||
return;
|
||||
}
|
||||
final item = BoardColumnItem(row: row, fieldContext: fieldContext);
|
||||
|
||||
if (index != null) {
|
||||
controller.insertColumnItem(group.groupId, index, item);
|
||||
@ -414,3 +423,29 @@ class BoardEditingRow {
|
||||
required this.index,
|
||||
});
|
||||
}
|
||||
|
||||
class BoardCustomData {
|
||||
final GroupPB group;
|
||||
final GridFieldContext fieldContext;
|
||||
BoardCustomData({
|
||||
required this.group,
|
||||
required this.fieldContext,
|
||||
});
|
||||
|
||||
CheckboxGroup? asCheckboxGroup() {
|
||||
if (fieldType != FieldType.Checkbox) return null;
|
||||
return CheckboxGroup(group);
|
||||
}
|
||||
|
||||
FieldType get fieldType => fieldContext.fieldType;
|
||||
}
|
||||
|
||||
class CheckboxGroup {
|
||||
final GroupPB group;
|
||||
|
||||
CheckboxGroup(this.group);
|
||||
|
||||
// Hardcode value: "Yes" that equal to the value defined in Rust
|
||||
// pub const CHECK: &str = "Yes";
|
||||
bool get isCheck => group.groupId == "Yes";
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ import 'package:flowy_infra_ui/style_widget/text.dart';
|
||||
import 'package:flowy_infra_ui/widget/error_page.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-folder/view.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/block_entities.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/group.pbserver.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../grid/application/row/row_cache.dart';
|
||||
@ -36,8 +36,7 @@ class BoardPage extends StatelessWidget {
|
||||
create: (context) =>
|
||||
BoardBloc(view: view)..add(const BoardEvent.initial()),
|
||||
child: BlocBuilder<BoardBloc, BoardState>(
|
||||
buildWhen: (previous, current) =>
|
||||
previous.loadingState != current.loadingState,
|
||||
buildWhen: (p, c) => p.loadingState != c.loadingState,
|
||||
builder: (context, state) {
|
||||
return state.loadingState.map(
|
||||
loading: (_) =>
|
||||
@ -84,36 +83,15 @@ class _BoardContentState extends State<BoardContent> {
|
||||
child: BlocBuilder<BoardBloc, BoardState>(
|
||||
buildWhen: (previous, current) => previous.groupIds != current.groupIds,
|
||||
builder: (context, state) {
|
||||
final theme = context.read<AppTheme>();
|
||||
final column = Column(
|
||||
children: [const _ToolbarBlocAdaptor(), _buildBoard(context)],
|
||||
);
|
||||
|
||||
return Container(
|
||||
color: theme.surface,
|
||||
color: context.read<AppTheme>().surface,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
child: Column(
|
||||
children: [
|
||||
const _ToolbarBlocAdaptor(),
|
||||
Expanded(
|
||||
child: AFBoard(
|
||||
key: UniqueKey(),
|
||||
scrollManager: scrollManager,
|
||||
scrollController: scrollController,
|
||||
dataController: context.read<BoardBloc>().boardController,
|
||||
headerBuilder: _buildHeader,
|
||||
footBuilder: _buildFooter,
|
||||
cardBuilder: (_, column, columnItem) => _buildCard(
|
||||
context,
|
||||
column,
|
||||
columnItem,
|
||||
),
|
||||
columnConstraints:
|
||||
const BoxConstraints.tightFor(width: 300),
|
||||
config: AFBoardConfig(
|
||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
child: column,
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -121,6 +99,27 @@ class _BoardContentState extends State<BoardContent> {
|
||||
);
|
||||
}
|
||||
|
||||
Expanded _buildBoard(BuildContext context) {
|
||||
return Expanded(
|
||||
child: AFBoard(
|
||||
scrollManager: scrollManager,
|
||||
scrollController: scrollController,
|
||||
dataController: context.read<BoardBloc>().boardController,
|
||||
headerBuilder: _buildHeader,
|
||||
footBuilder: _buildFooter,
|
||||
cardBuilder: (_, column, columnItem) => _buildCard(
|
||||
context,
|
||||
column,
|
||||
columnItem,
|
||||
),
|
||||
columnConstraints: const BoxConstraints.tightFor(width: 300),
|
||||
config: AFBoardConfig(
|
||||
columnBackgroundColor: HexColor.fromHex('#F7F8FC'),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _handleEditState(BoardState state, BuildContext context) {
|
||||
state.editingRow.fold(
|
||||
() => null,
|
||||
@ -152,6 +151,7 @@ class _BoardContentState extends State<BoardContent> {
|
||||
BuildContext context,
|
||||
AFBoardColumnData columnData,
|
||||
) {
|
||||
final boardCustomData = columnData.customData as BoardCustomData;
|
||||
return AppFlowyColumnHeader(
|
||||
title: Flexible(
|
||||
fit: FlexFit.tight,
|
||||
@ -162,6 +162,7 @@ class _BoardContentState extends State<BoardContent> {
|
||||
color: context.read<AppTheme>().textColor,
|
||||
),
|
||||
),
|
||||
icon: _buildHeaderIcon(boardCustomData),
|
||||
addIcon: SizedBox(
|
||||
height: 20,
|
||||
width: 20,
|
||||
@ -181,7 +182,9 @@ class _BoardContentState extends State<BoardContent> {
|
||||
}
|
||||
|
||||
Widget _buildFooter(BuildContext context, AFBoardColumnData columnData) {
|
||||
final group = columnData.customData as GroupPB;
|
||||
final boardCustomData = columnData.customData as BoardCustomData;
|
||||
final group = boardCustomData.group;
|
||||
|
||||
if (group.isDefault) {
|
||||
return const SizedBox();
|
||||
} else {
|
||||
@ -246,7 +249,7 @@ class _BoardContentState extends State<BoardContent> {
|
||||
child: BoardCard(
|
||||
gridId: gridId,
|
||||
groupId: column.id,
|
||||
fieldId: boardColumnItem.fieldId,
|
||||
fieldId: boardColumnItem.fieldContext.id,
|
||||
isEditing: isEditing,
|
||||
cellBuilder: cellBuilder,
|
||||
dataController: cardController,
|
||||
@ -319,3 +322,38 @@ extension HexColor on Color {
|
||||
return Color(int.parse(buffer.toString(), radix: 16));
|
||||
}
|
||||
}
|
||||
|
||||
Widget? _buildHeaderIcon(BoardCustomData customData) {
|
||||
Widget? widget;
|
||||
switch (customData.fieldType) {
|
||||
case FieldType.Checkbox:
|
||||
final group = customData.asCheckboxGroup()!;
|
||||
if (group.isCheck) {
|
||||
widget = svgWidget('editor/editor_check');
|
||||
} else {
|
||||
widget = svgWidget('editor/editor_uncheck');
|
||||
}
|
||||
break;
|
||||
case FieldType.DateTime:
|
||||
break;
|
||||
case FieldType.MultiSelect:
|
||||
break;
|
||||
case FieldType.Number:
|
||||
break;
|
||||
case FieldType.RichText:
|
||||
break;
|
||||
case FieldType.SingleSelect:
|
||||
break;
|
||||
case FieldType.URL:
|
||||
break;
|
||||
}
|
||||
|
||||
if (widget != null) {
|
||||
widget = SizedBox(
|
||||
width: 20,
|
||||
height: 20,
|
||||
child: widget,
|
||||
);
|
||||
}
|
||||
return widget;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@ import 'package:dartz/dartz.dart';
|
||||
import 'package:flowy_sdk/log.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-error/errors.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/group.pb.dart';
|
||||
import 'package:flowy_sdk/protobuf/flowy-grid/setting_entities.pb.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import '../row/row_cache.dart';
|
||||
@ -35,12 +36,12 @@ class GridFieldController {
|
||||
final SettingListener _settingListener;
|
||||
final Map<OnReceiveFields, VoidCallback> _fieldCallbackMap = {};
|
||||
final Map<OnChangeset, OnChangeset> _changesetCallbackMap = {};
|
||||
|
||||
_GridFieldNotifier? _fieldNotifier = _GridFieldNotifier();
|
||||
List<String> _groupFieldIds = [];
|
||||
final GridFFIService _gridFFIService;
|
||||
final SettingFFIService _settingFFIService;
|
||||
|
||||
_GridFieldNotifier? _fieldNotifier = _GridFieldNotifier();
|
||||
final Map<String, GridGroupConfigurationPB> _configurationByFieldId = {};
|
||||
|
||||
List<GridFieldContext> get fieldContexts =>
|
||||
[..._fieldNotifier?.fieldContexts ?? []];
|
||||
|
||||
@ -67,31 +68,43 @@ class GridFieldController {
|
||||
//Listen on setting changes
|
||||
_settingListener.start(onSettingUpdated: (result) {
|
||||
result.fold(
|
||||
(setting) => _updateFieldsWhenSettingChanged(setting),
|
||||
(setting) => _updateGroupConfiguration(setting),
|
||||
(r) => Log.error(r),
|
||||
);
|
||||
});
|
||||
|
||||
_settingFFIService.getSetting().then((result) {
|
||||
result.fold(
|
||||
(setting) => _updateFieldsWhenSettingChanged(setting),
|
||||
(setting) => _updateGroupConfiguration(setting),
|
||||
(err) => Log.error(err),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void _updateFieldsWhenSettingChanged(GridSettingPB setting) {
|
||||
_groupFieldIds = setting.groupConfigurations.items
|
||||
.map((item) => item.groupFieldId)
|
||||
GridFieldContext? getField(String fieldId) {
|
||||
final fields = _fieldNotifier?.fieldContexts
|
||||
.where(
|
||||
(element) => element.id == fieldId,
|
||||
)
|
||||
.toList();
|
||||
if (fields?.isEmpty ?? true) {
|
||||
return null;
|
||||
}
|
||||
return fields!.first;
|
||||
}
|
||||
|
||||
void _updateGroupConfiguration(GridSettingPB setting) {
|
||||
_configurationByFieldId.clear();
|
||||
for (final configuration in setting.groupConfigurations.items) {
|
||||
_configurationByFieldId[configuration.fieldId] = configuration;
|
||||
}
|
||||
_updateFieldContexts();
|
||||
}
|
||||
|
||||
void _updateFieldContexts() {
|
||||
if (_fieldNotifier != null) {
|
||||
for (var field in _fieldNotifier!.fieldContexts) {
|
||||
if (_groupFieldIds.contains(field.id)) {
|
||||
if (_configurationByFieldId[field.id] != null) {
|
||||
field._isGroupField = true;
|
||||
} else {
|
||||
field._isGroupField = false;
|
||||
|
@ -31,7 +31,7 @@ typedef AFBoardColumnCardBuilder = Widget Function(
|
||||
|
||||
typedef AFBoardColumnHeaderBuilder = Widget? Function(
|
||||
BuildContext context,
|
||||
AFBoardColumnData headerData,
|
||||
AFBoardColumnData columnData,
|
||||
);
|
||||
|
||||
typedef AFBoardColumnFooterBuilder = Widget Function(
|
||||
|
@ -44,14 +44,14 @@ pub struct GridGroupConfigurationPB {
|
||||
pub id: String,
|
||||
|
||||
#[pb(index = 2)]
|
||||
pub group_field_id: String,
|
||||
pub field_id: String,
|
||||
}
|
||||
|
||||
impl std::convert::From<&GroupConfigurationRevision> for GridGroupConfigurationPB {
|
||||
fn from(rev: &GroupConfigurationRevision) -> Self {
|
||||
GridGroupConfigurationPB {
|
||||
id: rev.id.clone(),
|
||||
group_field_id: rev.field_id.clone(),
|
||||
field_id: rev.field_id.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user