chore: config field separate line

This commit is contained in:
appflowy 2022-04-12 15:22:33 +08:00
parent ee0939ab86
commit 943b4507ac
11 changed files with 79 additions and 44 deletions

View File

@ -10,10 +10,12 @@ part 'field_cell_bloc.freezed.dart';
class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> { class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
final FieldListener _fieldListener; final FieldListener _fieldListener;
final FieldService _fieldService;
FieldCellBloc({ FieldCellBloc({
required GridFieldCellContext cellContext, required GridFieldCellContext cellContext,
}) : _fieldListener = FieldListener(fieldId: cellContext.field.id), }) : _fieldListener = FieldListener(fieldId: cellContext.field.id),
_fieldService = FieldService(gridId: cellContext.gridId),
super(FieldCellState.initial(cellContext)) { super(FieldCellState.initial(cellContext)) {
on<FieldCellEvent>( on<FieldCellEvent>(
(event, emit) async { (event, emit) async {
@ -24,6 +26,7 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) { didReceiveFieldUpdate: (_DidReceiveFieldUpdate value) {
emit(state.copyWith(field: value.field)); emit(state.copyWith(field: value.field));
}, },
updateWidth: (_UpdateWidth value) {},
); );
}, },
); );
@ -50,6 +53,7 @@ class FieldCellBloc extends Bloc<FieldCellEvent, FieldCellState> {
class FieldCellEvent with _$FieldCellEvent { class FieldCellEvent with _$FieldCellEvent {
const factory FieldCellEvent.initial() = _InitialCell; const factory FieldCellEvent.initial() = _InitialCell;
const factory FieldCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate; const factory FieldCellEvent.didReceiveFieldUpdate(Field field) = _DidReceiveFieldUpdate;
const factory FieldCellEvent.updateWidth(double offset) = _UpdateWidth;
} }
@freezed @freezed

View File

@ -1,9 +1,10 @@
import 'package:dartz/dartz.dart'; import 'package:dartz/dartz.dart';
import 'package:equatable/equatable.dart';
import 'package:flowy_sdk/dispatch/dispatch.dart'; 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-grid-data-model/grid.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart'; import 'package:flowy_sdk/protobuf/flowy-grid/field_entities.pb.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'field_service.freezed.dart';
class FieldService { class FieldService {
final String gridId; final String gridId;
@ -98,17 +99,12 @@ class FieldService {
} }
} }
class GridFieldCellContext extends Equatable { @freezed
final String gridId; class GridFieldCellContext with _$GridFieldCellContext {
final Field field; const factory GridFieldCellContext({
required String gridId,
const GridFieldCellContext({ required Field field,
required this.gridId, }) = _GridFieldCellContext;
required this.field,
});
@override
List<Object> get props => [field.id];
} }
abstract class EditFieldContextLoader { abstract class EditFieldContextLoader {

View File

@ -78,10 +78,10 @@ class CreateItem extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
final config = HoverDisplayConfig(hoverColor: theme.hover); final config = HoverStyle(hoverColor: theme.hover);
return FlowyHover( return FlowyHover(
config: config, style: config,
builder: (context, onHover) { builder: (context, onHover) {
return GestureDetector( return GestureDetector(
onTap: () => onSelected(pluginBuilder), onTap: () => onSelected(pluginBuilder),

View File

@ -43,7 +43,7 @@ class ViewSectionItem extends StatelessWidget {
return InkWell( return InkWell(
onTap: () => onSelected(context.read<ViewBloc>().state.view), onTap: () => onSelected(context.read<ViewBloc>().state.view),
child: FlowyHover( child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3), style: HoverStyle(hoverColor: theme.bg3),
builder: (_, onHover) => _render(context, onHover, state, theme.iconColor), builder: (_, onHover) => _render(context, onHover, state, theme.iconColor),
setSelected: () => state.isEditing || isSelected, setSelected: () => state.isEditing || isSelected,
), ),

View File

@ -100,7 +100,7 @@ class _FlowyGridState extends State<FlowyGrid> {
controller: _scrollController.verticalController, controller: _scrollController.verticalController,
slivers: [ slivers: [
_renderToolbar(state.gridId), _renderToolbar(state.gridId),
_renderGridHeader(state.gridId), _renderHeader(state.gridId),
_renderRows(gridId: state.gridId, context: context), _renderRows(gridId: state.gridId, context: context),
const GridFooter(), const GridFooter(),
], ],
@ -126,7 +126,7 @@ class _FlowyGridState extends State<FlowyGrid> {
); );
} }
Widget _renderGridHeader(String gridId) { Widget _renderHeader(String gridId) {
return BlocSelector<GridBloc, GridState, List<Field>>( return BlocSelector<GridBloc, GridState, List<Field>>(
selector: (state) => state.fields, selector: (state) => state.fields,
builder: (context, fields) { builder: (context, fields) {

View File

@ -199,7 +199,7 @@ class _SelectOptionCell extends StatelessWidget {
context.read<SelectOptionEditorBloc>().add(SelectOptionEditorEvent.selectOption(option.id)); context.read<SelectOptionEditorBloc>().add(SelectOptionEditorEvent.selectOption(option.id));
}, },
child: FlowyHover( child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.hover), style: HoverStyle(hoverColor: theme.hover),
builder: (_, onHover) { builder: (_, onHover) {
List<Widget> children = [ List<Widget> children = [
SelectOptionTag(option: option, isSelected: isSelected), SelectOptionTag(option: option, isSelected: isSelected),

View File

@ -4,7 +4,9 @@ import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.d
import 'package:flowy_infra/image.dart'; import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart'; import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/button.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_infra_ui/style_widget/text.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'field_type_extension.dart'; import 'field_type_extension.dart';
@ -25,21 +27,52 @@ class GridFieldCell extends StatelessWidget {
child: BlocBuilder<FieldCellBloc, FieldCellState>( child: BlocBuilder<FieldCellBloc, FieldCellState>(
builder: (context, state) { builder: (context, state) {
final button = FlowyButton( final button = FlowyButton(
hoverColor: theme.hover, hoverColor: theme.shader6,
onTap: () => _showActionSheet(context), onTap: () => _showActionSheet(context),
rightIcon: svgWidget("editor/details", color: theme.iconColor), // rightIcon: svgWidget("editor/details", color: theme.iconColor),
leftIcon: svgWidget(state.field.fieldType.iconName(), color: theme.iconColor), leftIcon: svgWidget(state.field.fieldType.iconName(), color: theme.iconColor),
text: FlowyText.medium(state.field.name, fontSize: 12), text: FlowyText.medium(state.field.name, fontSize: 12),
padding: GridSize.cellContentInsets, padding: GridSize.cellContentInsets,
); );
final line = InkWell(
onTap: () {},
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onHorizontalDragCancel: () {},
onHorizontalDragUpdate: (value) {
Log.info(value.delta);
},
child: FlowyHover(
style: HoverStyle(
hoverColor: theme.main1,
borderRadius: BorderRadius.zero,
contentMargin: const EdgeInsets.only(left: 5),
),
builder: (_, onHover) => const SizedBox(width: 2),
),
),
);
final borderSide = BorderSide(color: theme.shader4, width: 0.4); final borderSide = BorderSide(color: theme.shader4, width: 0.4);
final decoration = BoxDecoration(border: Border(top: borderSide, right: borderSide, bottom: borderSide)); final decoration = BoxDecoration(
border: Border(
top: borderSide,
right: borderSide,
bottom: borderSide,
));
return Container( return Container(
width: state.field.width.toDouble(), width: state.field.width.toDouble(),
decoration: decoration, decoration: decoration,
child: button, child: ConstrainedBox(
constraints: const BoxConstraints.expand(),
child: Stack(
alignment: Alignment.centerRight,
fit: StackFit.expand,
children: [button, Positioned(top: 0, bottom: 0, right: 0, child: line)],
),
),
); );
}, },
), ),

View File

@ -72,28 +72,27 @@ class _GridHeaderWidget extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
final cells = fields.map( final cells = fields.map(
(field) => GridFieldCell( (field) => GridFieldCell(
GridFieldCellContext(gridId: gridId, field: field), GridFieldCellContext(gridId: gridId, field: field),
), ),
); );
final row = Row( return Row(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
const _HeaderLeading(), const _CellLeading(),
...cells, ...cells,
_HeaderTrailing(gridId: gridId), _CellTrailing(gridId: gridId),
], ],
); );
return Container(height: GridSize.headerHeight, color: theme.surface, child: row); // return Container(height: GridSize.headerHeight, color: theme.surface, child: row);
} }
} }
class _HeaderLeading extends StatelessWidget { class _CellLeading extends StatelessWidget {
const _HeaderLeading({Key? key}) : super(key: key); const _CellLeading({Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
@ -103,9 +102,9 @@ class _HeaderLeading extends StatelessWidget {
} }
} }
class _HeaderTrailing extends StatelessWidget { class _CellTrailing extends StatelessWidget {
final String gridId; final String gridId;
const _HeaderTrailing({required this.gridId, Key? key}) : super(key: key); const _CellTrailing({required this.gridId, Key? key}) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {

View File

@ -85,7 +85,7 @@ class ActionCell<T extends ActionItem> extends StatelessWidget {
final theme = context.watch<AppTheme>(); final theme = context.watch<AppTheme>();
return FlowyHover( return FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.hover), style: HoverStyle(hoverColor: theme.hover),
builder: (context, onHover) { builder: (context, onHover) {
return GestureDetector( return GestureDetector(
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,

View File

@ -28,7 +28,7 @@ class FlowyButton extends StatelessWidget {
return InkWell( return InkWell(
onTap: onTap, onTap: onTap,
child: FlowyHover( child: FlowyHover(
config: HoverDisplayConfig(borderRadius: Corners.s6Border, hoverColor: hoverColor), style: HoverStyle(borderRadius: Corners.s6Border, hoverColor: hoverColor),
setSelected: () => isSelected, setSelected: () => isSelected,
builder: (context, onHover) => _render(), builder: (context, onHover) => _render(),
), ),

View File

@ -5,14 +5,14 @@ import 'package:flowy_infra/time/duration.dart';
typedef HoverBuilder = Widget Function(BuildContext context, bool onHover); typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
class FlowyHover extends StatefulWidget { class FlowyHover extends StatefulWidget {
final HoverDisplayConfig config; final HoverStyle style;
final HoverBuilder builder; final HoverBuilder builder;
final bool Function()? setSelected; final bool Function()? setSelected;
const FlowyHover({ const FlowyHover({
Key? key, Key? key,
required this.builder, required this.builder,
required this.config, required this.style,
this.setSelected, this.setSelected,
}) : super(key: key); }) : super(key: key);
@ -41,7 +41,7 @@ class _FlowyHoverState extends State<FlowyHover> {
if (showHover) { if (showHover) {
return FlowyHoverContainer( return FlowyHoverContainer(
config: widget.config, style: widget.style,
child: widget.builder(context, _onHover), child: widget.builder(context, _onHover),
); );
} else { } else {
@ -50,41 +50,44 @@ class _FlowyHoverState extends State<FlowyHover> {
} }
} }
class HoverDisplayConfig { class HoverStyle {
final Color borderColor; final Color borderColor;
final double borderWidth; final double borderWidth;
final Color hoverColor; final Color hoverColor;
final BorderRadius borderRadius; final BorderRadius borderRadius;
final EdgeInsets contentMargin;
const HoverDisplayConfig( const HoverStyle(
{this.borderColor = Colors.transparent, {this.borderColor = Colors.transparent,
this.borderWidth = 0, this.borderWidth = 0,
this.borderRadius = const BorderRadius.all(Radius.circular(6)), this.borderRadius = const BorderRadius.all(Radius.circular(6)),
this.contentMargin = EdgeInsets.zero,
required this.hoverColor}); required this.hoverColor});
} }
class FlowyHoverContainer extends StatelessWidget { class FlowyHoverContainer extends StatelessWidget {
final HoverDisplayConfig config; final HoverStyle style;
final Widget child; final Widget child;
const FlowyHoverContainer({ const FlowyHoverContainer({
Key? key, Key? key,
required this.child, required this.child,
required this.config, required this.style,
}) : super(key: key); }) : super(key: key);
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final hoverBorder = Border.all( final hoverBorder = Border.all(
color: config.borderColor, color: style.borderColor,
width: config.borderWidth, width: style.borderWidth,
); );
return Container( return Container(
margin: style.contentMargin,
decoration: BoxDecoration( decoration: BoxDecoration(
border: hoverBorder, border: hoverBorder,
color: config.hoverColor, color: style.hoverColor,
borderRadius: config.borderRadius, borderRadius: style.borderRadius,
), ),
child: child, child: child,
); );