chore: grid setting list

This commit is contained in:
appflowy 2022-04-03 10:53:24 +08:00
parent 147e948b35
commit 5d007c5359
50 changed files with 384 additions and 137 deletions

View File

@ -1,3 +0,0 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M11.2304 4.2561H10.0184L8.02638 7.9401H8.00238L5.99838 4.2561H4.78638L7.06638 8.2401H5.43438V8.9601H7.47438L7.48638 8.9841V9.8241H5.43438V10.5321H7.48638V12.5001H8.53038V10.5321H10.4984V9.8241H8.53038V8.9841L8.54238 8.9601H10.4984V8.2401H8.95038L11.2304 4.2561Z" fill="#333333"/>
</svg>

Before

Width:  |  Height:  |  Size: 392 B

View File

Before

Width:  |  Height:  |  Size: 238 B

After

Width:  |  Height:  |  Size: 238 B

View File

Before

Width:  |  Height:  |  Size: 281 B

After

Width:  |  Height:  |  Size: 281 B

View File

Before

Width:  |  Height:  |  Size: 512 B

After

Width:  |  Height:  |  Size: 512 B

View File

Before

Width:  |  Height:  |  Size: 499 B

After

Width:  |  Height:  |  Size: 499 B

View File

@ -0,0 +1,4 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M10.5221 3.21932C11.4366 2.6913 12.5634 2.6913 13.4779 3.21932L18.8653 6.32972C19.7799 6.85774 20.3433 7.83356 20.3433 8.88959V15.1104C20.3433 16.1664 19.7799 17.1423 18.8653 17.6703L13.4779 20.7807C12.5634 21.3087 11.4366 21.3087 10.5221 20.7807L5.13468 17.6703C4.22012 17.1423 3.65673 16.1664 3.65673 15.1104V8.88959C3.65673 7.83356 4.22012 6.85774 5.13467 6.32972L10.5221 3.21932Z" stroke="#333333" stroke-width="1.5"/>
<circle cx="12" cy="12" r="3.75" stroke="#333333" stroke-width="1.5"/>
</svg>

After

Width:  |  Height:  |  Size: 606 B

View File

@ -0,0 +1,4 @@
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect x="2.5" y="3" width="4" height="10" rx="1" stroke="#333333"/>
<rect x="9.5" y="7" width="4" height="6" rx="1" stroke="#333333"/>
</svg>

After

Width:  |  Height:  |  Size: 238 B

View File

@ -143,6 +143,11 @@
}
},
"grid": {
"settings": {
"filter": "Filter",
"sortBy": "Sort by",
"Properties": "Properties"
},
"field": {
"hide": "Hide",
"insertLeft": "Insert Left",

View File

@ -170,8 +170,8 @@ class PasswordTextField extends StatelessWidget {
return RoundedInputField(
obscureText: true,
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
obscureIcon: svg("home/hide"),
obscureHideIcon: svg("home/show"),
obscureIcon: svgWidget("home/hide"),
obscureHideIcon: svgWidget("home/show"),
hintText: LocaleKeys.signIn_passwordHint.tr(),
normalBorderColor: theme.shader4,
errorBorderColor: theme.red,

View File

@ -134,8 +134,8 @@ class PasswordTextField extends StatelessWidget {
builder: (context, state) {
return RoundedInputField(
obscureText: true,
obscureIcon: svg("home/hide"),
obscureHideIcon: svg("home/show"),
obscureIcon: svgWidget("home/hide"),
obscureHideIcon: svgWidget("home/show"),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
hintText: LocaleKeys.signUp_passwordHint.tr(),
normalBorderColor: theme.shader4,
@ -162,8 +162,8 @@ class RepeatPasswordTextField extends StatelessWidget {
builder: (context, state) {
return RoundedInputField(
obscureText: true,
obscureIcon: svg("home/hide"),
obscureHideIcon: svg("home/show"),
obscureIcon: svgWidget("home/hide"),
obscureHideIcon: svgWidget("home/show"),
style: const TextStyle(fontSize: 14, fontWeight: FontWeight.w500),
hintText: LocaleKeys.signUp_repeatPasswordHint.tr(),
normalBorderColor: theme.shader4,

View File

@ -44,7 +44,7 @@ class FlowyLogoTitle extends StatelessWidget {
children: [
SizedBox.fromSize(
size: logoSize,
child: svg("flowy_logo"),
child: svgWidget("flowy_logo"),
),
const VSpace(30),
Text(

View File

@ -23,3 +23,6 @@ export 'cell_bloc/selection_cell_bloc.dart';
export 'cell_bloc/date_cell_bloc.dart';
export 'cell_bloc/checkbox_cell_bloc.dart';
export 'cell_bloc/cell_service.dart';
// Setting
export 'setting/setting_bloc.dart';

View File

@ -0,0 +1,47 @@
import 'package:flowy_sdk/protobuf/flowy-grid-data-model/grid.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';
import 'package:dartz/dartz.dart';
part 'setting_bloc.freezed.dart';
class GridSettingBloc extends Bloc<GridSettingEvent, GridSettingState> {
final String gridId;
GridSettingBloc({required this.gridId}) : super(GridSettingState.initial()) {
on<GridSettingEvent>(
(event, emit) async {
event.map(performAction: (_PerformAction value) {
emit(state.copyWith(selectedAction: Some(value.action)));
});
},
);
}
@override
Future<void> close() async {
return super.close();
}
}
@freezed
class GridSettingEvent with _$GridSettingEvent {
const factory GridSettingEvent.performAction(GridSettingAction action) = _PerformAction;
}
@freezed
class GridSettingState with _$GridSettingState {
const factory GridSettingState({
required Option<GridSettingAction> selectedAction,
}) = _GridSettingState;
factory GridSettingState.initial() => GridSettingState(
selectedAction: none(),
);
}
enum GridSettingAction {
filter,
sortBy,
properties,
}

View File

@ -39,7 +39,7 @@ extension ViewExtension on View {
thumbnail = "file_icon";
}
final Widget widget = svg(thumbnail, color: iconColor);
final Widget widget = svgWidget(thumbnail, color: iconColor);
return widget;
}

View File

@ -28,7 +28,7 @@ class AddButton extends StatelessWidget {
onSelected: onSelected,
).show(context);
},
icon: svg("home/add").padding(horizontal: 3, vertical: 3),
icon: svgWidget("home/add").padding(horizontal: 3, vertical: 3),
);
}
}

View File

@ -153,9 +153,9 @@ extension AppDisclosureExtension on AppDisclosureAction {
Widget get icon {
switch (this) {
case AppDisclosureAction.rename:
return svg('editor/edit', color: const Color(0xffe5e5e5));
return svgWidget('editor/edit', color: const Color(0xffe5e5e5));
case AppDisclosureAction.delete:
return svg('editor/delete', color: const Color(0xffe5e5e5));
return svgWidget('editor/delete', color: const Color(0xffe5e5e5));
}
}
}

View File

@ -32,7 +32,7 @@ class ViewDisclosureButton extends StatelessWidget with ActionList<ViewDisclosur
onTap();
show(context);
},
icon: svg("editor/details", color: theme.iconColor),
icon: svgWidget("editor/details", color: theme.iconColor),
);
}

View File

@ -45,7 +45,7 @@ class ViewSectionItem extends StatelessWidget {
child: FlowyHover(
config: HoverDisplayConfig(hoverColor: theme.bg3),
builder: (_, onHover) => _render(context, onHover, state, theme.iconColor),
isOnSelected: () => state.isEditing || isSelected,
setSelected: () => state.isEditing || isSelected,
),
);
},
@ -126,11 +126,11 @@ extension ViewDisclosureExtension on ViewDisclosureAction {
Widget get icon {
switch (this) {
case ViewDisclosureAction.rename:
return svg('editor/edit', color: const Color(0xff999999));
return svgWidget('editor/edit', color: const Color(0xff999999));
case ViewDisclosureAction.delete:
return svg('editor/delete', color: const Color(0xff999999));
return svgWidget('editor/delete', color: const Color(0xff999999));
case ViewDisclosureAction.duplicate:
return svg('editor/copy', color: const Color(0xff999999));
return svgWidget('editor/copy', color: const Color(0xff999999));
}
}
}

View File

@ -186,7 +186,7 @@ class MenuTopBar extends StatelessWidget {
width: 28,
onPressed: () => context.read<MenuBloc>().add(const MenuEvent.collapse()),
iconPadding: const EdgeInsets.fromLTRB(4, 4, 4, 4),
icon: svg("home/hide_menu", color: theme.iconColor),
icon: svgWidget("home/hide_menu", color: theme.iconColor),
)
],
),

View File

@ -80,7 +80,7 @@ class MenuUser extends StatelessWidget {
},
icon: SizedBox.square(
dimension: 20,
child: svg("home/settings", color: theme.iconColor),
child: svgWidget("home/settings", color: theme.iconColor),
),
),
);

View File

@ -97,7 +97,7 @@ class FlowyNavigation extends StatelessWidget {
notifier.value = false;
},
iconPadding: const EdgeInsets.fromLTRB(2, 2, 2, 2),
icon: svg("home/hide_menu", color: theme.iconColor),
icon: svgWidget("home/hide_menu", color: theme.iconColor),
),
);
} else {

View File

@ -51,7 +51,7 @@ class _FlowyEditorCheckboxState extends State<FlowyEditorCheckbox> {
@override
Widget build(BuildContext context) {
final icon = isChecked ? svg('editor/editor_check') : svg('editor/editor_uncheck');
final icon = isChecked ? svgWidget('editor/editor_check') : svgWidget('editor/editor_uncheck');
return Align(
alignment: Alignment.centerLeft,
child: FlowyIconButton(

View File

@ -54,11 +54,11 @@ class _FlowyLinkStyleButtonState extends State<FlowyLinkStyleButton> {
final isEnabled = !widget.controller.selection.isCollapsed;
final pressedHandler = isEnabled ? () => _openLinkDialog(context) : null;
final icon = isEnabled
? svg(
? svgWidget(
'editor/share',
color: theme.iconColor,
)
: svg(
: svgWidget(
'editor/share',
color: theme.disableIconColor,
);

View File

@ -29,7 +29,7 @@ class ToolbarIconButton extends StatelessWidget {
iconPadding: const EdgeInsets.symmetric(horizontal: 4, vertical: 4),
onPressed: onPressed,
width: width,
icon: isToggled == true ? svg(iconName, color: Colors.white) : svg(iconName),
icon: isToggled == true ? svgWidget(iconName, color: Colors.white) : svgWidget(iconName),
fillColor: isToggled == true ? theme.main1 : theme.shader6,
hoverColor: isToggled == true ? theme.main1 : theme.shader5,
tooltipText: tooltipText,

View File

@ -13,6 +13,7 @@ import 'layout/sizes.dart';
import 'widgets/content/grid_row.dart';
import 'widgets/footer/grid_footer.dart';
import 'widgets/header/grid_header.dart';
import 'widgets/toolbar/grid_toolbar.dart';
class GridPage extends StatefulWidget {
final View view;
@ -99,6 +100,7 @@ class _FlowyGridState extends State<FlowyGrid> {
physics: StyledScrollPhysics(),
controller: _scrollController.verticalController,
slivers: [
SliverToBoxAdapter(child: GridToolbar(gridId: gridId)),
_buildHeader(gridId),
_buildRows(context),
const GridFooter(),

View File

@ -110,7 +110,7 @@ class AppendRowButton extends StatelessWidget {
width: 22,
onPressed: () => context.read<RowBloc>().add(const RowEvent.createRow()),
iconPadding: const EdgeInsets.all(3),
icon: svg("home/add"),
icon: svgWidget("home/add"),
);
}
}

View File

@ -39,7 +39,7 @@ class _AddRowButton extends StatelessWidget {
text: const FlowyText.medium('New row', fontSize: 12),
hoverColor: theme.hover,
onTap: () => context.read<GridBloc>().add(const GridEvent.createRow()),
leftIcon: svg("home/add"),
leftIcon: svgWidget("home/add"),
);
}
}

View File

@ -1,3 +1,4 @@
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
@ -13,14 +14,10 @@ import 'package:flutter_bloc/flutter_bloc.dart';
typedef SelectFieldCallback = void Function(FieldType);
class FieldTypeList extends StatelessWidget {
class FieldTypeList extends StatelessWidget with FlowyOverlayDelegate {
final SelectFieldCallback onSelectField;
const FieldTypeList({required this.onSelectField, Key? key}) : super(key: key);
static void hide(BuildContext context) {
FlowyOverlay.of(context).remove(FieldTypeList.identifier());
}
@override
Widget build(BuildContext context) {
final cells = FieldType.values.map((fieldType) {
@ -40,7 +37,7 @@ class FieldTypeList extends StatelessWidget {
controller: ScrollController(),
itemCount: cells.length,
separatorBuilder: (context, index) {
return const VSpace(10);
return VSpace(GridSize.typeOptionSeparatorHeight);
},
physics: StyledScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
@ -69,12 +66,12 @@ class FieldTypeCell extends StatelessWidget {
final theme = context.watch<AppTheme>();
return SizedBox(
height: 26,
height: GridSize.typeOptionItemHeight,
child: FlowyButton(
text: FlowyText.medium(fieldType.title(), fontSize: 12),
hoverColor: theme.hover,
onTap: () => onSelectField(fieldType),
leftIcon: svg(fieldType.iconName(), color: theme.iconColor),
leftIcon: svgWidget(fieldType.iconName(), color: theme.iconColor),
),
);
}

View File

@ -9,7 +9,7 @@ import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
class FieldOperationList extends StatelessWidget {
final List<FieldActionItem> actions;
final List<FieldActionCell> actions;
const FieldOperationList({required this.actions, Key? key}) : super(key: key);
@override
@ -27,12 +27,12 @@ class FieldOperationList extends StatelessWidget {
}
}
class FieldActionItem extends StatelessWidget {
class FieldActionCell extends StatelessWidget {
final String fieldId;
final VoidCallback onTap;
final FieldAction action;
const FieldActionItem({
const FieldActionCell({
required this.fieldId,
required this.action,
required this.onTap,
@ -49,7 +49,7 @@ class FieldActionItem extends StatelessWidget {
action.run(context);
onTap();
},
leftIcon: svg(action.iconName(), color: theme.iconColor),
leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
);
}
}

View File

@ -83,8 +83,8 @@ class _FieldSwitcherState extends State<FieldSwitcher> {
});
_showOverlay(context, list);
},
leftIcon: svg(field.fieldType.iconName(), color: theme.iconColor),
rightIcon: svg("grid/more", color: theme.iconColor),
leftIcon: svgWidget(field.fieldType.iconName(), color: theme.iconColor),
rightIcon: svgWidget("grid/more", color: theme.iconColor),
),
);
}

View File

@ -17,16 +17,16 @@ class GridFieldActionSheet extends StatelessWidget with FlowyOverlayDelegate {
final VoidCallback onEdited;
const GridFieldActionSheet({required this.fieldData, required this.onEdited, Key? key}) : super(key: key);
static void show(BuildContext overlayContext, GridFieldData fieldData, final VoidCallback onEdited) {
final editor = GridFieldActionSheet(fieldData: fieldData, onEdited: onEdited);
void show(BuildContext overlayContext) {
FlowyOverlay.of(overlayContext).insertWithAnchor(
widget: OverlayContainer(
child: editor,
child: this,
constraints: BoxConstraints.loose(const Size(240, 200)),
),
identifier: editor.identifier(),
identifier: identifier(),
anchorContext: overlayContext,
anchorDirection: AnchorDirection.bottomWithLeftAligned,
delegate: this,
);
}
@ -56,7 +56,9 @@ class GridFieldActionSheet extends StatelessWidget with FlowyOverlayDelegate {
}
@override
bool asBarrier() => true;
bool asBarrier() {
return true;
}
}
class _EditFieldButton extends StatelessWidget {
@ -90,7 +92,7 @@ class _FieldOperationList extends StatelessWidget {
Widget build(BuildContext context) {
final actions = FieldAction.values
.map(
(action) => FieldActionItem(
(action) => FieldActionCell(
fieldId: fieldData.field.id,
action: action,
onTap: onDismissed,

View File

@ -25,7 +25,7 @@ class FieldEditor extends FlowyOverlayDelegate {
void show(BuildContext context) {
FlowyOverlay.of(context).insertWithAnchor(
widget: OverlayContainer(
child: _EditFieldPannelWidget(_fieldEditorBloc),
child: _FieldEditorWidget(_fieldEditorBloc),
constraints: BoxConstraints.loose(const Size(220, 400)),
),
identifier: identifier(),
@ -49,9 +49,9 @@ class FieldEditor extends FlowyOverlayDelegate {
bool asBarrier() => true;
}
class _EditFieldPannelWidget extends StatelessWidget {
class _FieldEditorWidget extends StatelessWidget {
final FieldEditorBloc editorBloc;
const _EditFieldPannelWidget(this.editorBloc, {Key? key}) : super(key: key);
const _FieldEditorWidget(this.editorBloc, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {

View File

@ -121,7 +121,7 @@ class CreateFieldButton extends StatelessWidget {
gridId: gridId,
fieldContextLoader: NewFieldContextLoader(gridId: gridId),
).show(context),
leftIcon: svg("home/add"),
leftIcon: svgWidget("home/add"),
);
}
}

View File

@ -19,13 +19,16 @@ class GridHeaderCell extends StatelessWidget {
final theme = context.watch<AppTheme>();
final button = FlowyButton(
hoverColor: theme.hover,
onTap: () => GridFieldActionSheet.show(context, fieldData, () {
FieldEditor(
gridId: fieldData.gridId,
fieldContextLoader: FieldContextLoaderAdaptor(fieldData),
).show(context);
}),
rightIcon: svg("editor/details", color: theme.iconColor),
onTap: () => GridFieldActionSheet(
fieldData: fieldData,
onEdited: () {
FieldEditor(
gridId: fieldData.gridId,
fieldContextLoader: FieldContextLoaderAdaptor(fieldData),
).show(context);
},
).show(context),
rightIcon: svgWidget("editor/details", color: theme.iconColor),
text: Padding(padding: GridSize.cellContentInsets, child: FlowyText.medium(fieldData.field.name, fontSize: 12)),
);

View File

@ -1,35 +0,0 @@
enum GridSetting {
filter,
sortBy,
properties,
}
extension _GridSettingExtension on GridSetting {
String iconName() {
switch (this) {
case GridSetting.filter:
// TODO: Handle this case.
break;
case GridSetting.sortBy:
// TODO: Handle this case.
break;
case GridSetting.properties:
// TODO: Handle this case.
break;
}
}
String title() {
switch (this) {
case GridSetting.filter:
// TODO: Handle this case.
break;
case GridSetting.sortBy:
// TODO: Handle this case.
break;
case GridSetting.properties:
// TODO: Handle this case.
break;
}
}
}

View File

@ -75,7 +75,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
);
overlayDelegate.showOverlay(context, list);
},
rightIcon: svg("grid/more", color: theme.iconColor),
rightIcon: svgWidget("grid/more", color: theme.iconColor),
),
);
}
@ -96,7 +96,7 @@ class DateTypeOptionWidget extends TypeOptionWidget {
});
overlayDelegate.showOverlay(context, list);
},
rightIcon: svg("grid/more", color: theme.iconColor),
rightIcon: svgWidget("grid/more", color: theme.iconColor),
),
);
}
@ -156,7 +156,7 @@ class DateFormatItem extends StatelessWidget {
final theme = context.watch<AppTheme>();
Widget? checkmark;
if (isSelected) {
checkmark = svg("grid/checkmark");
checkmark = svgWidget("grid/checkmark");
}
return SizedBox(
@ -246,7 +246,7 @@ class TimeFormatItem extends StatelessWidget {
final theme = context.watch<AppTheme>();
Widget? checkmark;
if (isSelected) {
checkmark = svg("grid/checkmark");
checkmark = svgWidget("grid/checkmark");
}
return SizedBox(

View File

@ -79,7 +79,7 @@ class _DeleteTag extends StatelessWidget {
child: FlowyButton(
text: FlowyText.medium(LocaleKeys.grid_selectOption_deleteTag.tr(), fontSize: 12),
hoverColor: theme.hover,
leftIcon: svg("grid/delete", color: theme.iconColor),
leftIcon: svgWidget("grid/delete", color: theme.iconColor),
onTap: () {
context.read<EditOptionBloc>().add(const EditOptionEvent.delete());
},
@ -110,8 +110,8 @@ class SelectOptionColorList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final optionItems = SelectOptionColor.values.map((color) {
return _SelectOptionColorItem(color: color, isSelected: selectedColor == color);
final cells = SelectOptionColor.values.map((color) {
return _SelectOptionColorCell(color: color, isSelected: selectedColor == color);
}).toList();
return Column(
@ -135,10 +135,10 @@ class SelectOptionColorList extends StatelessWidget {
separatorBuilder: (context, index) {
return VSpace(GridSize.typeOptionSeparatorHeight);
},
itemCount: optionItems.length,
itemCount: cells.length,
physics: StyledScrollPhysics(),
itemBuilder: (BuildContext context, int index) {
return optionItems[index];
return cells[index];
},
),
],
@ -146,17 +146,17 @@ class SelectOptionColorList extends StatelessWidget {
}
}
class _SelectOptionColorItem extends StatelessWidget {
class _SelectOptionColorCell extends StatelessWidget {
final SelectOptionColor color;
final bool isSelected;
const _SelectOptionColorItem({required this.color, required this.isSelected, Key? key}) : super(key: key);
const _SelectOptionColorCell({required this.color, required this.isSelected, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
Widget? checkmark;
if (isSelected) {
checkmark = svg("grid/checkmark");
checkmark = svgWidget("grid/checkmark");
}
final colorIcon = SizedBox.square(

View File

@ -59,7 +59,7 @@ class NumberTypeOptionWidget extends TypeOptionWidget {
});
overlayDelegate.showOverlay(context, list);
},
rightIcon: svg("grid/more", color: theme.iconColor),
rightIcon: svgWidget("grid/more", color: theme.iconColor),
);
},
),
@ -76,8 +76,8 @@ class NumberFormatList extends StatelessWidget {
@override
Widget build(BuildContext context) {
final formatItems = NumberFormat.values.map((format) {
return NumberFormatItem(
final cells = NumberFormat.values.map((format) {
return NumberFormatCell(
format: format,
onSelected: (format) {
onSelected(format);
@ -93,9 +93,9 @@ class NumberFormatList extends StatelessWidget {
separatorBuilder: (context, index) {
return VSpace(GridSize.typeOptionSeparatorHeight);
},
itemCount: formatItems.length,
itemCount: cells.length,
itemBuilder: (BuildContext context, int index) {
return formatItems[index];
return cells[index];
},
),
);
@ -106,10 +106,10 @@ class NumberFormatList extends StatelessWidget {
}
}
class NumberFormatItem extends StatelessWidget {
class NumberFormatCell extends StatelessWidget {
final NumberFormat format;
final Function(NumberFormat format) onSelected;
const NumberFormatItem({required this.format, required this.onSelected, Key? key}) : super(key: key);
const NumberFormatCell({required this.format, required this.onSelected, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
@ -120,7 +120,7 @@ class NumberFormatItem extends StatelessWidget {
text: FlowyText.medium(format.title(), fontSize: 12),
hoverColor: theme.hover,
onTap: () => onSelected(format),
leftIcon: svg(format.iconName(), color: theme.iconColor),
leftIcon: svgWidget(format.iconName(), color: theme.iconColor),
),
);
}

View File

@ -132,8 +132,8 @@ class _OptionList extends StatelessWidget {
return previous.options != current.options;
},
builder: (context, state) {
final optionItems = state.options.map((option) {
return _makeOptionItem(context, option);
final cells = state.options.map((option) {
return _makeOptionCell(context, option);
}).toList();
return ListView.separated(
@ -142,17 +142,17 @@ class _OptionList extends StatelessWidget {
separatorBuilder: (context, index) {
return VSpace(GridSize.typeOptionSeparatorHeight);
},
itemCount: optionItems.length,
itemCount: cells.length,
itemBuilder: (BuildContext context, int index) {
return optionItems[index];
return cells[index];
},
);
},
);
}
_OptionItem _makeOptionItem(BuildContext context, SelectOption option) {
return _OptionItem(
_OptionCell _makeOptionCell(BuildContext context, SelectOption option) {
return _OptionCell(
option: option,
onEdited: (option) {
final pannel = EditSelectOptionPannel(
@ -173,10 +173,10 @@ class _OptionList extends StatelessWidget {
}
}
class _OptionItem extends StatelessWidget {
class _OptionCell extends StatelessWidget {
final SelectOption option;
final Function(SelectOption) onEdited;
const _OptionItem({
const _OptionCell({
required this.option,
required this.onEdited,
Key? key,
@ -191,7 +191,7 @@ class _OptionItem extends StatelessWidget {
text: FlowyText.medium(option.name, fontSize: 12),
hoverColor: theme.hover,
onTap: () => onEdited(option),
rightIcon: svg("grid/details", color: theme.iconColor),
rightIcon: svgWidget("grid/details", color: theme.iconColor),
),
);
}
@ -211,7 +211,7 @@ class _AddOptionButton extends StatelessWidget {
onTap: () {
context.read<OptionPannelBloc>().add(const OptionPannelEvent.beginAddingOption());
},
leftIcon: svg("home/add", color: theme.iconColor),
leftIcon: svgWidget("home/add", color: theme.iconColor),
),
);
}

View File

@ -0,0 +1,19 @@
import 'package:flutter/material.dart';
class GridPropertyList extends StatelessWidget {
const GridPropertyList({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}
class _GridPropertyCell extends StatelessWidget {
const _GridPropertyCell({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container();
}
}

View File

@ -0,0 +1,152 @@
import 'package:app_flowy/workspace/application/grid/setting/setting_bloc.dart';
import 'package:easy_localization/easy_localization.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';
import 'package:app_flowy/generated/locale_keys.g.dart';
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
class GridSettingContext {
final String gridId;
GridSettingContext({
required this.gridId,
});
}
class GridSettingList extends StatelessWidget with FlowyOverlayDelegate {
final GridSettingContext settingContext;
const GridSettingList({required this.settingContext, Key? key}) : super(key: key);
void show(BuildContext context) {
FlowyOverlay.of(context).insertWithAnchor(
widget: OverlayContainer(
child: this,
constraints: BoxConstraints.loose(const Size(140, 400)),
),
identifier: identifier(),
anchorContext: context,
anchorDirection: AnchorDirection.bottomRight,
style: FlowyOverlayStyle(blur: false),
delegate: this,
);
}
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => GridSettingBloc(gridId: settingContext.gridId),
child: BlocListener<GridSettingBloc, GridSettingState>(
listenWhen: (previous, current) => previous.selectedAction != current.selectedAction,
listener: (context, state) {
state.selectedAction.foldLeft(null, (_, action) {
switch (action) {
case GridSettingAction.filter:
// TODO: Handle this case.
break;
case GridSettingAction.sortBy:
// TODO: Handle this case.
break;
case GridSettingAction.properties:
// TODO: Handle this case.
break;
}
});
},
child: BlocBuilder<GridSettingBloc, GridSettingState>(
builder: (context, state) {
return _renderList();
},
),
),
);
}
String identifier() {
return toString();
}
Widget _renderList() {
final cells = GridSettingAction.values.map((action) {
return _SettingItem(action: action);
}).toList();
return SizedBox(
width: 140,
child: 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];
},
),
);
}
}
class _SettingItem extends StatelessWidget {
final GridSettingAction action;
const _SettingItem({
required this.action,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
final isSelected = context
.read<GridSettingBloc>()
.state
.selectedAction
.foldLeft(false, (_, selectedAction) => selectedAction == action);
return SizedBox(
height: GridSize.typeOptionItemHeight,
child: FlowyButton(
isSelected: isSelected,
text: FlowyText.medium(action.title(), fontSize: 12),
hoverColor: theme.hover,
onTap: () {
context.read<GridSettingBloc>().add(GridSettingEvent.performAction(action));
},
leftIcon: svgWidget(action.iconName(), color: theme.iconColor),
),
);
}
}
extension _GridSettingExtension on GridSettingAction {
String iconName() {
switch (this) {
case GridSettingAction.filter:
return 'grid/setting/filter';
case GridSettingAction.sortBy:
return 'grid/setting/sort';
case GridSettingAction.properties:
return 'grid/setting/properties';
}
}
String title() {
switch (this) {
case GridSettingAction.filter:
return LocaleKeys.grid_settings_filter.tr();
case GridSettingAction.sortBy:
return LocaleKeys.grid_settings_sortBy.tr();
case GridSettingAction.properties:
return LocaleKeys.grid_settings_Properties.tr();
}
}
}

View File

@ -0,0 +1,44 @@
import 'package:app_flowy/workspace/presentation/plugins/grid/src/layout/sizes.dart';
import 'package:flowy_infra_ui/style_widget/extension.dart';
import 'package:flutter/material.dart';
import 'package:flowy_infra/image.dart';
import 'package:flowy_infra/theme.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'grid_setting.dart';
class GridToolbar extends StatelessWidget {
final String gridId;
const GridToolbar({required this.gridId, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return SizedBox(
height: 40,
child: Row(
children: [
SizedBox(width: GridSize.leadingHeaderPadding),
_SettingButton(settingContext: GridSettingContext(gridId: gridId)),
const Spacer(),
],
),
);
}
}
class _SettingButton extends StatelessWidget {
final GridSettingContext settingContext;
const _SettingButton({required this.settingContext, Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return FlowyIconButton(
hoverColor: theme.hover,
width: 22,
onPressed: () => GridSettingList(settingContext: settingContext).show(context),
icon: svgWidget("grid/setting/setting").padding(horizontal: 3, vertical: 3),
);
}
}

View File

@ -36,7 +36,7 @@ class MenuTrash extends StatelessWidget {
child: Selector<AppearanceSettingModel, AppTheme>(
selector: (ctx, notifier) => notifier.theme,
builder: (ctx, theme, child) =>
SizedBox(width: 16, height: 16, child: svg("home/trash", color: theme.iconColor)),
SizedBox(width: 16, height: 16, child: svgWidget("home/trash", color: theme.iconColor)),
),
),
const HSpace(6),

View File

@ -29,13 +29,13 @@ class TrashCell extends StatelessWidget {
FlowyIconButton(
width: 16,
onPressed: onRestore,
icon: svg("editor/restore", color: theme.iconColor),
icon: svgWidget("editor/restore", color: theme.iconColor),
),
const HSpace(20),
FlowyIconButton(
width: 16,
onPressed: onDelete,
icon: svg("editor/delete", color: theme.iconColor),
icon: svgWidget("editor/delete", color: theme.iconColor),
),
],
);

View File

@ -146,7 +146,7 @@ class _TrashPageState extends State<TrashPage> {
size: const Size(102, 30),
child: FlowyButton(
text: FlowyText.medium(LocaleKeys.trash_restoreAll.tr(), fontSize: 12),
leftIcon: svg('editor/restore', color: theme.iconColor),
leftIcon: svgWidget('editor/restore', color: theme.iconColor),
hoverColor: theme.hover,
onTap: () => context.read<TrashBloc>().add(const TrashEvent.restoreAll()),
),
@ -156,7 +156,7 @@ class _TrashPageState extends State<TrashPage> {
size: const Size(102, 30),
child: FlowyButton(
text: FlowyText.medium(LocaleKeys.trash_deleteAll.tr(), fontSize: 12),
leftIcon: svg('editor/delete', color: theme.iconColor),
leftIcon: svgWidget('editor/delete', color: theme.iconColor),
hoverColor: theme.hover,
onTap: () => context.read<TrashBloc>().add(const TrashEvent.deleteAll()),
),

View File

@ -1,7 +1,7 @@
import 'package:flutter/widgets.dart';
import 'package:flutter_svg/flutter_svg.dart';
Widget svg(String name, {Color? color}) {
Widget svgWidget(String name, {Color? color}) {
final Widget svg = SvgPicture.asset('assets/images/$name.svg', color: color);
return svg;
@ -10,6 +10,6 @@ Widget svg(String name, {Color? color}) {
Widget svgWithSize(String name, Size size) {
return SizedBox.fromSize(
size: size,
child: svg(name),
child: svgWidget(name),
);
}

View File

@ -11,6 +11,7 @@ class FlowyButton extends StatelessWidget {
final Widget? leftIcon;
final Widget? rightIcon;
final Color hoverColor;
final bool isSelected;
const FlowyButton({
Key? key,
required this.text,
@ -19,6 +20,7 @@ class FlowyButton extends StatelessWidget {
this.leftIcon,
this.rightIcon,
this.hoverColor = Colors.transparent,
this.isSelected = false,
}) : super(key: key);
@override
@ -27,6 +29,7 @@ class FlowyButton extends StatelessWidget {
onTap: onTap,
child: FlowyHover(
config: HoverDisplayConfig(borderRadius: Corners.s6Border, hoverColor: hoverColor),
setSelected: () => isSelected,
builder: (context, onHover) => _render(),
),
);

View File

@ -3,18 +3,17 @@ import 'package:flutter/material.dart';
import 'package:flowy_infra/time/duration.dart';
typedef HoverBuilder = Widget Function(BuildContext context, bool onHover);
typedef IsOnSelected = bool Function();
class FlowyHover extends StatefulWidget {
final HoverDisplayConfig config;
final HoverBuilder builder;
final IsOnSelected? isOnSelected;
final bool Function()? setSelected;
const FlowyHover({
Key? key,
required this.builder,
required this.config,
this.isOnSelected,
this.setSelected,
}) : super(key: key);
@override
@ -36,8 +35,8 @@ class _FlowyHoverState extends State<FlowyHover> {
Widget render() {
var showHover = _onHover;
if (!showHover && widget.isOnSelected != null) {
showHover = widget.isOnSelected!();
if (!showHover && widget.setSelected != null) {
showHover = widget.setSelected!();
}
if (showHover) {

View File

@ -77,7 +77,7 @@ class FlowyDropdownButton extends StatelessWidget {
return FlowyIconButton(
width: 16,
onPressed: onPressed,
icon: svg("home/drop_down_show"),
icon: svgWidget("home/drop_down_show"),
);
}
}

View File

@ -113,6 +113,7 @@ flutter:
- assets/images/editor/
- assets/images/grid/
- assets/images/grid/field/
- assets/images/grid/setting/
- assets/translations/
# - images/a_dot_ham.jpeg