fix: billing+cleanup (#5634)

* fix: billing fixes

* chore: best practice and cleaning

* chore: dispose of unused resources

* chore: upgrade editor version
This commit is contained in:
Mathias Mogensen 2024-06-27 02:00:21 +02:00 committed by GitHub
parent 7859fc7922
commit bbb3f95a13
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
49 changed files with 392 additions and 316 deletions

View File

@ -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

View File

@ -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<FlowyEmojiPicker> {
EmojiData.builtIn().then(
(value) {
kCachedEmojiData = value;
setState(() {
emojiData = value;
});
setState(() => emojiData = value);
},
);
}

View File

@ -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<void> _loadGroups() async {

View File

@ -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<CalendarPage> {
@override
void initState() {
super.initState();
_calendarState = GlobalKey<MonthViewState>();
_calendarBloc = CalendarBloc(
databaseController: widget.databaseController,
)..add(const CalendarEvent.initial());
super.initState();
}
@override
@ -378,13 +379,7 @@ class UnscheduledEventsButton extends StatefulWidget {
}
class _UnscheduledEventsButtonState extends State<UnscheduledEventsButton> {
late final PopoverController _popoverController;
@override
void initState() {
super.initState();
_popoverController = PopoverController();
}
final PopoverController _popoverController = PopoverController();
@override
Widget build(BuildContext context) {

View File

@ -30,6 +30,12 @@ class CalendarLayoutSetting extends StatefulWidget {
class _CalendarLayoutSettingState extends State<CalendarLayoutSetting> {
final PopoverMutex popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocProvider(

View File

@ -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<CheckboxFilterChoicechip> {
@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<CheckboxFilterEditor> {
final popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(

View File

@ -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<ChecklistFilterChoicechip> {
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();
}

View File

@ -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<NumberFilterEditor> {
final popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<NumberFilterEditorBloc, NumberFilterEditorState>(

View File

@ -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<SelectOptionFilterEditor> {
final popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocProvider.value(

View File

@ -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<TextFilterEditor> {
final popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<TextFilterEditorBloc, TextFilterEditorState>(

View File

@ -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<TimeFilterEditor> {
final popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<TimeFilterEditorBloc, TimeFilterEditorState>(

View File

@ -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<GridCreateFilterList> {
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

View File

@ -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<AddFilterButton> {
late PopoverController popoverController;
@override
void initState() {
popoverController = PopoverController();
super.initState();
}
final PopoverController popoverController = PopoverController();
@override
Widget build(BuildContext context) {

View File

@ -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<GridFieldCell> {
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) {

View File

@ -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<SortEditor> {
final popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocBuilder<SortEditorBloc, SortEditorState>(

View File

@ -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) {

View File

@ -370,13 +370,7 @@ class FieldDetailsEditor extends StatefulWidget {
}
class _FieldDetailsEditorState extends State<FieldDetailsEditor> {
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<FieldNameTextField> {
}
class SwitchFieldButton extends StatefulWidget {
const SwitchFieldButton({
super.key,
required this.popoverMutex,
});
const SwitchFieldButton({super.key, required this.popoverMutex});
final PopoverMutex popoverMutex;

View File

@ -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<CreateRowFieldButton> {
late PopoverController popoverController;
final PopoverController popoverController = PopoverController();
FieldPB? createdField;
@override
void initState() {
popoverController = PopoverController();
super.initState();
}
@override
Widget build(BuildContext context) {
return AppFlowyPopover(

View File

@ -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<DatabaseSettingsList> {
late final PopoverMutex popoverMutex = PopoverMutex();
final PopoverMutex popoverMutex = PopoverMutex();
@override
void dispose() {
popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {

View File

@ -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<DatabasePropertyList> {
)..add(const DatabasePropertyEvent.initial());
}
@override
void dispose() {
_popoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return BlocProvider<DatabasePropertyBloc>.value(

View File

@ -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<MentionDateBlock> {
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) {

View File

@ -67,8 +67,9 @@ class SettingsAIBloc extends Bloc<SettingsAIEvent, SettingsAIState> {
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<SettingsAIEvent, SettingsAIState> {
FlowyResult<UserProfilePB, FlowyError> 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);

View File

@ -117,6 +117,10 @@ class SettingsPlanBloc extends Bloc<SettingsPlanEvent, SettingsPlanState> {
);
},
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;
}

View File

@ -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);
}

View File

@ -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<HomeHotKeys> {
@override
void initState() {
super.initState();
_registerHotKeys(context);
}
@override
void didChangeDependencies() {
super.didChangeDependencies();
_registerHotKeys(context);
}

View File

@ -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 {

View File

@ -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<NotificationDialog>
@override
void dispose() {
_mutex.close();
_mutex.dispose();
_controller.removeListener(_updateState);
_controller.dispose();
super.dispose();

View File

@ -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<NotificationButton> createState() => _NotificationButtonState();
}
class _NotificationButtonState extends State<NotificationButton> {
final mutex = PopoverMutex();
@override
void dispose() {
mutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final views = context.watch<SidebarSectionsBloc>().state.section.views;
final mutex = PopoverMutex();
return BlocProvider<ReminderBloc>.value(
value: getIt<ReminderBloc>(),

View File

@ -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<NotificationItem> {
infoString = _buildInfoString();
}
@override
void dispose() {
mutex.dispose();
super.dispose();
}
String _buildInfoString() {
String scheduledString =
_scheduledString(widget.scheduled, widget.includeTime);

View File

@ -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<SettingsAIBloc>().add(
const SettingsAIEvent.toggleAISearch(),
);
},
onChanged: (_) => context
.read<SettingsAIBloc>()
.add(const SettingsAIEvent.toggleAISearch()),
);
}
},

View File

@ -47,7 +47,7 @@ class _SettingsPlanComparisonDialogState
Widget build(BuildContext context) {
final isLM = Theme.of(context).isLightMode;
return BlocListener<SettingsPlanBloc, SettingsPlanState>(
return BlocConsumer<SettingsPlanBloc, SettingsPlanState>(
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<SettingsPlanBloc>()
.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,

View File

@ -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<SettingsPlanBloc>();
}
@override
void didChangeDependencies() {
planBloc = context.read<SettingsPlanBloc>();
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<SettingsPlanBloc>().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<AppearanceSettingsCubit>().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<SettingsPlanBloc>.value(
value: context.read<SettingsPlanBloc>(),
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<String> _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<String> _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),
],
],
);
}

View File

@ -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<EmojiSelectionMenu> {
@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<EmojiSelectionMenu> {
//triggers on esc
widget.onExit();
return true;
} else {
return false;
}
return false;
}
@override
@ -106,17 +106,10 @@ class _EmojiSelectionMenuState extends State<EmojiSelectionMenu> {
super.deactivate();
}
@override
void dispose() {
super.dispose();
}
@override
Widget build(BuildContext context) {
return FlowyEmojiPicker(
onEmojiSelected: (_, emoji) {
widget.onSubmitted(emoji);
},
onEmojiSelected: (_, emoji) => widget.onSubmitted(emoji),
);
}
}

View File

@ -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<DefaultEmojiPickerView>
@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<DefaultEmojiPickerView>
);
_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<DefaultEmojiPickerView>
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<DefaultEmojiPickerView>
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<DefaultEmojiPickerView>
child: FittedBox(
child: Text(
emoji.emoji,
style: TextStyle(
fontSize: emojiSize,
),
style: TextStyle(fontSize: emojiSize),
),
),
),

View File

@ -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<SupabaseInput> {
late TextEditingController _controller;
@override
void initState() {
super.initState();
_controller = TextEditingController(text: widget.url);
}
late final _controller = TextEditingController(text: widget.url);
@override
void dispose() {

View File

@ -29,6 +29,12 @@ class _DateTimeSettingState extends State<DateTimeSetting> {
final timeSettingPopoverMutex = PopoverMutex();
String? overlayIdentifier;
@override
void dispose() {
timeSettingPopoverMutex.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
final List<Widget> children = [

View File

@ -129,11 +129,6 @@ class NavigatorAlertDialog extends StatefulWidget {
}
class _CreateFlowyAlertDialog extends State<NavigatorAlertDialog> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return StyledDialog(

View File

@ -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<T extends PopoverAction> extends StatefulWidget {
@ -42,12 +43,12 @@ class PopoverActionList<T extends PopoverAction> extends StatefulWidget {
class _PopoverActionListState<T extends PopoverAction>
extends State<PopoverActionList<T>> {
late PopoverController popoverController;
final PopoverController popoverController = PopoverController();
@override
void initState() {
popoverController = PopoverController();
super.initState();
void dispose() {
popoverController.close();
super.dispose();
}
@override

View File

@ -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<ViewTabBarItem> {
}
@override
Widget build(BuildContext context) {
return FlowyText.medium(view.name);
}
Widget build(BuildContext context) => FlowyText.medium(view.name);
}

View File

@ -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<MyApp> {
// 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')),
),
);
}

View File

@ -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<Popover> {
_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<PopoverContainerState>();
return result!;
return context.findAncestorStateOfType<PopoverContainerState>()!;
}
static PopoverContainerState? maybeOf(BuildContext context) {

View File

@ -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<FlowyOverlay> {
@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<FlowyOverlay> {
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<Widget> overlays) {
Widget? child;

View File

@ -36,13 +36,7 @@ class StyledListView extends StatefulWidget {
/// State is public so this can easily be controlled externally
class StyledListViewState extends State<StyledListView> {
late ScrollController scrollController;
@override
void initState() {
scrollController = ScrollController();
super.initState();
}
final scrollController = ScrollController();
@override
void dispose() {
@ -50,15 +44,6 @@ class StyledListViewState extends State<StyledListView> {
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<StyledListView> {
controller: scrollController,
itemExtent: widget.itemExtent,
itemCount: widget.itemCount,
itemBuilder: (c, i) => widget.itemBuilder(c, i),
itemBuilder: widget.itemBuilder,
),
);
return listContent;

View File

@ -137,7 +137,6 @@ class FlowyTextFieldState extends State<FlowyTextField> {
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<FlowyTextField> {
_onChanged(text);
}
},
onSubmitted: (text) => _onSubmitted(text),
onSubmitted: _onSubmitted,
onEditingComplete: widget.onEditingComplete,
minLines: 1,
maxLines: widget.maxLines,

View File

@ -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<StyledSearchTextInput> {
@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<StyledSearchTextInput> {
}
return KeyEventResult.ignored;
},
canRequestFocus: true,
);
// Listen for focus out events
_focusNode
@ -182,7 +184,6 @@ class StyledSearchTextInputState extends State<StyledSearchTextInput> {
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}) {

View File

@ -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<RoundedInputField> {
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<RoundedInputField> {
},
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<RoundedInputField> {
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<RoundedInputField> {
}
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,
);
}

View File

@ -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:

View File

@ -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:

View File

@ -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$",