chore: reorganize cell code (#4516)

* chore: move cell bloc files to application

* chore: move cell editor widgets to its own folder
This commit is contained in:
Richard Shiue
2024-01-27 10:57:09 +08:00
committed by GitHub
parent 72a23bfe82
commit 4811e65efa
83 changed files with 100 additions and 205 deletions

View File

@ -2,7 +2,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checkbox_cell/checkbox_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checkbox_cell_bloc.dart';
import 'package:flowy_infra_ui/style_widget/icon_button.dart';
import 'package:flowy_infra_ui/widget/spacing.dart';
import 'package:flutter/material.dart';

View File

@ -1,8 +1,8 @@
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_progress_bar.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,7 +1,7 @@
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/date_cell_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,7 +1,7 @@
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/number_cell/number_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/number_cell_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,8 +1,8 @@
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -3,7 +3,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/text_cell/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/widget/flowy_tooltip.dart';
import 'package:flutter/material.dart';

View File

@ -1,7 +1,7 @@
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/timestamp_cell_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,7 +1,7 @@
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/url_cell/url_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,7 +1,7 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checkbox_cell/checkbox_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checkbox_cell_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';

View File

@ -1,8 +1,8 @@
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_editor.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_cell_editor.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_progress_bar.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';

View File

@ -2,8 +2,8 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_editor.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/date_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/number_cell/number_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/number_cell_bloc.dart';
import 'package:flutter/material.dart';
import '../editable_cell_skeleton/number.dart';

View File

@ -1,8 +1,8 @@
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_editor.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/select_option_editor.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/text_cell/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/timestamp_cell_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/widgets.dart';

View File

@ -3,7 +3,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/url_cell/url_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
import 'package:appflowy/workspace/presentation/home/toast.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra/theme_extension.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checkbox_cell/checkbox_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checkbox_cell_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';

View File

@ -1,9 +1,9 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_editor.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_cell_editor.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_progress_bar.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';

View File

@ -2,8 +2,8 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/date.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_editor.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/date_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/number_cell/number_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/number_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

View File

@ -1,8 +1,8 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_editor.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/select_option_editor.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/text_cell/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

View File

@ -1,5 +1,5 @@
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/timestamp_cell_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/widgets.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/cell/desktop_grid/desktop_grid_url_cell.dart';
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/url_cell/url_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checkbox_cell/checkbox_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checkbox_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flutter/material.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flutter/material.dart';

View File

@ -4,7 +4,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/number_cell/number_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/number_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:appflowy_popover/appflowy_popover.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/text_cell/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/timestamp_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart';
import 'package:flutter/material.dart';

View File

@ -5,7 +5,7 @@ import 'package:appflowy/plugins/database/application/cell/cell_controller_build
import 'package:appflowy/plugins/database/application/database_controller.dart';
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/url_cell/url_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checkbox_cell/checkbox_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checkbox_cell_bloc.dart';
import 'package:flutter/material.dart';
import '../editable_cell_skeleton/checkbox.dart';

View File

@ -1,9 +1,9 @@
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/mobile_checklist_cell_editor.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/mobile_checklist_cell_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_she
import 'package:appflowy/mobile/presentation/database/date_picker/mobile_date_picker_screen.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/date.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/date_cell_bloc.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';

View File

@ -1,5 +1,5 @@
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/number_cell/number_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/number_cell_bloc.dart';
import 'package:flutter/material.dart';
import '../editable_cell_skeleton/number.dart';

View File

@ -1,8 +1,8 @@
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/mobile_select_option_editor.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:collection/collection.dart';

View File

@ -1,5 +1,5 @@
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/text_cell/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,5 +1,5 @@
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/timestamp_cell_bloc.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/url_cell/url_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checkbox_cell/checkbox_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checkbox_cell_bloc.dart';
import 'package:flutter/material.dart';
import '../editable_cell_skeleton/checkbox.dart';

View File

@ -1,9 +1,9 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/mobile_checklist_cell_editor.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/checklist_progress_bar.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/mobile_checklist_cell_editor.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';

View File

@ -3,7 +3,7 @@ import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_she
import 'package:appflowy/mobile/presentation/database/date_picker/mobile_date_picker_screen.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/date.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/date_cell/date_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/date_cell_bloc.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/number_cell/number_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/number_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

View File

@ -1,9 +1,9 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/mobile_select_option_editor.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:collection/collection.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/text_cell/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';

View File

@ -1,6 +1,6 @@
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/timestamp_cell/timestamp_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/timestamp_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';
import 'package:flutter/material.dart';

View File

@ -2,7 +2,7 @@ import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/database/widgets/row/accessory/cell_accessory.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/url_cell/url_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/url_cell_bloc.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';

View File

@ -14,7 +14,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'checklist_cell_bloc.dart';
import '../../application/cell/bloc/checklist_cell_bloc.dart';
import 'checklist_progress_bar.dart';
class ChecklistCellEditor extends StatefulWidget {

View File

@ -2,7 +2,7 @@ import 'package:appflowy_editor/appflowy_editor.dart';
import 'package:flowy_infra/theme_extension.dart';
import 'package:flutter/material.dart';
import 'package:percent_indicator/percent_indicator.dart';
import 'checklist_cell_bloc.dart';
import '../../application/cell/bloc/checklist_cell_bloc.dart';
class ChecklistProgressBar extends StatefulWidget {
const ChecklistProgressBar({

View File

@ -9,7 +9,7 @@ import 'package:appflowy/workspace/presentation/widgets/date_picker/widgets/date
import 'package:appflowy_popover/appflowy_popover.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'date_cell_editor_bloc.dart';
import '../../application/cell/bloc/date_cell_editor_bloc.dart';
class DateCellEditor extends StatefulWidget {
const DateCellEditor({

View File

@ -4,7 +4,7 @@ import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/show_mobile_bottom_sheet.dart';
import 'package:appflowy/plugins/base/drag_handler.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/checklist_cell/checklist_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/checklist_cell_bloc.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:flowy_infra_ui/flowy_infra_ui.dart';

View File

@ -5,8 +5,8 @@ import 'package:appflowy/mobile/presentation/widgets/widgets.dart';
import 'package:appflowy/plugins/base/drag_handler.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/extension.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/select_option_cell/select_option_editor_bloc.dart';
import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/select_option_editor_bloc.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
import 'package:easy_localization/easy_localization.dart';

View File

@ -12,12 +12,12 @@ import 'package:flowy_infra_ui/style_widget/hover.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import '../../../../grid/presentation/layout/sizes.dart';
import '../../../../grid/presentation/widgets/common/type_option_separator.dart';
import '../../../../grid/presentation/widgets/header/type_option/select/select_option_editor.dart';
import '../../grid/presentation/layout/sizes.dart';
import '../../grid/presentation/widgets/common/type_option_separator.dart';
import '../../grid/presentation/widgets/header/type_option/select/select_option_editor.dart';
import 'extension.dart';
import 'select_option_editor_bloc.dart';
import 'text_field.dart';
import '../../application/cell/bloc/select_option_editor_bloc.dart';
import 'select_option_text_field.dart';
const double _editorPanelWidth = 300;

View File

@ -1,93 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'checkbox_cell_bloc.freezed.dart';
class CheckboxCellBloc extends Bloc<CheckboxCellEvent, CheckboxCellState> {
CheckboxCellBloc({
required this.cellController,
}) : super(CheckboxCellState.initial(cellController)) {
_dispatch();
}
final CheckboxCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<CheckboxCellEvent>(
(event, emit) {
event.when(
initial: () => _startListening(),
didUpdateCell: (isSelected) {
emit(state.copyWith(isSelected: isSelected));
},
didUpdateField: (fieldName) {
emit(state.copyWith(fieldName: fieldName));
},
select: () {
cellController.saveCellData(state.isSelected ? "No" : "Yes");
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (cellData) {
if (!isClosed) {
add(CheckboxCellEvent.didUpdateCell(_isSelected(cellData)));
}
},
onCellFieldChanged: (field) {
if (!isClosed) {
add(CheckboxCellEvent.didUpdateField(field.name));
}
},
);
}
}
@freezed
class CheckboxCellEvent with _$CheckboxCellEvent {
const factory CheckboxCellEvent.initial() = _Initial;
const factory CheckboxCellEvent.select() = _Selected;
const factory CheckboxCellEvent.didUpdateCell(bool isSelected) =
_DidUpdateCell;
const factory CheckboxCellEvent.didUpdateField(String fieldName) =
_DidUpdateField;
}
@freezed
class CheckboxCellState with _$CheckboxCellState {
const factory CheckboxCellState({
required bool isSelected,
required String fieldName,
}) = _CheckboxCellState;
factory CheckboxCellState.initial(CheckboxCellController cellController) {
return CheckboxCellState(
isSelected: _isSelected(cellController.getCellData()),
fieldName: cellController.fieldInfo.field.name,
);
}
}
bool _isSelected(String? cellData) {
// The backend use "Yes" and "No" to represent the checkbox cell data.
return cellData == "Yes";
}

View File

@ -1,171 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/cell/checklist_cell_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/checklist_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'checklist_cell_bloc.freezed.dart';
class ChecklistSelectOption {
ChecklistSelectOption(this.isSelected, this.data);
final bool isSelected;
final SelectOptionPB data;
}
class ChecklistCellBloc extends Bloc<ChecklistCellEvent, ChecklistCellState> {
ChecklistCellBloc({required this.cellController})
: _checklistCellService = ChecklistCellBackendService(
viewId: cellController.viewId,
fieldId: cellController.fieldId,
rowId: cellController.rowId,
),
super(ChecklistCellState.initial(cellController)) {
_dispatch();
}
final ChecklistCellController cellController;
final ChecklistCellBackendService _checklistCellService;
void Function()? _onCellChangedFn;
void _dispatch() {
on<ChecklistCellEvent>(
(event, emit) async {
await event.when(
initial: () {
_startListening();
},
didReceiveOptions: (data) {
if (data == null) {
emit(
const ChecklistCellState(
tasks: [],
percent: 0,
newTask: false,
),
);
return;
}
emit(
state.copyWith(
tasks: _makeChecklistSelectOptions(data),
percent: data.percentage,
),
);
},
updateTaskName: (option, name) {
_updateOption(option, name);
},
selectTask: (option) async {
await _checklistCellService.select(optionId: option.id);
},
createNewTask: (name) async {
final result = await _checklistCellService.create(name: name);
result.fold(
(l) => emit(state.copyWith(newTask: true)),
(err) => Log.error(err),
);
},
deleteTask: (option) async {
await _deleteOption([option]);
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (data) {
if (!isClosed) {
add(ChecklistCellEvent.didReceiveOptions(data));
}
},
);
}
void _updateOption(SelectOptionPB option, String name) async {
final result =
await _checklistCellService.updateName(option: option, name: name);
result.fold((l) => null, (err) => Log.error(err));
}
Future<void> _deleteOption(List<SelectOptionPB> options) async {
final result = await _checklistCellService.delete(
optionIds: options.map((e) => e.id).toList(),
);
result.fold((l) => null, (err) => Log.error(err));
}
}
@freezed
class ChecklistCellEvent with _$ChecklistCellEvent {
const factory ChecklistCellEvent.initial() = _InitialCell;
const factory ChecklistCellEvent.didReceiveOptions(
ChecklistCellDataPB? data,
) = _DidReceiveCellUpdate;
const factory ChecklistCellEvent.updateTaskName(
SelectOptionPB option,
String name,
) = _UpdateTaskName;
const factory ChecklistCellEvent.selectTask(SelectOptionPB task) =
_SelectTask;
const factory ChecklistCellEvent.createNewTask(String description) =
_CreateNewTask;
const factory ChecklistCellEvent.deleteTask(SelectOptionPB option) =
_DeleteTask;
}
@freezed
class ChecklistCellState with _$ChecklistCellState {
const factory ChecklistCellState({
required List<ChecklistSelectOption> tasks,
required double percent,
required bool newTask,
}) = _ChecklistCellState;
factory ChecklistCellState.initial(ChecklistCellController cellController) {
final cellData = cellController.getCellData(loadIfNotExist: true);
return ChecklistCellState(
tasks: _makeChecklistSelectOptions(cellData),
percent: cellData?.percentage ?? 0,
newTask: false,
);
}
}
List<ChecklistSelectOption> _makeChecklistSelectOptions(
ChecklistCellDataPB? data,
) {
if (data == null) {
return [];
}
final List<ChecklistSelectOption> options = [];
final List<SelectOptionPB> allOptions = List.from(data.options);
final selectedOptionIds = data.selectedOptions.map((e) => e.id).toList();
for (final option in allOptions) {
options.add(
ChecklistSelectOption(selectedOptionIds.contains(option.id), option),
);
}
return options;
}

View File

@ -1,105 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/field/field_info.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'date_cell_bloc.freezed.dart';
class DateCellBloc extends Bloc<DateCellEvent, DateCellState> {
DateCellBloc({required this.cellController})
: super(DateCellState.initial(cellController)) {
_dispatch();
}
final DateCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<DateCellEvent>(
(event, emit) async {
event.when(
initial: () => _startListening(),
didReceiveCellUpdate: (DateCellDataPB? cellData) {
emit(
state.copyWith(
data: cellData,
dateStr: _dateStrFromCellData(cellData),
),
);
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (data) {
if (!isClosed) {
add(DateCellEvent.didReceiveCellUpdate(data));
}
},
);
}
}
@freezed
class DateCellEvent with _$DateCellEvent {
const factory DateCellEvent.initial() = _InitialCell;
const factory DateCellEvent.didReceiveCellUpdate(DateCellDataPB? data) =
_DidReceiveCellUpdate;
}
@freezed
class DateCellState with _$DateCellState {
const factory DateCellState({
required DateCellDataPB? data,
required String dateStr,
required FieldInfo fieldInfo,
}) = _DateCellState;
factory DateCellState.initial(DateCellController context) {
final cellData = context.getCellData();
return DateCellState(
fieldInfo: context.fieldInfo,
data: cellData,
dateStr: _dateStrFromCellData(cellData),
);
}
}
String _dateStrFromCellData(DateCellDataPB? cellData) {
if (cellData == null || !cellData.hasTimestamp()) {
return "";
}
String dateStr = "";
if (cellData.isRange) {
if (cellData.includeTime) {
dateStr =
"${cellData.date} ${cellData.time}${cellData.endDate} ${cellData.endTime}";
} else {
dateStr = "${cellData.date}${cellData.endDate}";
}
} else {
if (cellData.includeTime) {
dateStr = "${cellData.date} ${cellData.time}";
} else {
dateStr = cellData.date;
}
}
return dateStr.trim();
}

View File

@ -1,605 +0,0 @@
import 'dart:async';
import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/cell/date_cell_service.dart';
import 'package:appflowy/plugins/database/application/field/field_service.dart';
import 'package:appflowy/plugins/database/application/field/type_option/type_option_data_parser.dart';
import 'package:appflowy/user/application/reminder/reminder_bloc.dart';
import 'package:appflowy/user/application/reminder/reminder_extension.dart';
import 'package:appflowy/util/int64_extension.dart';
import 'package:appflowy/workspace/presentation/widgets/date_picker/widgets/reminder_selector.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart';
import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart';
import 'package:collection/collection.dart';
import 'package:easy_localization/easy_localization.dart'
show StringTranslateExtension;
import 'package:fixnum/fixnum.dart';
import 'package:flowy_infra/time/duration.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:nanoid/non_secure.dart';
import 'package:protobuf/protobuf.dart';
part 'date_cell_editor_bloc.freezed.dart';
class DateCellEditorBloc
extends Bloc<DateCellEditorEvent, DateCellEditorState> {
DateCellEditorBloc({
required this.cellController,
required ReminderBloc reminderBloc,
}) : _reminderBloc = reminderBloc,
_dateCellBackendService = DateCellBackendService(
viewId: cellController.viewId,
fieldId: cellController.fieldId,
rowId: cellController.rowId,
),
super(DateCellEditorState.initial(cellController, reminderBloc)) {
_dispatch();
}
final DateCellBackendService _dateCellBackendService;
final DateCellController cellController;
final ReminderBloc _reminderBloc;
void Function()? _onCellChangedFn;
void _dispatch() {
on<DateCellEditorEvent>(
(event, emit) async {
await event.when(
initial: () async => _startListening(),
didReceiveCellUpdate: (DateCellDataPB? cellData) {
final dateCellData = _dateDataFromCellData(cellData);
final endDay =
dateCellData.isRange == state.isRange && dateCellData.isRange
? dateCellData.endDateTime
: null;
if (dateCellData.dateTime != null &&
(state.reminderId?.isEmpty ?? true) &&
(dateCellData.reminderId?.isNotEmpty ?? false) &&
state.reminderOption != ReminderOption.none) {
// Add Reminder
_reminderBloc.add(
ReminderEvent.addById(
reminderId: dateCellData.reminderId!,
objectId: cellController.viewId,
meta: {ReminderMetaKeys.rowId: cellController.rowId},
scheduledAt: Int64(
dateCellData.dateTime!
.subtract(state.reminderOption.time)
.millisecondsSinceEpoch ~/
1000,
),
),
);
}
if ((dateCellData.reminderId?.isNotEmpty ?? false) &&
dateCellData.dateTime != null) {
// Update Reminder
_reminderBloc.add(
ReminderEvent.update(
ReminderUpdate(
id: state.reminderId!,
scheduledAt: dateCellData.dateTime!
.subtract(state.reminderOption.time),
),
),
);
}
emit(
state.copyWith(
dateTime: dateCellData.dateTime,
timeStr: dateCellData.timeStr,
endDateTime: dateCellData.endDateTime,
endTimeStr: dateCellData.endTimeStr,
includeTime: dateCellData.includeTime,
isRange: dateCellData.isRange,
startDay: dateCellData.isRange ? dateCellData.dateTime : null,
endDay: endDay,
dateStr: dateCellData.dateStr,
endDateStr: dateCellData.endDateStr,
reminderId: dateCellData.reminderId,
),
);
},
didReceiveTimeFormatError: (
String? parseTimeError,
String? parseEndTimeError,
) {
emit(
state.copyWith(
parseTimeError: parseTimeError,
parseEndTimeError: parseEndTimeError,
),
);
},
selectDay: (date) async {
if (!state.isRange) {
await _updateDateData(date: date);
}
},
setIncludeTime: (includeTime) async =>
_updateDateData(includeTime: includeTime),
setIsRange: (isRange) async => _updateDateData(isRange: isRange),
setTime: (timeStr) async {
emit(state.copyWith(timeStr: timeStr));
await _updateDateData(timeStr: timeStr);
},
selectDateRange: (DateTime? start, DateTime? end) async {
if (end == null && state.startDay != null && state.endDay == null) {
final (newStart, newEnd) = state.startDay!.isBefore(start!)
? (state.startDay!, start)
: (start, state.startDay!);
emit(state.copyWith(startDay: null, endDay: null));
await _updateDateData(date: newStart.date, endDate: newEnd.date);
} else if (end == null) {
emit(state.copyWith(startDay: start, endDay: null));
} else {
await _updateDateData(date: start!.date, endDate: end.date);
}
},
setStartDay: (DateTime startDay) async {
if (state.endDay == null) {
emit(state.copyWith(startDay: startDay));
} else if (startDay.isAfter(state.endDay!)) {
emit(state.copyWith(startDay: startDay, endDay: null));
} else {
emit(state.copyWith(startDay: startDay));
await _updateDateData(
date: startDay.date,
endDate: state.endDay!.date,
);
}
},
setEndDay: (DateTime endDay) {
if (state.startDay == null) {
emit(state.copyWith(endDay: endDay));
} else if (endDay.isBefore(state.startDay!)) {
emit(state.copyWith(startDay: null, endDay: endDay));
} else {
emit(state.copyWith(endDay: endDay));
_updateDateData(date: state.startDay!.date, endDate: endDay.date);
}
},
setEndTime: (String? endTime) async {
emit(state.copyWith(endTimeStr: endTime));
await _updateDateData(endTimeStr: endTime);
},
setDateFormat: (DateFormatPB dateFormat) async =>
await _updateTypeOption(emit, dateFormat: dateFormat),
setTimeFormat: (TimeFormatPB timeFormat) async =>
await _updateTypeOption(emit, timeFormat: timeFormat),
clearDate: () async {
// Remove reminder if neccessary
if (state.reminderId != null) {
_reminderBloc
.add(ReminderEvent.remove(reminderId: state.reminderId!));
}
await _clearDate();
},
setReminderOption: (ReminderOption option) async {
if (state.reminderId?.isEmpty ??
true &&
state.dateTime != null &&
option != ReminderOption.none) {
// New Reminder
final reminderId = nanoid();
await _updateDateData(reminderId: reminderId);
emit(state.copyWith(reminderOption: option));
} else if (option == ReminderOption.none &&
(state.reminderId?.isNotEmpty ?? false)) {
// Remove reminder
_reminderBloc
.add(ReminderEvent.remove(reminderId: state.reminderId!));
await _updateDateData(reminderId: "");
emit(state.copyWith(reminderOption: option));
} else if (state.dateTime != null &&
(state.reminderId?.isNotEmpty ?? false)) {
// Update reminder
_reminderBloc.add(
ReminderEvent.update(
ReminderUpdate(
id: state.reminderId!,
scheduledAt: state.dateTime!.subtract(option.time),
),
),
);
}
},
// Empty String signifies no reminder
removeReminder: () async => _updateDateData(reminderId: ""),
);
},
);
}
Future<void> _updateDateData({
DateTime? date,
String? timeStr,
DateTime? endDate,
String? endTimeStr,
bool? includeTime,
bool? isRange,
String? reminderId,
}) async {
// make sure that not both date and time are updated at the same time
assert(
!(date != null && timeStr != null) ||
!(endDate != null && endTimeStr != null),
);
// if not updating the time, use the old time in the state
final String? newTime = timeStr ?? state.timeStr;
final DateTime? newDate = timeStr != null && timeStr.isNotEmpty
? state.dateTime ?? DateTime.now()
: _utcToLocalAndAddCurrentTime(date);
// if not updating the time, use the old time in the state
final String? newEndTime = endTimeStr ?? state.endTimeStr;
final DateTime? newEndDate = endTimeStr != null && endTimeStr.isNotEmpty
? state.endDateTime ?? DateTime.now()
: _utcToLocalAndAddCurrentTime(endDate);
final result = await _dateCellBackendService.update(
date: newDate,
time: newTime,
endDate: newEndDate,
endTime: newEndTime,
includeTime: includeTime ?? state.includeTime,
isRange: isRange ?? state.isRange,
reminderId: reminderId ?? state.reminderId,
);
result.fold(
(_) {
if (!isClosed &&
(state.parseEndTimeError != null || state.parseTimeError != null)) {
add(const DateCellEditorEvent.didReceiveTimeFormatError(null, null));
}
},
(err) {
switch (err.code) {
case ErrorCode.InvalidDateTimeFormat:
if (isClosed) {
return;
}
// to determine which textfield should show error
final (startError, endError) = newDate != null
? (timeFormatPrompt(err), null)
: (null, timeFormatPrompt(err));
add(
DateCellEditorEvent.didReceiveTimeFormatError(
startError,
endError,
),
);
break;
default:
Log.error(err);
}
},
);
}
Future<void> _clearDate() async {
final result = await _dateCellBackendService.clear();
result.fold(
(_) {
if (!isClosed) {
add(const DateCellEditorEvent.didReceiveTimeFormatError(null, null));
}
},
(err) => Log.error(err),
);
}
DateTime? _utcToLocalAndAddCurrentTime(DateTime? date) {
if (date == null) {
return null;
}
final now = DateTime.now();
// the incoming date is Utc. This trick converts it into Local
// and add the current time. The time may be overwritten by
// explicitly provided time string in the backend though
return DateTime(
date.year,
date.month,
date.day,
now.hour,
now.minute,
now.second,
);
}
String timeFormatPrompt(FlowyError error) {
return switch (state.dateTypeOptionPB.timeFormat) {
TimeFormatPB.TwelveHour =>
"${LocaleKeys.grid_field_invalidTimeFormat.tr()}. e.g. 01:00 PM",
TimeFormatPB.TwentyFourHour =>
"${LocaleKeys.grid_field_invalidTimeFormat.tr()}. e.g. 13:00",
_ => "",
};
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (cell) {
if (!isClosed) {
add(DateCellEditorEvent.didReceiveCellUpdate(cell));
}
},
);
}
Future<void>? _updateTypeOption(
Emitter<DateCellEditorState> emit, {
DateFormatPB? dateFormat,
TimeFormatPB? timeFormat,
}) async {
state.dateTypeOptionPB.freeze();
final newDateTypeOption = state.dateTypeOptionPB.rebuild((typeOption) {
if (dateFormat != null) {
typeOption.dateFormat = dateFormat;
}
if (timeFormat != null) {
typeOption.timeFormat = timeFormat;
}
});
final result = await FieldBackendService.updateFieldTypeOption(
viewId: cellController.viewId,
fieldId: cellController.fieldInfo.id,
typeOptionData: newDateTypeOption.writeToBuffer(),
);
result.fold(
(_) => emit(
state.copyWith(
dateTypeOptionPB: newDateTypeOption,
timeHintText: _timeHintText(newDateTypeOption),
),
),
(err) => Log.error(err),
);
}
}
@freezed
class DateCellEditorEvent with _$DateCellEditorEvent {
// initial event
const factory DateCellEditorEvent.initial() = _Initial;
// notification that cell is updated in the backend
const factory DateCellEditorEvent.didReceiveCellUpdate(
DateCellDataPB? data,
) = _DidReceiveCellUpdate;
const factory DateCellEditorEvent.didReceiveTimeFormatError(
String? parseTimeError,
String? parseEndTimeError,
) = _DidReceiveTimeFormatError;
// date cell data is modified
const factory DateCellEditorEvent.selectDay(DateTime day) = _SelectDay;
const factory DateCellEditorEvent.selectDateRange(
DateTime? start,
DateTime? end,
) = _SelectDateRange;
const factory DateCellEditorEvent.setStartDay(
DateTime startDay,
) = _SetStartDay;
const factory DateCellEditorEvent.setEndDay(
DateTime endDay,
) = _SetEndDay;
const factory DateCellEditorEvent.setTime(String time) = _SetTime;
const factory DateCellEditorEvent.setEndTime(String endTime) = _SetEndTime;
const factory DateCellEditorEvent.setIncludeTime(bool includeTime) =
_IncludeTime;
const factory DateCellEditorEvent.setIsRange(bool isRange) = _SetIsRange;
const factory DateCellEditorEvent.setReminderOption({
required ReminderOption option,
}) = _SetReminderOption;
const factory DateCellEditorEvent.removeReminder() = _RemoveReminder;
// date field type options are modified
const factory DateCellEditorEvent.setTimeFormat(TimeFormatPB timeFormat) =
_SetTimeFormat;
const factory DateCellEditorEvent.setDateFormat(DateFormatPB dateFormat) =
_SetDateFormat;
const factory DateCellEditorEvent.clearDate() = _ClearDate;
}
@freezed
class DateCellEditorState with _$DateCellEditorState {
const factory DateCellEditorState({
// the date field's type option
required DateTypeOptionPB dateTypeOptionPB,
// used when selecting a date range
required DateTime? startDay,
required DateTime? endDay,
// cell data from the backend
required DateTime? dateTime,
required DateTime? endDateTime,
required String? timeStr,
required String? endTimeStr,
required bool includeTime,
required bool isRange,
required String? dateStr,
required String? endDateStr,
required String? reminderId,
// error and hint text
required String? parseTimeError,
required String? parseEndTimeError,
required String timeHintText,
@Default(ReminderOption.none) ReminderOption reminderOption,
}) = _DateCellEditorState;
factory DateCellEditorState.initial(
DateCellController controller,
ReminderBloc reminderBloc,
) {
final typeOption = controller.getTypeOption(DateTypeOptionDataParser());
final cellData = controller.getCellData();
final dateCellData = _dateDataFromCellData(cellData);
ReminderOption reminderOption = ReminderOption.none;
if ((dateCellData.reminderId?.isNotEmpty ?? false) &&
dateCellData.dateTime != null) {
final reminder = reminderBloc.state.reminders
.firstWhereOrNull((r) => r.id == dateCellData.reminderId);
if (reminder != null) {
reminderOption = ReminderOption.fromDateDifference(
dateCellData.dateTime!,
reminder.scheduledAt.toDateTime(),
);
}
}
return DateCellEditorState(
dateTypeOptionPB: typeOption,
startDay: dateCellData.isRange ? dateCellData.dateTime : null,
endDay: dateCellData.isRange ? dateCellData.endDateTime : null,
dateTime: dateCellData.dateTime,
endDateTime: dateCellData.endDateTime,
timeStr: dateCellData.timeStr,
endTimeStr: dateCellData.endTimeStr,
dateStr: dateCellData.dateStr,
endDateStr: dateCellData.endDateStr,
includeTime: dateCellData.includeTime,
isRange: dateCellData.isRange,
parseTimeError: null,
parseEndTimeError: null,
timeHintText: _timeHintText(typeOption),
reminderId: dateCellData.reminderId,
reminderOption: reminderOption,
);
}
}
String _timeHintText(DateTypeOptionPB typeOption) {
switch (typeOption.timeFormat) {
case TimeFormatPB.TwelveHour:
return LocaleKeys.document_date_timeHintTextInTwelveHour.tr();
case TimeFormatPB.TwentyFourHour:
return LocaleKeys.document_date_timeHintTextInTwentyFourHour.tr();
default:
return "";
}
}
_DateCellData _dateDataFromCellData(
DateCellDataPB? cellData,
) {
// a null DateCellDataPB may be returned, indicating that all the fields are
// their default values: empty strings and false booleans
if (cellData == null) {
return _DateCellData(
dateTime: null,
endDateTime: null,
timeStr: null,
endTimeStr: null,
includeTime: false,
isRange: false,
dateStr: null,
endDateStr: null,
reminderId: null,
);
}
DateTime? dateTime;
String? timeStr;
DateTime? endDateTime;
String? endTimeStr;
String? endDateStr;
if (cellData.hasTimestamp()) {
final timestamp = cellData.timestamp * 1000;
dateTime = DateTime.fromMillisecondsSinceEpoch(timestamp.toInt());
timeStr = cellData.time;
if (cellData.hasEndTimestamp()) {
final endTimestamp = cellData.endTimestamp * 1000;
endDateTime = DateTime.fromMillisecondsSinceEpoch(endTimestamp.toInt());
endTimeStr = cellData.endTime;
}
}
final bool includeTime = cellData.includeTime;
final bool isRange = cellData.isRange;
if (cellData.isRange) {
endDateStr = cellData.endDate;
}
final String dateStr = cellData.date;
return _DateCellData(
dateTime: dateTime,
endDateTime: endDateTime,
timeStr: timeStr,
endTimeStr: endTimeStr,
includeTime: includeTime,
isRange: isRange,
dateStr: dateStr,
endDateStr: endDateStr,
reminderId: cellData.reminderId,
);
}
class _DateCellData {
_DateCellData({
required this.dateTime,
required this.endDateTime,
required this.timeStr,
required this.endTimeStr,
required this.includeTime,
required this.isRange,
required this.dateStr,
required this.endDateStr,
required this.reminderId,
});
final DateTime? dateTime;
final DateTime? endDateTime;
final String? timeStr;
final String? endTimeStr;
final bool includeTime;
final bool isRange;
final String? dateStr;
final String? endDateStr;
final String? reminderId;
}

View File

@ -1,88 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'number_cell_bloc.freezed.dart';
class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
NumberCellBloc({required this.cellController})
: super(NumberCellState.initial(cellController)) {
_dispatch();
}
final NumberCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<NumberCellEvent>(
(event, emit) async {
event.when(
initial: () {
_startListening();
},
didReceiveCellUpdate: (cellData) {
emit(state.copyWith(content: cellData ?? ""));
},
updateCell: (text) async {
if (state.content != text) {
emit(state.copyWith(content: text));
await cellController.saveCellData(text);
// If the input content is "abc" that can't parsered as number then the data stored in the backend will be an empty string.
// So for every cell data that will be formatted in the backend.
// It needs to get the formatted data after saving.
add(
NumberCellEvent.didReceiveCellUpdate(
cellController.getCellData(),
),
);
}
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (cellContent) {
if (!isClosed) {
add(NumberCellEvent.didReceiveCellUpdate(cellContent));
}
},
);
}
}
@freezed
class NumberCellEvent with _$NumberCellEvent {
const factory NumberCellEvent.initial() = _Initial;
const factory NumberCellEvent.updateCell(String text) = _UpdateCell;
const factory NumberCellEvent.didReceiveCellUpdate(String? cellContent) =
_DidReceiveCellUpdate;
}
@freezed
class NumberCellState with _$NumberCellState {
const factory NumberCellState({
required String content,
}) = _NumberCellState;
factory NumberCellState.initial(TextCellController cellController) {
return NumberCellState(
content: cellController.getCellData() ?? "",
);
}
}

View File

@ -1,87 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'select_option_cell_bloc.freezed.dart';
class SelectOptionCellBloc
extends Bloc<SelectOptionCellEvent, SelectOptionCellState> {
SelectOptionCellBloc({required this.cellController})
: super(SelectOptionCellState.initial(cellController)) {
_dispatch();
}
final SelectOptionCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<SelectOptionCellEvent>(
(event, emit) async {
await event.when(
initial: () async {
_startListening();
},
didReceiveOptions: (List<SelectOptionPB> selectedOptions) {
emit(
state.copyWith(
selectedOptions: selectedOptions,
),
);
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (selectOptionCellData) {
if (!isClosed) {
add(
SelectOptionCellEvent.didReceiveOptions(
selectOptionCellData?.selectOptions ?? [],
),
);
}
},
);
}
}
@freezed
class SelectOptionCellEvent with _$SelectOptionCellEvent {
const factory SelectOptionCellEvent.initial() = _InitialCell;
const factory SelectOptionCellEvent.didReceiveOptions(
List<SelectOptionPB> selectedOptions,
) = _DidReceiveOptions;
}
@freezed
class SelectOptionCellState with _$SelectOptionCellState {
const factory SelectOptionCellState({
required List<SelectOptionPB> selectedOptions,
}) = _SelectOptionCellState;
factory SelectOptionCellState.initial(
SelectOptionCellController cellController,
) {
final data = cellController.getCellData();
return SelectOptionCellState(
selectedOptions: data?.selectOptions ?? [],
);
}
}

View File

@ -1,322 +0,0 @@
import 'dart:async';
import 'package:flutter/widgets.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/cell/select_option_cell_service.dart';
import 'package:appflowy_backend/log.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart';
import 'package:dartz/dartz.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'select_option_editor_bloc.freezed.dart';
class SelectOptionCellEditorBloc
extends Bloc<SelectOptionEditorEvent, SelectOptionEditorState> {
SelectOptionCellEditorBloc({required this.cellController})
: _selectOptionService = SelectOptionCellBackendService(
viewId: cellController.viewId,
fieldId: cellController.fieldId,
rowId: cellController.rowId,
),
super(SelectOptionEditorState.initial(cellController)) {
_dispatch();
}
final SelectOptionCellBackendService _selectOptionService;
final SelectOptionCellController cellController;
VoidCallback? _onCellChangedFn;
void _dispatch() {
on<SelectOptionEditorEvent>(
(event, emit) async {
await event.when(
initial: () async {
_startListening();
await _loadOptions();
},
didReceiveOptions: (options, selectedOptions) {
final result = _makeOptions(state.filter, options);
emit(
state.copyWith(
allOptions: options,
options: result.options,
createOption: result.createOption,
selectedOptions: selectedOptions,
),
);
},
newOption: (optionName) async {
await _createOption(optionName);
emit(
state.copyWith(
filter: none(),
),
);
},
deleteOption: (option) async {
await _deleteOption([option]);
},
deleteAllOptions: () async {
if (state.allOptions.isNotEmpty) {
await _deleteOption(state.allOptions);
}
},
updateOption: (option) async {
await _updateOption(option);
},
selectOption: (optionId) async {
await _selectOptionService.select(optionIds: [optionId]);
final selectedOption = [
...state.selectedOptions,
state.options.firstWhere(
(element) => element.id == optionId,
),
];
emit(
state.copyWith(
selectedOptions: selectedOption,
),
);
},
unSelectOption: (optionId) async {
await _selectOptionService.unSelect(optionIds: [optionId]);
final selectedOptions = [...state.selectedOptions]
..removeWhere((e) => e.id == optionId);
emit(
state.copyWith(
selectedOptions: selectedOptions,
),
);
},
trySelectOption: (optionName) {
_trySelectOption(optionName, emit);
},
selectMultipleOptions: (optionNames, remainder) {
if (optionNames.isNotEmpty) {
_selectMultipleOptions(optionNames);
}
_filterOption(remainder, emit);
},
filterOption: (optionName) {
_filterOption(optionName, emit);
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
return super.close();
}
Future<void> _createOption(String name) async {
final result = await _selectOptionService.create(name: name);
result.fold((l) => {}, (err) => Log.error(err));
}
Future<void> _deleteOption(List<SelectOptionPB> options) async {
final result = await _selectOptionService.delete(options: options);
result.fold((l) => null, (err) => Log.error(err));
}
Future<void> _updateOption(SelectOptionPB option) async {
final result = await _selectOptionService.update(
option: option,
);
result.fold((l) => null, (err) => Log.error(err));
}
void _trySelectOption(
String optionName,
Emitter<SelectOptionEditorState> emit,
) {
SelectOptionPB? matchingOption;
bool optionExistsButSelected = false;
for (final option in state.options) {
if (option.name.toLowerCase() == optionName.toLowerCase()) {
if (!state.selectedOptions.contains(option)) {
matchingOption = option;
break;
} else {
optionExistsButSelected = true;
}
}
}
// if there isn't a matching option at all, then create it
if (matchingOption == null && !optionExistsButSelected) {
_createOption(optionName);
}
// if there is an unselected matching option, select it
if (matchingOption != null) {
_selectOptionService.select(optionIds: [matchingOption.id]);
}
// clear the filter
emit(state.copyWith(filter: none()));
}
void _selectMultipleOptions(List<String> optionNames) {
// The options are unordered. So in order to keep the inserted [optionNames]
// order, it needs to get the option id in the [optionNames] order.
final lowerCaseNames = optionNames.map((e) => e.toLowerCase());
final Map<String, String> optionIdsMap = {};
for (final option in state.options) {
optionIdsMap[option.name.toLowerCase()] = option.id;
}
final optionIds = lowerCaseNames
.where((name) => optionIdsMap[name] != null)
.map((name) => optionIdsMap[name]!)
.toList();
_selectOptionService.select(optionIds: optionIds);
}
void _filterOption(String optionName, Emitter<SelectOptionEditorState> emit) {
final _MakeOptionResult result = _makeOptions(
Some(optionName),
state.allOptions,
);
emit(
state.copyWith(
filter: Some(optionName),
options: result.options,
createOption: result.createOption,
),
);
}
Future<void> _loadOptions() async {
final result = await _selectOptionService.getCellData();
if (isClosed) {
Log.warn("Unexpected closing the bloc");
return;
}
return result.fold(
(data) => add(
SelectOptionEditorEvent.didReceiveOptions(
data.options,
data.selectOptions,
),
),
(err) {
Log.error(err);
return null;
},
);
}
_MakeOptionResult _makeOptions(
Option<String> filter,
List<SelectOptionPB> allOptions,
) {
final List<SelectOptionPB> options = List.from(allOptions);
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);
});
} else {
createOption = none();
}
});
return _MakeOptionResult(
options: options,
createOption: createOption,
);
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (selectOptionContext) {
_loadOptions();
},
onCellFieldChanged: (field) {
_loadOptions();
},
);
}
}
@freezed
class SelectOptionEditorEvent with _$SelectOptionEditorEvent {
const factory SelectOptionEditorEvent.initial() = _Initial;
const factory SelectOptionEditorEvent.didReceiveOptions(
List<SelectOptionPB> options,
List<SelectOptionPB> selectedOptions,
) = _DidReceiveOptions;
const factory SelectOptionEditorEvent.newOption(String optionName) =
_NewOption;
const factory SelectOptionEditorEvent.selectOption(String optionId) =
_SelectOption;
const factory SelectOptionEditorEvent.unSelectOption(String optionId) =
_UnSelectOption;
const factory SelectOptionEditorEvent.updateOption(SelectOptionPB option) =
_UpdateOption;
const factory SelectOptionEditorEvent.deleteOption(SelectOptionPB option) =
_DeleteOption;
const factory SelectOptionEditorEvent.deleteAllOptions() = _DeleteAllOptions;
const factory SelectOptionEditorEvent.filterOption(String optionName) =
_SelectOptionFilter;
const factory SelectOptionEditorEvent.trySelectOption(String optionName) =
_TrySelectOption;
const factory SelectOptionEditorEvent.selectMultipleOptions(
List<String> optionNames,
String remainder,
) = _SelectMultipleOptions;
}
@freezed
class SelectOptionEditorState with _$SelectOptionEditorState {
const factory SelectOptionEditorState({
required List<SelectOptionPB> options,
required List<SelectOptionPB> allOptions,
required List<SelectOptionPB> selectedOptions,
required Option<String> createOption,
required Option<String> filter,
}) = _SelectOptionEditorState;
factory SelectOptionEditorState.initial(SelectOptionCellController context) {
final data = context.getCellData(loadIfNotExist: false);
return SelectOptionEditorState(
options: data?.options ?? [],
allOptions: data?.options ?? [],
selectedOptions: data?.selectOptions ?? [],
createOption: none(),
filter: none(),
);
}
}
class _MakeOptionResult {
_MakeOptionResult({
required this.options,
required this.createOption,
});
List<SelectOptionPB> options;
Option<String> createOption;
}

View File

@ -1,95 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'text_cell_bloc.freezed.dart';
class TextCellBloc extends Bloc<TextCellEvent, TextCellState> {
TextCellBloc({required this.cellController})
: super(TextCellState.initial(cellController)) {
_dispatch();
}
final TextCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<TextCellEvent>(
(event, emit) {
event.when(
initial: () {
_startListening();
},
didReceiveCellUpdate: (String content) {
emit(state.copyWith(content: content));
},
didUpdateEmoji: (String emoji) {
emit(state.copyWith(emoji: emoji));
},
updateText: (String text) {
if (state.content != text) {
cellController.saveCellData(text, debounce: true);
}
},
enableEdit: (bool enabled) {
emit(state.copyWith(enableEdit: enabled));
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (cellContent) {
if (!isClosed) {
add(TextCellEvent.didReceiveCellUpdate(cellContent ?? ""));
}
},
onRowMetaChanged: () {
if (!isClosed && cellController.fieldInfo.isPrimary) {
add(TextCellEvent.didUpdateEmoji(cellController.icon ?? ""));
}
},
);
}
}
@freezed
class TextCellEvent with _$TextCellEvent {
const factory TextCellEvent.initial() = _InitialCell;
const factory TextCellEvent.didReceiveCellUpdate(String cellContent) =
_DidReceiveCellUpdate;
const factory TextCellEvent.updateText(String text) = _UpdateText;
const factory TextCellEvent.enableEdit(bool enabled) = _EnableEdit;
const factory TextCellEvent.didUpdateEmoji(String emoji) = _UpdateEmoji;
}
@freezed
class TextCellState with _$TextCellState {
const factory TextCellState({
required String content,
required String emoji,
required bool enableEdit,
}) = _TextCellState;
factory TextCellState.initial(TextCellController cellController) =>
TextCellState(
content: cellController.getCellData() ?? "",
emoji:
cellController.fieldInfo.isPrimary ? cellController.icon ?? "" : "",
enableEdit: false,
);
}

View File

@ -1,84 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/field/field_info.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/timestamp_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'timestamp_cell_bloc.freezed.dart';
class TimestampCellBloc extends Bloc<TimestampCellEvent, TimestampCellState> {
TimestampCellBloc({required this.cellController})
: super(TimestampCellState.initial(cellController)) {
_dispatch();
}
final TimestampCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<TimestampCellEvent>(
(event, emit) async {
event.when(
initial: () => _startListening(),
didReceiveCellUpdate: (TimestampCellDataPB? cellData) {
emit(
state.copyWith(
data: cellData,
dateStr: cellData?.dateTime ?? "",
),
);
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (data) {
if (!isClosed) {
add(TimestampCellEvent.didReceiveCellUpdate(data));
}
},
);
}
}
@freezed
class TimestampCellEvent with _$TimestampCellEvent {
const factory TimestampCellEvent.initial() = _InitialCell;
const factory TimestampCellEvent.didReceiveCellUpdate(
TimestampCellDataPB? data,
) = _DidReceiveCellUpdate;
}
@freezed
class TimestampCellState with _$TimestampCellState {
const factory TimestampCellState({
required TimestampCellDataPB? data,
required String dateStr,
required FieldInfo fieldInfo,
}) = _TimestampCellState;
factory TimestampCellState.initial(TimestampCellController context) {
final cellData = context.getCellData();
return TimestampCellState(
fieldInfo: context.fieldInfo,
data: cellData,
dateStr: cellData?.dateTime ?? "",
);
}
}

View File

@ -1,106 +0,0 @@
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'url_cell_editor_bloc.dart';
class URLCellEditor extends StatefulWidget {
const URLCellEditor({
super.key,
required this.cellController,
required this.onExit,
});
final URLCellController cellController;
final VoidCallback onExit;
@override
State<URLCellEditor> createState() => _URLCellEditorState();
}
class _URLCellEditorState extends State<URLCellEditor> {
late URLCellEditorBloc _cellBloc;
late TextEditingController _controller;
@override
void initState() {
_cellBloc = URLCellEditorBloc(cellController: widget.cellController);
_cellBloc.add(const URLCellEditorEvent.initial());
_controller = TextEditingController(text: _cellBloc.state.content);
super.initState();
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(
value: _cellBloc,
child: BlocListener<URLCellEditorBloc, URLCellEditorState>(
listener: (context, state) {
if (_controller.text != state.content) {
_controller.text = state.content;
}
if (state.isFinishEditing) {
widget.onExit();
}
},
child: TextField(
autofocus: true,
controller: _controller,
onSubmitted: (value) => focusChanged(),
onEditingComplete: () => focusChanged(),
style: Theme.of(context).textTheme.bodyMedium,
decoration: const InputDecoration(
contentPadding: EdgeInsets.zero,
border: InputBorder.none,
hintText: "",
isDense: true,
),
),
),
);
}
@override
Future<void> dispose() async {
_cellBloc.close();
super.dispose();
}
void focusChanged() {
if (mounted) {
if (_cellBloc.isClosed == false &&
_controller.text != _cellBloc.state.content) {
_cellBloc.add(URLCellEditorEvent.updateText(_controller.text));
}
}
}
}
class URLEditorPopover extends StatelessWidget {
const URLEditorPopover({
super.key,
required this.cellController,
required this.onExit,
});
final URLCellController cellController;
final VoidCallback onExit;
@override
Widget build(BuildContext context) {
return Container(
decoration: BoxDecoration(
color: Theme.of(context).cardColor,
borderRadius: BorderRadius.circular(4),
),
padding: const EdgeInsets.all(12),
child: URLCellEditor(
cellController: cellController,
onExit: onExit,
),
);
}
}

View File

@ -1,85 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/url_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'url_cell_bloc.freezed.dart';
class URLCellBloc extends Bloc<URLCellEvent, URLCellState> {
URLCellBloc({required this.cellController})
: super(URLCellState.initial(cellController)) {
_dispatch();
}
final URLCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<URLCellEvent>(
(event, emit) async {
event.when(
initial: () {
_startListening();
},
didReceiveCellUpdate: (cellData) {
emit(
state.copyWith(
content: cellData?.content ?? "",
url: cellData?.url ?? "",
),
);
},
updateURL: (String url) {
cellController.saveCellData(url, debounce: true);
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (cellData) {
if (!isClosed) {
add(URLCellEvent.didReceiveCellUpdate(cellData));
}
},
);
}
}
@freezed
class URLCellEvent with _$URLCellEvent {
const factory URLCellEvent.initial() = _InitialCell;
const factory URLCellEvent.updateURL(String url) = _UpdateURL;
const factory URLCellEvent.didReceiveCellUpdate(URLCellDataPB? cell) =
_DidReceiveCellUpdate;
}
@freezed
class URLCellState with _$URLCellState {
const factory URLCellState({
required String content,
required String url,
}) = _URLCellState;
factory URLCellState.initial(URLCellController context) {
final cellData = context.getCellData();
return URLCellState(
content: cellData?.content ?? "",
url: cellData?.url ?? "",
);
}
}

View File

@ -1,86 +0,0 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy_backend/protobuf/flowy-database2/url_entities.pb.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:freezed_annotation/freezed_annotation.dart';
part 'url_cell_editor_bloc.freezed.dart';
class URLCellEditorBloc extends Bloc<URLCellEditorEvent, URLCellEditorState> {
URLCellEditorBloc({required this.cellController})
: super(URLCellEditorState.initial(cellController)) {
_dispatch();
}
final URLCellController cellController;
void Function()? _onCellChangedFn;
void _dispatch() {
on<URLCellEditorEvent>(
(event, emit) async {
await event.when(
initial: () {
_startListening();
},
updateText: (text) async {
await cellController.saveCellData(text);
emit(
state.copyWith(
content: text,
isFinishEditing: true,
),
);
},
didReceiveCellUpdate: (cellData) {
emit(state.copyWith(content: cellData?.content ?? ""));
},
);
},
);
}
@override
Future<void> close() async {
if (_onCellChangedFn != null) {
cellController.removeListener(_onCellChangedFn!);
_onCellChangedFn = null;
}
await cellController.dispose();
return super.close();
}
void _startListening() {
_onCellChangedFn = cellController.addListener(
onCellChanged: (cellData) {
if (!isClosed) {
add(URLCellEditorEvent.didReceiveCellUpdate(cellData));
}
},
);
}
}
@freezed
class URLCellEditorEvent with _$URLCellEditorEvent {
const factory URLCellEditorEvent.initial() = _InitialCell;
const factory URLCellEditorEvent.didReceiveCellUpdate(URLCellDataPB? cell) =
_DidReceiveCellUpdate;
const factory URLCellEditorEvent.updateText(String text) = _UpdateText;
}
@freezed
class URLCellEditorState with _$URLCellEditorState {
const factory URLCellEditorState({
required String content,
required bool isFinishEditing,
}) = _URLCellEditorState;
factory URLCellEditorState.initial(URLCellController context) {
final cellData = context.getCellData();
return URLCellEditorState(
content: cellData?.content ?? "",
isFinishEditing: true,
);
}
}

View File

@ -6,7 +6,7 @@ import 'package:appflowy/plugins/database/application/row/row_controller.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_builder.dart';
import 'package:appflowy/plugins/database/widgets/cell/editable_cell_skeleton/text.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/cell_container.dart';
import 'package:appflowy/plugins/database/widgets/row/cells/text_cell/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/application/cell/bloc/text_cell_bloc.dart';
import 'package:appflowy/plugins/database/widgets/row/row_action.dart';
import 'package:appflowy/workspace/presentation/settings/widgets/emoji_picker/emoji_picker.dart';
import 'package:appflowy_popover/appflowy_popover.dart';