diff --git a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart index 540779b1a1..4d9869e349 100644 --- a/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart +++ b/frontend/appflowy_flutter/lib/plugins/ai_chat/chat.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/ai_chat/chat_page.dart'; import 'package:appflowy/plugins/util.dart'; @@ -7,7 +9,6 @@ import 'package:appflowy/workspace/presentation/home/home_stack.dart'; import 'package:appflowy/workspace/presentation/widgets/tab_bar_item.dart'; import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class AIChatPluginBuilder extends PluginBuilder { @@ -65,6 +66,13 @@ class AIChatPagePlugin extends Plugin { _viewInfoBloc = ViewInfoBloc(view: notifier.view) ..add(const ViewInfoEvent.started()); } + + @override + void dispose() { + _viewInfoBloc.close(); + notifier.dispose(); + super.dispose(); + } } class AIChatPagePluginWidgetBuilder extends PluginWidgetBuilder diff --git a/frontend/appflowy_flutter/lib/plugins/base/emoji/emoji_picker.dart b/frontend/appflowy_flutter/lib/plugins/base/emoji/emoji_picker.dart index d7a7b9ceb2..bcdcf9816d 100644 --- a/frontend/appflowy_flutter/lib/plugins/base/emoji/emoji_picker.dart +++ b/frontend/appflowy_flutter/lib/plugins/base/emoji/emoji_picker.dart @@ -1,9 +1,10 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/plugins/base/emoji/emoji_picker_header.dart'; import 'package:appflowy/plugins/base/emoji/emoji_search_bar.dart'; import 'package:appflowy/plugins/base/emoji/emoji_skin_tone.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_emoji_mart/flutter_emoji_mart.dart'; // use a global value to store the selected emoji to prevent reloading every time. @@ -37,9 +38,7 @@ class _FlowyEmojiPickerState extends State { EmojiData.builtIn().then( (value) { kCachedEmojiData = value; - setState(() { - emojiData = value; - }); + setState(() => emojiData = value); }, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart b/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart index b1bc6c43a5..382bf8ab63 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart @@ -1,5 +1,7 @@ import 'dart:async'; +import 'package:flutter/material.dart'; + import 'package:appflowy/plugins/database/application/field/field_controller.dart'; import 'package:appflowy/plugins/database/application/view/view_cache.dart'; import 'package:appflowy/plugins/database/domain/database_view_service.dart'; @@ -12,7 +14,6 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_result/appflowy_result.dart'; import 'package:collection/collection.dart'; -import 'package:flutter/material.dart'; import 'defines.dart'; import 'row/row_cache.dart'; @@ -223,6 +224,7 @@ class DatabaseController { _databaseCallbacks.clear(); _groupCallbacks.clear(); _layoutCallbacks.clear(); + _isLoading.dispose(); } Future _loadGroups() async { diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart index ff695eea0e..82c43845b6 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart'; @@ -19,12 +21,12 @@ import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:go_router/go_router.dart'; import '../../application/row/row_controller.dart'; import '../../widgets/row/row_detail.dart'; + import 'calendar_day.dart'; import 'layout/sizes.dart'; import 'toolbar/calendar_setting_bar.dart'; @@ -90,12 +92,11 @@ class _CalendarPageState extends State { @override void initState() { + super.initState(); _calendarState = GlobalKey(); _calendarBloc = CalendarBloc( databaseController: widget.databaseController, )..add(const CalendarEvent.initial()); - - super.initState(); } @override @@ -378,13 +379,7 @@ class UnscheduledEventsButton extends StatefulWidget { } class _UnscheduledEventsButtonState extends State { - late final PopoverController _popoverController; - - @override - void initState() { - super.initState(); - _popoverController = PopoverController(); - } + final PopoverController _popoverController = PopoverController(); @override Widget build(BuildContext context) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/toolbar/calendar_layout_setting.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/toolbar/calendar_layout_setting.dart index e081a2fbb3..6cbf39e9e3 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/toolbar/calendar_layout_setting.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/toolbar/calendar_layout_setting.dart @@ -30,6 +30,12 @@ class CalendarLayoutSetting extends StatefulWidget { class _CalendarLayoutSettingState extends State { final PopoverMutex popoverMutex = PopoverMutex(); + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocProvider( diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checkbox.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checkbox.dart index 7341f6046d..85370cc7a1 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checkbox.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checkbox.dart @@ -1,18 +1,19 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/grid/application/filter/checkbox_filter_editor_bloc.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbenum.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; - import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbenum.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../condition_button.dart'; import '../disclosure_button.dart'; import '../filter_info.dart'; + import 'choicechip.dart'; class CheckboxFilterChoicechip extends StatefulWidget { @@ -30,9 +31,9 @@ class _CheckboxFilterChoicechipState extends State { @override void initState() { + super.initState(); bloc = CheckboxFilterEditorBloc(filterInfo: widget.filterInfo) ..add(const CheckboxFilterEditorEvent.initial()); - super.initState(); } @override @@ -82,6 +83,12 @@ class CheckboxFilterEditor extends StatefulWidget { class _CheckboxFilterEditorState extends State { final popoverMutex = PopoverMutex(); + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocProvider.value( diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checklist/checklist.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checklist/checklist.dart index c16df32306..e10e35dd7b 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checklist/checklist.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/checklist/checklist.dart @@ -1,12 +1,14 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/grid/application/filter/checklist_filter_bloc.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pbenum.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pbenum.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; + import '../../condition_button.dart'; import '../../disclosure_button.dart'; import '../../filter_info.dart'; @@ -23,20 +25,20 @@ class ChecklistFilterChoicechip extends StatefulWidget { } class _ChecklistFilterChoicechipState extends State { - late ChecklistFilterEditorBloc bloc; - late PopoverMutex popoverMutex; + late final ChecklistFilterEditorBloc bloc; + final PopoverMutex popoverMutex = PopoverMutex(); @override void initState() { - popoverMutex = PopoverMutex(); + super.initState(); bloc = ChecklistFilterEditorBloc(filterInfo: widget.filterInfo); bloc.add(const ChecklistFilterEditorEvent.initial()); - super.initState(); } @override void dispose() { bloc.close(); + popoverMutex.dispose(); super.dispose(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/number.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/number.dart index 0947239273..bbd9240bc4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/number.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/number.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/grid/application/filter/number_filter_editor_bloc.dart'; @@ -6,12 +8,12 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../condition_button.dart'; import '../disclosure_button.dart'; import '../filter_info.dart'; + import 'choicechip.dart'; class NumberFilterChoiceChip extends StatefulWidget { @@ -64,6 +66,12 @@ class NumberFilterEditor extends StatefulWidget { class _NumberFilterEditorState extends State { final popoverMutex = PopoverMutex(); + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocBuilder( diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart index 24d1955a3f..734aaf143e 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/select_option/select_option.dart @@ -1,14 +1,16 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/plugins/database/grid/application/filter/select_option_filter_bloc.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.pb.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../disclosure_button.dart'; import '../../filter_info.dart'; import '../choicechip.dart'; + import 'condition_list.dart'; import 'option_list.dart'; import 'select_option_loader.dart'; @@ -29,6 +31,7 @@ class _SelectOptionFilterChoicechipState @override void initState() { + super.initState(); if (widget.filterInfo.fieldInfo.fieldType == FieldType.SingleSelect) { bloc = SelectOptionFilterEditorBloc( filterInfo: widget.filterInfo, @@ -43,7 +46,6 @@ class _SelectOptionFilterChoicechipState ); } bloc.add(const SelectOptionFilterEditorEvent.initial()); - super.initState(); } @override @@ -90,6 +92,12 @@ class SelectOptionFilterEditor extends StatefulWidget { class _SelectOptionFilterEditorState extends State { final popoverMutex = PopoverMutex(); + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocProvider.value( diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart index 66f17e0971..0ee63f25da 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/text.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/grid/application/filter/text_filter_editor_bloc.dart'; @@ -6,12 +8,12 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../condition_button.dart'; import '../disclosure_button.dart'; import '../filter_info.dart'; + import 'choicechip.dart'; class TextFilterChoicechip extends StatelessWidget { @@ -72,6 +74,12 @@ class TextFilterEditor extends StatefulWidget { class _TextFilterEditorState extends State { final popoverMutex = PopoverMutex(); + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocBuilder( diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/time.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/time.dart index 828f124de1..22e999d010 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/time.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/choicechip/time.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/grid/application/filter/time_filter_editor_bloc.dart'; @@ -6,12 +8,12 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../condition_button.dart'; import '../disclosure_button.dart'; import '../filter_info.dart'; + import 'choicechip.dart'; class TimeFilterChoiceChip extends StatefulWidget { @@ -64,6 +66,12 @@ class TimeFilterEditor extends StatefulWidget { class _TimeFilterEditorState extends State { final popoverMutex = PopoverMutex(); + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocBuilder( diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/create_filter_list.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/create_filter_list.dart index b91fb44389..6c5437ef51 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/create_filter_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/create_filter_list.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/application/field/field_info.dart'; @@ -10,7 +12,6 @@ import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/style_widget/text_field.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../../../application/field/field_controller.dart'; @@ -35,15 +36,15 @@ class GridCreateFilterList extends StatefulWidget { } class _GridCreateFilterListState extends State { - late GridCreateFilterBloc editBloc; + late final GridCreateFilterBloc editBloc; @override void initState() { + super.initState(); editBloc = GridCreateFilterBloc( viewId: widget.viewId, fieldController: widget.fieldController, )..add(const GridCreateFilterEvent.initial()); - super.initState(); } @override diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart index 80deb98695..52c361ab38 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/filter/filter_menu.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/application/field/field_controller.dart'; @@ -5,9 +7,7 @@ import 'package:appflowy/plugins/database/grid/application/filter/filter_menu_bl import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; - import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'create_filter_list.dart'; @@ -77,13 +77,7 @@ class AddFilterButton extends StatefulWidget { } class _AddFilterButtonState extends State { - late PopoverController popoverController; - - @override - void initState() { - popoverController = PopoverController(); - super.initState(); - } + final PopoverController popoverController = PopoverController(); @override Widget build(BuildContext context) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart index fd09b6a591..56c48261f3 100755 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/desktop_field_cell.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/database/application/field/field_cell_bloc.dart'; import 'package:appflowy/plugins/database/application/field/field_controller.dart'; @@ -9,7 +11,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../layout/sizes.dart'; @@ -41,13 +42,12 @@ class GridFieldCell extends StatefulWidget { } class _GridFieldCellState extends State { + final PopoverController popoverController = PopoverController(); late final FieldCellBloc _bloc; - late PopoverController popoverController; @override void initState() { super.initState(); - popoverController = PopoverController(); _bloc = FieldCellBloc(viewId: widget.viewId, fieldInfo: widget.fieldInfo); if (widget.isEditing) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/sort/sort_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/sort/sort_editor.dart index 671a5c2084..bbcbc0a7f0 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/sort/sort_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/sort/sort_editor.dart @@ -1,5 +1,7 @@ import 'dart:io'; +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/grid/application/sort/sort_editor_bloc.dart'; @@ -7,10 +9,8 @@ import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pbenum.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; - import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'create_sort_list.dart'; @@ -28,6 +28,12 @@ class SortEditor extends StatefulWidget { class _SortEditorState extends State { final popoverMutex = PopoverMutex(); + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocBuilder( diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart index d3a41c6c3f..a2653a5389 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_cell_editor.dart @@ -1,6 +1,10 @@ import 'dart:collection'; import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/application/cell/bloc/select_option_cell_editor_bloc.dart'; @@ -10,14 +14,12 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import '../../grid/presentation/layout/sizes.dart'; import '../../grid/presentation/widgets/common/type_option_separator.dart'; import '../field/type_option_editor/select/select_option_editor.dart'; + import 'extension.dart'; import 'select_option_text_field.dart'; @@ -314,13 +316,7 @@ class _SelectOptionCell extends StatefulWidget { } class _SelectOptionCellState extends State<_SelectOptionCell> { - late PopoverController _popoverController; - - @override - void initState() { - _popoverController = PopoverController(); - super.initState(); - } + final _popoverController = PopoverController(); @override Widget build(BuildContext context) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_editor.dart index c3d950afae..ad1214fdba 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/field/field_editor.dart @@ -370,13 +370,7 @@ class FieldDetailsEditor extends StatefulWidget { } class _FieldDetailsEditorState extends State { - late PopoverMutex popoverMutex; - - @override - void initState() { - popoverMutex = PopoverMutex(); - super.initState(); - } + final PopoverMutex popoverMutex = PopoverMutex(); @override void dispose() { @@ -575,10 +569,7 @@ class _FieldNameTextFieldState extends State { } class SwitchFieldButton extends StatefulWidget { - const SwitchFieldButton({ - super.key, - required this.popoverMutex, - }); + const SwitchFieldButton({super.key, required this.popoverMutex}); final PopoverMutex popoverMutex; diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart index 8762918141..4a6aa78adb 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/row/row_property.dart @@ -1,5 +1,8 @@ import 'dart:io'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'; @@ -18,13 +21,12 @@ import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'accessory/cell_accessory.dart'; import '../cell/editable_cell_builder.dart'; +import 'accessory/cell_accessory.dart'; + /// Display the row properties in a list. Only used in [RowDetailPage]. class RowPropertyList extends StatelessWidget { const RowPropertyList({ @@ -363,15 +365,9 @@ class CreateRowFieldButton extends StatefulWidget { } class _CreateRowFieldButtonState extends State { - late PopoverController popoverController; + final PopoverController popoverController = PopoverController(); FieldPB? createdField; - @override - void initState() { - popoverController = PopoverController(); - super.initState(); - } - @override Widget build(BuildContext context) { return AppFlowyPopover( diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/database_settings_list.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/database_settings_list.dart index 7422db15ca..fdd6a65cb4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/database_settings_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/database_settings_list.dart @@ -1,3 +1,5 @@ +import 'package:flutter/widgets.dart'; + import 'package:appflowy/plugins/database/application/database_controller.dart'; import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart'; import 'package:appflowy/plugins/database/widgets/setting/database_setting_action.dart'; @@ -6,7 +8,6 @@ import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/style_widget/scrolling/styled_list.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter/widgets.dart'; class DatabaseSettingsList extends StatefulWidget { const DatabaseSettingsList({ @@ -21,7 +22,13 @@ class DatabaseSettingsList extends StatefulWidget { } class _DatabaseSettingsListState extends State { - late final PopoverMutex popoverMutex = PopoverMutex(); + final PopoverMutex popoverMutex = PopoverMutex(); + + @override + void dispose() { + popoverMutex.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart index ece69f9848..a72a30f2ea 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/setting/setting_property_list.dart @@ -1,5 +1,7 @@ import 'dart:io'; +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/database/application/field/field_controller.dart'; import 'package:appflowy/plugins/database/application/field/field_info.dart'; @@ -13,7 +15,6 @@ import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:collection/collection.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class DatabasePropertyList extends StatefulWidget { @@ -43,6 +44,12 @@ class _DatabasePropertyListState extends State { )..add(const DatabasePropertyEvent.initial()); } + @override + void dispose() { + _popoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { return BlocProvider.value( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart index 31fe8f0a4e..75261263d3 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_date_block.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + 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'; @@ -25,7 +27,6 @@ import 'package:collection/collection.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:fixnum/fixnum.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nanoid/non_secure.dart'; @@ -64,6 +65,12 @@ class _MentionDateBlockState extends State { late bool _includeTime = widget.includeTime; late DateTime? parsedDate = DateTime.tryParse(widget.date); + @override + void dispose() { + mutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { if (parsedDate == null) { diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/settings_ai_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/settings_ai_bloc.dart index 212c3c3139..7adfc43a81 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/ai/settings_ai_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/ai/settings_ai_bloc.dart @@ -67,8 +67,9 @@ class SettingsAIBloc extends Bloc { bool? disableSearchIndexing, AIModelPB? model, }) { - final payload = - UpdateUserWorkspaceSettingPB(workspaceId: userProfile.workspaceId); + final payload = UpdateUserWorkspaceSettingPB( + workspaceId: userProfile.workspaceId, + ); if (disableSearchIndexing != null) { payload.disableSearchIndexing = disableSearchIndexing; } @@ -82,17 +83,16 @@ class SettingsAIBloc extends Bloc { FlowyResult userProfileOrFailed, ) => userProfileOrFailed.fold( - (newUserProfile) => - add(SettingsAIEvent.didReceiveUserProfile(newUserProfile)), + (profile) => add(SettingsAIEvent.didReceiveUserProfile(profile)), (err) => Log.error(err), ); void _loadUserWorkspaceSetting() { final payload = UserWorkspaceIdPB(workspaceId: userProfile.workspaceId); UserEventGetWorkspaceSetting(payload).send().then((result) { - result.fold((settins) { + result.fold((settings) { if (!isClosed) { - add(SettingsAIEvent.didLoadAISetting(settins)); + add(SettingsAIEvent.didLoadAISetting(settings)); } }, (err) { Log.error(err); diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/plan/settings_plan_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/plan/settings_plan_bloc.dart index fd5587e322..48cd6a739d 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/plan/settings_plan_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/plan/settings_plan_bloc.dart @@ -117,6 +117,10 @@ class SettingsPlanBloc extends Bloc { ); }, cancelSubscription: () async { + final newState = state + .mapOrNull(ready: (state) => state) + ?.copyWith(downgradeProcessing: true); + emit(newState ?? state); await _userService.cancelSubscription(workspaceId); add(const SettingsPlanEvent.started()); }, @@ -174,5 +178,6 @@ class SettingsPlanState with _$SettingsPlanState { required WorkspaceSubscriptionPB subscription, required BillingPortalPB? billingPortal, @Default(false) bool showSuccessDialog, + @Default(false) bool downgradeProcessing, }) = _Ready; } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/plan/workspace_usage_ext.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/plan/workspace_usage_ext.dart index bc309b60c5..3dcd87ca58 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/plan/workspace_usage_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/plan/workspace_usage_ext.dart @@ -1,8 +1,20 @@ import 'package:appflowy_backend/protobuf/flowy-user/workspace.pb.dart'; +import 'package:intl/intl.dart'; + +final _storageNumberFormat = NumberFormat() + ..maximumFractionDigits = 2 + ..minimumFractionDigits = 0; extension PresentableUsage on WorkspaceUsagePB { String get totalBlobInGb => (totalBlobBytesLimit.toInt() / 1024 / 1024 / 1024).round().toString(); + + /// We use [NumberFormat] to format the current blob in GB. + /// + /// Where the [totalBlobBytes] is the total blob bytes in bytes. + /// And [NumberFormat.maximumFractionDigits] is set to 2. + /// And [NumberFormat.minimumFractionDigits] is set to 0. + /// String get currentBlobInGb => - (totalBlobBytes.toInt() / 1024 / 1024 / 1024).round().toString(); + _storageNumberFormat.format(totalBlobBytes.toInt() / 1024 / 1024 / 1024); } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart index bab2c3b618..1fb9a00658 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/hotkeys.dart @@ -1,5 +1,7 @@ import 'dart:io'; +import 'package:flutter/material.dart'; + import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/tasks/app_window_size_manager.dart'; import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; @@ -9,7 +11,6 @@ import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/shared/sidebar_setting.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:flutter/material.dart'; import 'package:hotkey_manager/hotkey_manager.dart'; import 'package:provider/provider.dart'; import 'package:scaled_app/scaled_app.dart'; @@ -186,14 +187,12 @@ class _HomeHotKeysState extends State { @override void initState() { super.initState(); - _registerHotKeys(context); } @override void didChangeDependencies() { super.didChangeDependencies(); - _registerHotKeys(context); } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/tabs/tabs_manager.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/tabs/tabs_manager.dart index 064d64477f..07870a152d 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/tabs/tabs_manager.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/tabs/tabs_manager.dart @@ -1,7 +1,8 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart'; import 'package:appflowy/workspace/presentation/home/home_sizes.dart'; import 'package:appflowy/workspace/presentation/home/tabs/flowy_tab.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class TabsManager extends StatefulWidget { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/notification_dialog.dart b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/notification_dialog.dart index 1394758fe1..022e6b3876 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/notification_dialog.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/notification_dialog.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/notification_filter/notification_filter_bloc.dart'; import 'package:appflowy/user/application/reminder/reminder_bloc.dart'; @@ -9,7 +11,6 @@ import 'package:appflowy/workspace/presentation/notifications/widgets/notificati import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart'; import 'package:appflowy_popover/appflowy_popover.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class NotificationDialog extends StatefulWidget { @@ -44,7 +45,7 @@ class _NotificationDialogState extends State @override void dispose() { - _mutex.close(); + _mutex.dispose(); _controller.removeListener(_updateState); _controller.dispose(); super.dispose(); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_button.dart b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_button.dart index e28ebfb1c2..eae3c29d76 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_button.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_button.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/startup.dart'; @@ -10,18 +12,27 @@ import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; -import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -class NotificationButton extends StatelessWidget { - const NotificationButton({ - super.key, - }); +class NotificationButton extends StatefulWidget { + const NotificationButton({super.key}); + + @override + State createState() => _NotificationButtonState(); +} + +class _NotificationButtonState extends State { + final mutex = PopoverMutex(); + + @override + void dispose() { + mutex.dispose(); + super.dispose(); + } @override Widget build(BuildContext context) { final views = context.watch().state.section.views; - final mutex = PopoverMutex(); return BlocProvider.value( value: getIt(), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_item.dart index 0f69d0e679..5abc214583 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_item.dart @@ -1,3 +1,5 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_configuration.dart'; @@ -12,7 +14,6 @@ import 'package:fixnum/fixnum.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; import 'package:provider/provider.dart'; class NotificationItem extends StatefulWidget { @@ -71,6 +72,12 @@ class _NotificationItemState extends State { infoString = _buildInfoString(); } + @override + void dispose() { + mutex.dispose(); + super.dispose(); + } + String _buildInfoString() { String scheduledString = _scheduledString(widget.scheduled, widget.includeTime); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_ai_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_ai_view.dart index 96fe256bd0..d5f4a62558 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_ai_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_ai_view.dart @@ -1,13 +1,13 @@ -import 'package:appflowy/workspace/presentation/settings/shared/af_dropdown_menu_entry.dart'; -import 'package:appflowy/workspace/presentation/settings/shared/settings_dropdown.dart'; -import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:flutter/material.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/workspace/application/settings/ai/settings_ai_bloc.dart'; +import 'package:appflowy/workspace/presentation/settings/shared/af_dropdown_menu_entry.dart'; import 'package:appflowy/workspace/presentation/settings/shared/settings_body.dart'; +import 'package:appflowy/workspace/presentation/settings/shared/settings_dropdown.dart'; import 'package:appflowy/workspace/presentation/widgets/toggle/toggle.dart'; +import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; @@ -153,11 +153,9 @@ class _AISearchToggle extends StatelessWidget { } else { return Toggle( value: state.enableSearchIndexing, - onChanged: (_) { - context.read().add( - const SettingsAIEvent.toggleAISearch(), - ); - }, + onChanged: (_) => context + .read() + .add(const SettingsAIEvent.toggleAISearch()), ); } }, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart index a094c0db39..96f3cde646 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_comparison_dialog.dart @@ -47,7 +47,7 @@ class _SettingsPlanComparisonDialogState Widget build(BuildContext context) { final isLM = Theme.of(context).isLightMode; - return BlocListener( + return BlocConsumer( listener: (context, state) { final readyState = state.mapOrNull(ready: (state) => state); @@ -82,7 +82,7 @@ class _SettingsPlanComparisonDialogState currentSubscription = readyState.subscription; }); }, - child: FlowyDialog( + builder: (context, state) => FlowyDialog( constraints: const BoxConstraints(maxWidth: 784, minWidth: 674), child: Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -185,7 +185,16 @@ class _SettingsPlanComparisonDialogState canDowngrade: currentSubscription.subscriptionPlan != SubscriptionPlanPB.None, - currentCanceled: currentSubscription.hasCanceled, + currentCanceled: currentSubscription.hasCanceled || + (context + .watch() + .state + .mapOrNull( + loading: (_) => true, + ready: (state) => + state.downgradeProcessing, + ) ?? + false), onSelected: () async { if (currentSubscription.subscriptionPlan == SubscriptionPlanPB.None || @@ -484,8 +493,9 @@ class _ActionButton extends StatelessWidget { cursor: onPressed != null ? SystemMouseCursors.click : MouseCursor.defer, - child: _drawGradientBorder( + child: _drawBorder( isLM: isLM, + isUpgrade: isUpgrade, child: Container( height: 36, width: 148, @@ -496,9 +506,7 @@ class _ActionButton extends StatelessWidget { border: Border.all(color: Colors.transparent), borderRadius: BorderRadius.circular(14), ), - child: Center( - child: _drawText(label, isLM), - ), + child: Center(child: _drawText(label, isLM, isUpgrade)), ), ), ), @@ -509,13 +517,13 @@ class _ActionButton extends StatelessWidget { ); } - Widget _drawText(String text, bool isLM) { + Widget _drawText(String text, bool isLM, bool isUpgrade) { final child = FlowyText( text, fontSize: 14, lineHeight: 1.2, fontWeight: useGradientBorder ? FontWeight.w600 : FontWeight.w500, - color: const Color(0xFFC49BEC), + color: isUpgrade ? const Color(0xFFC49BEC) : null, ); if (!useGradientBorder || !isLM) { @@ -536,18 +544,25 @@ class _ActionButton extends StatelessWidget { ); } - Widget _drawGradientBorder({required bool isLM, required Widget child}) { + Widget _drawBorder({ + required bool isLM, + required bool isUpgrade, + required Widget child, + }) { return Container( padding: const EdgeInsets.all(2), decoration: BoxDecoration( - gradient: LinearGradient( - transform: const GradientRotation(-1.2), - stops: const [0.4, 1], - colors: [ - isLM ? const Color(0xFF251D37) : const Color(0xFF7459AD), - isLM ? const Color(0xFF7547C0) : const Color(0xFFDDC8FF), - ], - ), + gradient: isUpgrade + ? LinearGradient( + transform: const GradientRotation(-1.2), + stops: const [0.4, 1], + colors: [ + isLM ? const Color(0xFF251D37) : const Color(0xFF7459AD), + isLM ? const Color(0xFF7547C0) : const Color(0xFFDDC8FF), + ], + ) + : null, + border: isUpgrade ? null : Border.all(), borderRadius: BorderRadius.circular(16), ), child: child, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart index 5373196a2c..3c67d6c4f3 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/pages/settings_plan_view.dart @@ -80,11 +80,30 @@ class SettingsPlanView extends StatelessWidget { } } -class _CurrentPlanBox extends StatelessWidget { +class _CurrentPlanBox extends StatefulWidget { const _CurrentPlanBox({required this.subscription}); final WorkspaceSubscriptionPB subscription; + @override + State<_CurrentPlanBox> createState() => _CurrentPlanBoxState(); +} + +class _CurrentPlanBoxState extends State<_CurrentPlanBox> { + late SettingsPlanBloc planBloc; + + @override + void initState() { + super.initState(); + planBloc = context.read(); + } + + @override + void didChangeDependencies() { + planBloc = context.read(); + super.didChangeDependencies(); + } + @override Widget build(BuildContext context) { return Stack( @@ -105,13 +124,13 @@ class _CurrentPlanBox extends StatelessWidget { children: [ const VSpace(4), FlowyText.semibold( - subscription.label, + widget.subscription.label, fontSize: 24, color: AFThemeExtension.of(context).strongText, ), const VSpace(8), FlowyText.regular( - subscription.info, + widget.subscription.info, fontSize: 16, color: AFThemeExtension.of(context).strongText, maxLines: 3, @@ -124,10 +143,10 @@ class _CurrentPlanBox extends StatelessWidget { onPressed: () => _openPricingDialog( context, context.read().workspaceId, - subscription, + widget.subscription, ), ), - if (subscription.hasCanceled) ...[ + if (widget.subscription.hasCanceled) ...[ const VSpace(12), FlowyText( LocaleKeys @@ -149,10 +168,10 @@ class _CurrentPlanBox extends StatelessWidget { separatorBuilder: () => const VSpace(4), crossAxisAlignment: CrossAxisAlignment.start, children: [ - ..._getPros(subscription.subscriptionPlan).map( + ..._getPros(widget.subscription.subscriptionPlan).map( (s) => _ProConItem(label: s), ), - ..._getCons(subscription.subscriptionPlan).map( + ..._getCons(widget.subscription.subscriptionPlan).map( (s) => _ProConItem(label: s, isPro: false), ), ], @@ -185,7 +204,7 @@ class _CurrentPlanBox extends StatelessWidget { String _canceledDate(BuildContext context) { final appearance = context.read().state; return appearance.dateFormat.formatDate( - subscription.canceledAt.toDateTime(), + widget.subscription.canceledAt.toDateTime(), true, appearance.timeFormat, ); @@ -199,7 +218,7 @@ class _CurrentPlanBox extends StatelessWidget { showDialog( context: context, builder: (_) => BlocProvider.value( - value: context.read(), + value: planBloc, child: SettingsPlanComparisonDialog( workspaceId: workspaceId, subscription: subscription, @@ -224,6 +243,7 @@ class _CurrentPlanBox extends StatelessWidget { LocaleKeys.settings_planPage_planUsage_currentPlan_freeProFour.tr(), LocaleKeys.settings_planPage_planUsage_currentPlan_freeProFive.tr(), ]; + List _freeCons() => [ LocaleKeys.settings_planPage_planUsage_currentPlan_freeConOne.tr(), LocaleKeys.settings_planPage_planUsage_currentPlan_freeConTwo.tr(), @@ -242,6 +262,7 @@ class _CurrentPlanBox extends StatelessWidget { LocaleKeys.settings_planPage_planUsage_currentPlan_professionalProFive .tr(), ]; + List _proCons() => [ LocaleKeys.settings_planPage_planUsage_currentPlan_professionalConOne .tr(), @@ -314,6 +335,11 @@ class _PlanUsageSummary extends StatelessWidget { Expanded( child: _UsageBox( title: LocaleKeys.settings_planPage_planUsage_storageLabel.tr(), + replacementText: subscription.subscriptionPlan == + SubscriptionPlanPB.Pro + ? LocaleKeys.settings_planPage_planUsage_storageUnlimited + .tr() + : null, label: LocaleKeys.settings_planPage_planUsage_storageUsage.tr( args: [ usage.currentBlobInGb, @@ -372,12 +398,16 @@ class _UsageBox extends StatelessWidget { required this.title, required this.label, required this.value, + this.replacementText, }); final String title; final String label; final double value; + /// Replaces the progress indicator if not null + final String? replacementText; + @override Widget build(BuildContext context) { return Column( @@ -388,7 +418,21 @@ class _UsageBox extends StatelessWidget { fontSize: 11, color: AFThemeExtension.of(context).secondaryTextColor, ), - _PlanProgressIndicator(label: label, progress: value), + if (replacementText != null) ...[ + Row( + children: [ + Flexible( + child: FlowyText.medium( + replacementText!, + fontSize: 11, + color: AFThemeExtension.of(context).secondaryTextColor, + ), + ), + ], + ), + ] else ...[ + _PlanProgressIndicator(label: label, progress: value), + ], ], ); } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart index f57c25b351..6cdccb3b3b 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/emoji_menu_item.dart @@ -1,11 +1,12 @@ +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/base/emoji/emoji_picker.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_svg_widget.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/decoration.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; SelectionMenuItem emojiMenuItem = SelectionMenuItem( getName: LocaleKeys.document_plugins_emoji.tr, @@ -85,8 +86,8 @@ class EmojiSelectionMenu extends StatefulWidget { class _EmojiSelectionMenuState extends State { @override void initState() { - HardwareKeyboard.instance.addHandler(_handleGlobalKeyEvent); super.initState(); + HardwareKeyboard.instance.addHandler(_handleGlobalKeyEvent); } bool _handleGlobalKeyEvent(KeyEvent event) { @@ -95,9 +96,8 @@ class _EmojiSelectionMenuState extends State { //triggers on esc widget.onExit(); return true; - } else { - return false; } + return false; } @override @@ -106,17 +106,10 @@ class _EmojiSelectionMenuState extends State { super.deactivate(); } - @override - void dispose() { - super.dispose(); - } - @override Widget build(BuildContext context) { return FlowyEmojiPicker( - onEmojiSelected: (_, emoji) { - widget.onSubmitted(emoji); - }, + onEmojiSelected: (_, emoji) => widget.onSubmitted(emoji), ); } } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/default_emoji_picker_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/default_emoji_picker_view.dart index f2bdbf4faa..53ef37cea9 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/default_emoji_picker_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/emoji_picker/src/default_emoji_picker_view.dart @@ -1,6 +1,8 @@ +import 'package:flutter/material.dart'; + import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; -import 'package:flutter/material.dart'; + import 'emoji_picker.dart'; import 'emoji_picker_builder.dart'; import 'models/emoji_category_models.dart'; @@ -29,8 +31,10 @@ class DefaultEmojiPickerViewState extends State @override void initState() { - var initCategory = widget.state.emojiCategoryGroupList.indexWhere( - (element) => element.category == widget.config.initCategory, + super.initState(); + + int initCategory = widget.state.emojiCategoryGroupList.indexWhere( + (el) => el.category == widget.config.initCategory, ); if (initCategory == -1) { initCategory = 0; @@ -42,27 +46,23 @@ class DefaultEmojiPickerViewState extends State ); _pageController = PageController(initialPage: initCategory); _emojiFocusNode.requestFocus(); - _emojiController.addListener(() { final String query = _emojiController.text.toLowerCase(); if (query.isEmpty) { searchEmojiList.emoji.clear(); - _pageController!.jumpToPage( - _tabController!.index, - ); + _pageController!.jumpToPage(_tabController!.index); } else { searchEmojiList.emoji.clear(); for (final element in widget.state.emojiCategoryGroupList) { searchEmojiList.emoji.addAll( - element.emoji.where((item) { - return item.name.toLowerCase().contains(query); - }).toList(), + element.emoji + .where((item) => item.name.toLowerCase().contains(query)) + .toList(), ); } } setState(() {}); }); - super.initState(); } @override @@ -81,25 +81,17 @@ class DefaultEmojiPickerViewState extends State type: MaterialType.transparency, child: IconButton( padding: const EdgeInsets.only(bottom: 2), - icon: Icon( - Icons.backspace, - color: widget.config.backspaceColor, - ), - onPressed: () { - widget.state.onBackspacePressed!(); - }, + icon: Icon(Icons.backspace, color: widget.config.backspaceColor), + onPressed: () => widget.state.onBackspacePressed!(), ), ); } + return const SizedBox.shrink(); } - bool isEmojiSearching() { - final bool result = - searchEmojiList.emoji.isNotEmpty || _emojiController.text.isNotEmpty; - - return result; - } + bool isEmojiSearching() => + searchEmojiList.emoji.isNotEmpty || _emojiController.text.isNotEmpty; @override Widget build(BuildContext context) { @@ -213,15 +205,9 @@ class DefaultEmojiPickerViewState extends State required Widget child, }) { if (widget.config.buttonMode == ButtonMode.MATERIAL) { - return InkWell( - onTap: onPressed, - child: child, - ); + return InkWell(onTap: onPressed, child: child); } - return GestureDetector( - onTap: onPressed, - child: child, - ); + return GestureDetector(onTap: onPressed, child: child); } Widget _buildPage(double emojiSize, EmojiCategoryGroup emojiCategoryGroup) { @@ -275,9 +261,7 @@ class DefaultEmojiPickerViewState extends State child: FittedBox( child: Text( emoji.emoji, - style: TextStyle( - fontSize: emojiSize, - ), + style: TextStyle(fontSize: emojiSize), ), ), ), diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart index 29fab1805f..e54de4d9c5 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart @@ -1,3 +1,7 @@ +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; + import 'package:appflowy/core/helpers/url_launcher.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/workspace/application/settings/supabase_cloud_setting_bloc.dart'; @@ -15,9 +19,6 @@ import 'package:flowy_infra/theme_extension.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/widget/error_page.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; class SettingSupabaseCloudView extends StatelessWidget { @@ -265,13 +266,7 @@ class SupabaseInput extends StatefulWidget { } class SupabaseInputState extends State { - late TextEditingController _controller; - - @override - void initState() { - super.initState(); - _controller = TextEditingController(text: widget.url); - } + late final _controller = TextEditingController(text: widget.url); @override void dispose() { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/widgets/date_time_settings.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/widgets/date_time_settings.dart index 0c9c6aaa8e..e1e6641953 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/widgets/date_time_settings.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/date_picker/widgets/date_time_settings.dart @@ -29,6 +29,12 @@ class _DateTimeSettingState extends State { final timeSettingPopoverMutex = PopoverMutex(); String? overlayIdentifier; + @override + void dispose() { + timeSettingPopoverMutex.dispose(); + super.dispose(); + } + @override Widget build(BuildContext context) { final List children = [ diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart index 66cad4ab38..7576530c17 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/dialogs.dart @@ -129,11 +129,6 @@ class NavigatorAlertDialog extends StatefulWidget { } class _CreateFlowyAlertDialog extends State { - @override - void initState() { - super.initState(); - } - @override Widget build(BuildContext context) { return StyledDialog( diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart index 6abc789223..379104b94a 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/pop_up_action.dart @@ -1,7 +1,8 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/hover.dart'; -import 'package:flutter/material.dart'; import 'package:styled_widget/styled_widget.dart'; class PopoverActionList extends StatefulWidget { @@ -42,12 +43,12 @@ class PopoverActionList extends StatefulWidget { class _PopoverActionListState extends State> { - late PopoverController popoverController; + final PopoverController popoverController = PopoverController(); @override - void initState() { - popoverController = PopoverController(); - super.initState(); + void dispose() { + popoverController.close(); + super.dispose(); } @override diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/tab_bar_item.dart b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/tab_bar_item.dart index 1023553efb..cef51258ff 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/widgets/tab_bar_item.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/widgets/tab_bar_item.dart @@ -1,7 +1,8 @@ +import 'package:flutter/material.dart'; + import 'package:appflowy/workspace/application/view/view_listener.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:flutter/material.dart'; class ViewTabBarItem extends StatefulWidget { const ViewTabBarItem({super.key, required this.view}); @@ -37,7 +38,5 @@ class _ViewTabBarItemState extends State { } @override - Widget build(BuildContext context) { - return FlowyText.medium(view.name); - } + Widget build(BuildContext context) => FlowyText.medium(view.name); } diff --git a/frontend/appflowy_flutter/packages/appflowy_backend/example/lib/main.dart b/frontend/appflowy_flutter/packages/appflowy_backend/example/lib/main.dart index 39759cfbff..a3fb8967a5 100644 --- a/frontend/appflowy_flutter/packages/appflowy_backend/example/lib/main.dart +++ b/frontend/appflowy_flutter/packages/appflowy_backend/example/lib/main.dart @@ -1,7 +1,8 @@ -import 'package:flutter/material.dart'; import 'dart:async'; +import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; + import 'package:appflowy_backend/appflowy_backend.dart'; void main() { @@ -36,21 +37,15 @@ class _MyAppState extends State { // message was in flight, we want to discard the reply rather than calling // setState to update our non-existent appearance. if (!mounted) return; - setState(() { - _platformVersion = platformVersion; - }); + setState(() => _platformVersion = platformVersion); } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( - appBar: AppBar( - title: const Text('Plugin example app'), - ), - body: Center( - child: Text('Running on: $_platformVersion\n'), - ), + appBar: AppBar(title: const Text('Plugin example app')), + body: Center(child: Text('Running on: $_platformVersion\n')), ), ); } diff --git a/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/popover.dart b/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/popover.dart index 405db2bee8..1c8bee41be 100644 --- a/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/popover.dart +++ b/frontend/appflowy_flutter/packages/appflowy_popover/lib/src/popover.dart @@ -1,7 +1,8 @@ -import 'package:appflowy_popover/src/layout.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:appflowy_popover/src/layout.dart'; + import 'mask.dart'; import 'mutex.dart'; @@ -177,9 +178,7 @@ class PopoverState extends State { _rootEntry.addEntry(context, this, newEntry, widget.asBarrier); } - void close({ - bool notify = true, - }) { + void close({bool notify = true}) { if (_rootEntry.contains(this)) { _rootEntry.removeEntry(this); if (notify) { @@ -286,9 +285,7 @@ class PopoverContainer extends StatefulWidget { if (context is StatefulElement && context.state is PopoverContainerState) { return context.state as PopoverContainerState; } - final PopoverContainerState? result = - context.findAncestorStateOfType(); - return result!; + return context.findAncestorStateOfType()!; } static PopoverContainerState? maybeOf(BuildContext context) { diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 97d368eab6..ef03bbc3bd 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -2,10 +2,11 @@ import 'dart:ui'; -import 'package:flowy_infra_ui/src/flowy_overlay/layout.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flowy_infra_ui/src/flowy_overlay/layout.dart'; + /// Specifies how overlay are anchored to the SourceWidget enum AnchorDirection { // Corner aligned with a corner of the SourceWidget @@ -341,18 +342,17 @@ class FlowyOverlayState extends State { @override void initState() { - _keyboardShortcutBindings.addAll({ - LogicalKeySet(LogicalKeyboardKey.escape): (identifier) { - remove(identifier); - }, - }); super.initState(); + _keyboardShortcutBindings.addAll({ + LogicalKeySet(LogicalKeyboardKey.escape): (identifier) => + remove(identifier), + }); } @override Widget build(BuildContext context) { final overlays = _overlayList.map((item) { - var widget = item.widget; + Widget widget = item.widget; // requestFocus will cause the children weird focus behaviors. // item.focusNode.requestFocus(); @@ -390,15 +390,11 @@ class FlowyOverlayState extends State { return MaterialApp( theme: Theme.of(context), debugShowCheckedModeBanner: false, - home: Stack( - children: children..addAll(overlays), - ), + home: Stack(children: children..addAll(overlays)), ); } - void _handleTapOnBackground() { - removeAll(); - } + void _handleTapOnBackground() => removeAll(); Widget? _renderBackground(List overlays) { Widget? child; diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_list.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_list.dart index a3f262c070..92381cff44 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_list.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/scrolling/styled_list.dart @@ -36,13 +36,7 @@ class StyledListView extends StatefulWidget { /// State is public so this can easily be controlled externally class StyledListViewState extends State { - late ScrollController scrollController; - - @override - void initState() { - scrollController = ScrollController(); - super.initState(); - } + final scrollController = ScrollController(); @override void dispose() { @@ -50,15 +44,6 @@ class StyledListViewState extends State { super.dispose(); } - @override - void didUpdateWidget(StyledListView oldWidget) { - if (oldWidget.itemCount != widget.itemCount || - oldWidget.itemExtent != widget.itemExtent) { - setState(() {}); - } - super.didUpdateWidget(oldWidget); - } - @override Widget build(BuildContext context) { final contentSize = (widget.itemCount ?? 0.0) * (widget.itemExtent ?? 00.0); @@ -75,7 +60,7 @@ class StyledListViewState extends State { controller: scrollController, itemExtent: widget.itemExtent, itemCount: widget.itemCount, - itemBuilder: (c, i) => widget.itemBuilder(c, i), + itemBuilder: widget.itemBuilder, ), ); return listContent; diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart index d26f353c72..1b46682628 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_field.dart @@ -137,7 +137,6 @@ class FlowyTextFieldState extends State { void _onSubmitted(String text) { widget.onSubmitted?.call(text); if (widget.autoClearWhenDone) { - // using `controller.clear()` instead of `controller.text = ''` which will crash on Windows. controller.clear(); } } @@ -154,7 +153,7 @@ class FlowyTextFieldState extends State { _onChanged(text); } }, - onSubmitted: (text) => _onSubmitted(text), + onSubmitted: _onSubmitted, onEditingComplete: widget.onEditingComplete, minLines: 1, maxLines: widget.maxLines, diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_input.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_input.dart index 8e3bcc9bf5..7e9b7b12ad 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_input.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/style_widget/text_input.dart @@ -1,10 +1,11 @@ import 'dart:async'; import 'dart:math' as math; -import 'package:flowy_infra/size.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flowy_infra/size.dart'; + class FlowyFormTextInput extends StatelessWidget { static EdgeInsets kDefaultTextInputPadding = EdgeInsets.only(bottom: Insets.sm, top: 4); @@ -162,10 +163,12 @@ class StyledSearchTextInputState extends State { @override void initState() { + super.initState(); _controller = widget.controller ?? TextEditingController(text: widget.initialValue); _focusNode = FocusNode( - debugLabel: widget.label ?? '', + debugLabel: widget.label, + canRequestFocus: true, onKeyEvent: (node, event) { if (event.logicalKey == LogicalKeyboardKey.escape) { widget.onEditingCancel?.call(); @@ -173,7 +176,6 @@ class StyledSearchTextInputState extends State { } return KeyEventResult.ignored; }, - canRequestFocus: true, ); // Listen for focus out events _focusNode @@ -182,7 +184,6 @@ class StyledSearchTextInputState extends State { if (widget.autoFocus ?? false) { scheduleMicrotask(() => _focusNode.requestFocus()); } - super.initState(); } @override @@ -292,8 +293,10 @@ class ThinUnderlineBorder extends InputBorder { bool get isOutline => false; @override - UnderlineInputBorder copyWith( - {BorderSide? borderSide, BorderRadius? borderRadius}) { + UnderlineInputBorder copyWith({ + BorderSide? borderSide, + BorderRadius? borderRadius, + }) { return UnderlineInputBorder( borderSide: borderSide ?? this.borderSide, borderRadius: borderRadius ?? this.borderRadius, @@ -301,14 +304,12 @@ class ThinUnderlineBorder extends InputBorder { } @override - EdgeInsetsGeometry get dimensions { - return EdgeInsets.only(bottom: borderSide.width); - } + EdgeInsetsGeometry get dimensions => + EdgeInsets.only(bottom: borderSide.width); @override - UnderlineInputBorder scale(double t) { - return UnderlineInputBorder(borderSide: borderSide.scale(t)); - } + UnderlineInputBorder scale(double t) => + UnderlineInputBorder(borderSide: borderSide.scale(t)); @override Path getInnerPath(Rect rect, {TextDirection? textDirection}) { diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart index 40978aa461..de5e3061fd 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/widget/rounded_input_field.dart @@ -1,9 +1,10 @@ -import 'package:flowy_infra/size.dart'; -import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flutter/material.dart'; -import 'package:flowy_infra/time/duration.dart'; import 'package:flutter/services.dart'; +import 'package:flowy_infra/size.dart'; +import 'package:flowy_infra/time/duration.dart'; +import 'package:flowy_infra_ui/widget/rounded_button.dart'; + class RoundedInputField extends StatefulWidget { final String? hintText; final bool obscureText; @@ -60,33 +61,26 @@ class RoundedInputField extends StatefulWidget { class _RoundedInputFieldState extends State { String inputText = ""; - bool obscuteText = false; + bool obscureText = false; @override void initState() { - obscuteText = widget.obscureText; - if (widget.controller != null) { - inputText = widget.controller!.text; - } else { - inputText = widget.initialValue ?? ""; - } - super.initState(); + obscureText = widget.obscureText; + inputText = widget.controller != null + ? widget.controller!.text + : widget.initialValue ?? ""; } - String? _suffixText() { - if (widget.maxLength != null) { - return ' ${widget.controller!.text.length}/${widget.maxLength}'; - } else { - return null; - } - } + String? _suffixText() => widget.maxLength != null + ? ' ${widget.controller!.text.length}/${widget.maxLength}' + : null; @override Widget build(BuildContext context) { - var borderColor = + Color borderColor = widget.normalBorderColor ?? Theme.of(context).colorScheme.outline; - var focusBorderColor = + Color focusBorderColor = widget.focusBorderColor ?? Theme.of(context).colorScheme.primary; if (widget.errorText.isNotEmpty) { @@ -122,7 +116,7 @@ class _RoundedInputFieldState extends State { }, cursorColor: widget.cursorColor ?? Theme.of(context).colorScheme.primary, - obscureText: obscuteText, + obscureText: obscureText, style: widget.style ?? Theme.of(context).textTheme.bodyMedium, decoration: InputDecoration( contentPadding: widget.contentPadding, @@ -134,17 +128,11 @@ class _RoundedInputFieldState extends State { suffixText: _suffixText(), counterText: "", enabledBorder: OutlineInputBorder( - borderSide: BorderSide( - color: borderColor, - width: 1.0, - ), + borderSide: BorderSide(color: borderColor, width: 1.0), borderRadius: Corners.s10Border, ), focusedBorder: OutlineInputBorder( - borderSide: BorderSide( - color: focusBorderColor, - width: 1.0, - ), + borderSide: BorderSide(color: focusBorderColor, width: 1.0), borderRadius: Corners.s10Border, ), suffixIcon: obscureIcon(), @@ -186,19 +174,11 @@ class _RoundedInputFieldState extends State { } assert(widget.obscureIcon != null && widget.obscureHideIcon != null); - Widget? icon; - if (obscuteText) { - icon = widget.obscureIcon!; - } else { - icon = widget.obscureHideIcon!; - } + final icon = obscureText ? widget.obscureIcon! : widget.obscureHideIcon!; return RoundedImageButton( size: iconWidth, - press: () { - obscuteText = !obscuteText; - setState(() {}); - }, + press: () => setState(() => obscureText = !obscureText), child: icon, ); } diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index e066d6e0dd..defd58dadf 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -53,11 +53,11 @@ packages: dependency: "direct main" description: path: "." - ref: "64c0be8" - resolved-ref: "64c0be88a113c2eece5512701527e7d11b8c9239" + ref: e8ee051 + resolved-ref: e8ee051719eded6621ccdc2722f696411c020209 url: "https://github.com/AppFlowy-IO/appflowy-editor.git" source: git - version: "2.5.1" + version: "3.0.0" appflowy_editor_plugins: dependency: "direct main" description: diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index dffab82055..2511666563 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -185,7 +185,7 @@ dependency_overrides: appflowy_editor: git: url: https://github.com/AppFlowy-IO/appflowy-editor.git - ref: "64c0be8" + ref: "e8ee051" appflowy_editor_plugins: git: diff --git a/frontend/resources/translations/en.json b/frontend/resources/translations/en.json index fd6c1aa38a..b09a20e924 100644 --- a/frontend/resources/translations/en.json +++ b/frontend/resources/translations/en.json @@ -633,6 +633,7 @@ "proBadge": "Pro", "memberProToggle": "Unlimited members", "guestCollabToggle": "10 guest collaborators", + "storageUnlimited": "Unlimited storage with your Pro Plan", "aiCredit": { "title": "Add AppFlowy AI Credit", "price": "5$",