Skip to content

Commit

Permalink
chore: show create option message on bottom
Browse files Browse the repository at this point in the history
  • Loading branch information
appflowy committed May 6, 2022
1 parent 228695d commit 18752e7
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 29 deletions.
1 change: 1 addition & 0 deletions frontend/app_flowy/assets/translations/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,7 @@
"textPlaceholder": "Empty"
},
"selectOption": {
"create": "Create",
"purpleColor": "Purple",
"pinkColor": "Pink",
"lightPinkColor": "Light Pink",
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';
import 'dart:async';

import 'package:dartz/dartz.dart';
import 'package:flowy_sdk/log.dart';
import 'package:flowy_sdk/protobuf/flowy-grid/selection_type_option.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'dart:async';

import 'package:app_flowy/workspace/application/grid/cell/cell_service.dart';

import 'select_option_service.dart';

part 'selection_editor_bloc.freezed.dart';
Expand All @@ -24,14 +28,19 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
_startListening();
},
didReceiveOptions: (_DidReceiveOptions value) {
final result = _makeOptions(state.filter, value.options);
emit(state.copyWith(
allOptions: value.options,
options: _makeOptions(state.filter, value.options),
options: result.options,
createOption: result.createOption,
selectedOptions: value.selectedOptions,
));
},
newOption: (_NewOption value) {
_createOption(value.optionName);
emit(state.copyWith(
filter: none(),
));
},
deleteOption: (_DeleteOption value) {
_deleteOption(value.option);
Expand Down Expand Up @@ -91,16 +100,37 @@ class SelectOptionEditorBloc extends Bloc<SelectOptionEditorEvent, SelectOptionE
}

void _filterOption(String optionName, Emitter<SelectOptionEditorState> emit) {
emit(state.copyWith(filter: optionName, options: _makeOptions(optionName, state.allOptions)));
final _MakeOptionResult result = _makeOptions(Some(optionName), state.allOptions);
emit(state.copyWith(
filter: Some(optionName),
options: result.options,
createOption: result.createOption,
));
}

List<SelectOption> _makeOptions(String filter, List<SelectOption> allOptions) {
_MakeOptionResult _makeOptions(Option<String> filter, List<SelectOption> allOptions) {
final List<SelectOption> options = List.from(allOptions);
if (filter.isNotEmpty) {
options.retainWhere((option) => option.name.toLowerCase().contains(filter.toLowerCase()));
}

return options;
Option<String> createOption = filter;

filter.foldRight(null, (filter, previous) {
if (filter.isNotEmpty) {
options.retainWhere((option) {
final name = option.name.toLowerCase();
final lFilter = filter.toLowerCase();

if (name == lFilter) {
createOption = none();
}

return name.contains(lFilter);
});
}
});

return _MakeOptionResult(
options: options,
createOption: createOption,
);
}

void _startListening() {
Expand Down Expand Up @@ -135,7 +165,8 @@ class SelectOptionEditorState with _$SelectOptionEditorState {
required List<SelectOption> options,
required List<SelectOption> allOptions,
required List<SelectOption> selectedOptions,
required String filter,
required Option<String> createOption,
required Option<String> filter,
}) = _SelectOptionEditorState;

factory SelectOptionEditorState.initial(GridSelectOptionCellContext context) {
Expand All @@ -144,7 +175,18 @@ class SelectOptionEditorState with _$SelectOptionEditorState {
options: data?.options ?? [],
allOptions: data?.options ?? [],
selectedOptions: data?.selectOptions ?? [],
filter: "",
createOption: none(),
filter: none(),
);
}
}

class _MakeOptionResult {
List<SelectOption> options;
Option<String> createOption;

_MakeOptionResult({
required this.options,
required this.createOption,
});
}
Original file line number Diff line number Diff line change
Expand Up @@ -60,17 +60,35 @@ extension SelectOptionColorExtension on SelectOptionColor {
}

class SelectOptionTag extends StatelessWidget {
final SelectOption option;
final String name;
final Color color;
final bool isSelected;
const SelectOptionTag({required this.option, this.isSelected = false, Key? key}) : super(key: key);
const SelectOptionTag({
required this.name,
required this.color,
this.isSelected = false,
Key? key,
}) : super(key: key);

factory SelectOptionTag.fromSelectOption({
required BuildContext context,
required SelectOption option,
bool isSelected = false,
}) {
return SelectOptionTag(
name: option.name,
color: option.color.make(context),
isSelected: isSelected,
);
}

@override
Widget build(BuildContext context) {
return ChoiceChip(
pressElevation: 1,
label: FlowyText.medium(option.name, fontSize: 12),
selectedColor: option.color.make(context),
backgroundColor: option.color.make(context),
label: FlowyText.medium(name, fontSize: 12),
selectedColor: color,
backgroundColor: color,
labelPadding: const EdgeInsets.symmetric(horizontal: 6),
selected: true,
onSelected: (_) {},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,14 @@ class _SelectOptionCell extends StatelessWidget {
child: FlowyText.medium(cellStyle!.placeholder, fontSize: 14, color: theme.shader3),
);
} else {
final tags = selectOptions.map((option) => SelectOptionTag(option: option)).toList();
final tags = selectOptions
.map(
(option) => SelectOptionTag.fromSelectOption(
context: context,
option: option,
),
)
.toList();
child = Align(
alignment: Alignment.centerLeft,
child: Wrap(children: tags, spacing: 4, runSpacing: 4),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,18 @@ class _OptionList extends StatelessWidget {
Widget build(BuildContext context) {
return BlocBuilder<SelectOptionEditorBloc, SelectOptionEditorState>(
builder: (context, state) {
final cells = state.options.map((option) {
List<Widget> cells = [];
cells.addAll(state.options.map((option) {
return _SelectOptionCell(option, state.selectedOptions.contains(option));
}).toList();
}).toList());

state.createOption.fold(
() => null,
(createOption) {
cells.add(_CreateOptionCell(name: createOption));
},
);

final list = ListView.separated(
shrinkWrap: true,
controller: ScrollController(),
Expand All @@ -119,7 +128,11 @@ class _OptionList extends StatelessWidget {
return cells[index];
},
);
return list;

return Padding(
padding: const EdgeInsets.all(3.0),
child: list,
);
},
);
}
Expand Down Expand Up @@ -177,6 +190,30 @@ class _Title extends StatelessWidget {
}
}

class _CreateOptionCell extends StatelessWidget {
final String name;
const _CreateOptionCell({required this.name, Key? key}) : super(key: key);

@override
Widget build(BuildContext context) {
final theme = context.watch<AppTheme>();
return Row(
children: [
FlowyText.medium(
LocaleKeys.grid_selectOption_create.tr(),
fontSize: 12,
color: theme.shader3,
),
const HSpace(10),
SelectOptionTag(
name: name,
color: theme.shader6,
),
],
);
}
}

class _SelectOptionCell extends StatelessWidget {
final SelectOption option;
final bool isSelected;
Expand Down Expand Up @@ -206,7 +243,11 @@ class _SelectOptionCell extends StatelessWidget {
style: HoverStyle(hoverColor: theme.hover),
builder: (_, onHover) {
List<Widget> children = [
SelectOptionTag(option: option, isSelected: isSelected),
SelectOptionTag(
name: option.name,
color: option.color.make(context),
isSelected: isSelected,
),
const Spacer(),
];

Expand All @@ -223,10 +264,7 @@ class _SelectOptionCell extends StatelessWidget {
));
}

return Padding(
padding: const EdgeInsets.all(3.0),
child: Row(children: children),
);
return Row(children: children);
},
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ class SelectOptionTextField extends StatelessWidget {
borderRadius: Corners.s10Border,
),
isDense: true,
prefixIcon: _renderTags(sc),
prefixIcon: _renderTags(context, sc),
hintText: LocaleKeys.grid_selectOption_searchOption.tr(),
prefixIconConstraints: BoxConstraints(maxWidth: distanceToText),
focusedBorder: OutlineInputBorder(
Expand All @@ -90,12 +90,14 @@ class SelectOptionTextField extends StatelessWidget {
);
}

Widget? _renderTags(ScrollController sc) {
Widget? _renderTags(BuildContext context, ScrollController sc) {
if (selectedOptionMap.isEmpty) {
return null;
}

final children = selectedOptionMap.values.map((option) => SelectOptionTag(option: option)).toList();
final children = selectedOptionMap.values
.map((option) => SelectOptionTag.fromSelectOption(context: context, option: option))
.toList();
return Padding(
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
Expand Down

0 comments on commit 18752e7

Please sign in to comment.