mirror of
https://github.com/AppFlowy-IO/AppFlowy.git
synced 2024-08-30 18:12:39 +00:00
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:
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
||||
|
@ -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';
|
||||
|
@ -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';
|
||||
|
@ -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 {
|
@ -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({
|
@ -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({
|
@ -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';
|
@ -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';
|
@ -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;
|
||||
|
@ -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";
|
||||
}
|
@ -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;
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
@ -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() ?? "",
|
||||
);
|
||||
}
|
||||
}
|
@ -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 ?? [],
|
||||
);
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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,
|
||||
);
|
||||
}
|
@ -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 ?? "",
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -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 ?? "",
|
||||
);
|
||||
}
|
||||
}
|
@ -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,
|
||||
);
|
||||
}
|
||||
}
|
@ -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';
|
||||
|
Reference in New Issue
Block a user