chore: add unwaited futures to analysis options (#4485)

This commit is contained in:
Richard Shiue
2024-01-29 10:26:45 +08:00
committed by GitHub
parent 7be29c04a2
commit 05a06980b9
93 changed files with 441 additions and 452 deletions

View File

@ -49,6 +49,7 @@ linter:
- always_declare_return_types - always_declare_return_types
- sort_constructors_first - sort_constructors_first
- unawaited_futures
# Additional information about this file can be found at # Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options # https://dart.dev/guides/language/analysis-options

View File

@ -23,7 +23,7 @@ void main() {
input: 'hello world', input: 'hello world',
); );
await tester.assertCellContent( tester.assertCellContent(
rowIndex: 0, rowIndex: 0,
fieldType: FieldType.RichText, fieldType: FieldType.RichText,
content: 'hello world', content: 'hello world',
@ -56,13 +56,13 @@ void main() {
cellIndex: 1, cellIndex: 1,
); );
await tester.assertCellContent( tester.assertCellContent(
rowIndex: 0, rowIndex: 0,
fieldType: FieldType.RichText, fieldType: FieldType.RichText,
content: 'hello', content: 'hello',
); );
await tester.assertCellContent( tester.assertCellContent(
rowIndex: 0, rowIndex: 0,
fieldType: FieldType.RichText, fieldType: FieldType.RichText,
content: 'world', content: 'world',
@ -95,7 +95,7 @@ void main() {
input: '0.2', input: '0.2',
); );
// -1 -> -1 // -1 -> -1
await tester.assertCellContent( tester.assertCellContent(
rowIndex: 0, rowIndex: 0,
fieldType: fieldType, fieldType: fieldType,
content: '-1', content: '-1',
@ -108,7 +108,7 @@ void main() {
input: '.1', input: '.1',
); );
// 0.2 -> 0.2 // 0.2 -> 0.2
await tester.assertCellContent( tester.assertCellContent(
rowIndex: 1, rowIndex: 1,
fieldType: fieldType, fieldType: fieldType,
content: '0.2', content: '0.2',
@ -121,7 +121,7 @@ void main() {
input: '', input: '',
); );
// .1 -> 0.1 // .1 -> 0.1
await tester.assertCellContent( tester.assertCellContent(
rowIndex: 2, rowIndex: 2,
fieldType: fieldType, fieldType: fieldType,
content: '0.1', content: '0.1',

View File

@ -27,29 +27,29 @@ void main() {
// hide the field // hide the field
await tester.tapGridFieldWithName('New field 1'); await tester.tapGridFieldWithName('New field 1');
await tester.tapHidePropertyButton(); await tester.tapHidePropertyButton();
await tester.noFieldWithName('New field 1'); tester.noFieldWithName('New field 1');
// go back to inline database view, expect field to be shown // go back to inline database view, expect field to be shown
await tester.tapTabBarLinkedViewByViewName('Untitled'); await tester.tapTabBarLinkedViewByViewName('Untitled');
await tester.findFieldWithName('New field 1'); tester.findFieldWithName('New field 1');
// go back to linked database view, expect field to be hidden // go back to linked database view, expect field to be hidden
await tester.tapTabBarLinkedViewByViewName('Grid'); await tester.tapTabBarLinkedViewByViewName('Grid');
await tester.noFieldWithName('New field 1'); tester.noFieldWithName('New field 1');
// use the settings button to show the field // use the settings button to show the field
await tester.tapDatabaseSettingButton(); await tester.tapDatabaseSettingButton();
await tester.tapViewPropertiesButton(); await tester.tapViewPropertiesButton();
await tester.tapViewTogglePropertyVisibilityButtonByName('New field 1'); await tester.tapViewTogglePropertyVisibilityButtonByName('New field 1');
await tester.dismissFieldEditor(); await tester.dismissFieldEditor();
await tester.findFieldWithName('New field 1'); tester.findFieldWithName('New field 1');
// open first row in popup then hide the field // open first row in popup then hide the field
await tester.openFirstRowDetailPage(); await tester.openFirstRowDetailPage();
await tester.tapGridFieldWithNameInRowDetailPage('New field 1'); await tester.tapGridFieldWithNameInRowDetailPage('New field 1');
await tester.tapHidePropertyButtonInFieldEditor(); await tester.tapHidePropertyButtonInFieldEditor();
await tester.dismissRowDetailPage(); await tester.dismissRowDetailPage();
await tester.noFieldWithName('New field 1'); tester.noFieldWithName('New field 1');
}); });
}); });
} }

View File

@ -64,7 +64,7 @@ void main() {
await tester.createField(FieldType.Checklist, 'checklist'); await tester.createField(FieldType.Checklist, 'checklist');
// check the field is created successfully // check the field is created successfully
await tester.findFieldWithName('checklist'); tester.findFieldWithName('checklist');
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
@ -84,7 +84,7 @@ void main() {
// confirm delete // confirm delete
await tester.tapDialogOkButton(); await tester.tapDialogOkButton();
await tester.noFieldWithName('New field 1'); tester.noFieldWithName('New field 1');
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
@ -104,7 +104,7 @@ void main() {
await tester.tapGridFieldWithName('New field 1'); await tester.tapGridFieldWithName('New field 1');
await tester.tapDuplicatePropertyButton(); await tester.tapDuplicatePropertyButton();
await tester.findFieldWithName('New field 1 (copy)'); tester.findFieldWithName('New field 1 (copy)');
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });
@ -120,13 +120,13 @@ void main() {
await tester.tapGridFieldWithName('Type'); await tester.tapGridFieldWithName('Type');
await tester.tapInsertFieldButton(left: false, name: 'Right'); await tester.tapInsertFieldButton(left: false, name: 'Right');
await tester.dismissFieldEditor(); await tester.dismissFieldEditor();
await tester.findFieldWithName('Right'); tester.findFieldWithName('Right');
// insert new field to the right // insert new field to the right
await tester.tapGridFieldWithName('Type'); await tester.tapGridFieldWithName('Type');
await tester.tapInsertFieldButton(left: true, name: "Left"); await tester.tapInsertFieldButton(left: true, name: "Left");
await tester.dismissFieldEditor(); await tester.dismissFieldEditor();
await tester.findFieldWithName('Left'); tester.findFieldWithName('Left');
await tester.pumpAndSettle(); await tester.pumpAndSettle();
}); });

View File

@ -16,7 +16,7 @@ void main() {
// check the text cell // check the text cell
final textCells = <String>['A', 'B', 'C', 'D', 'E', '', '', '', '', '']; final textCells = <String>['A', 'B', 'C', 'D', 'E', '', '', '', '', ''];
for (final (index, content) in textCells.indexed) { for (final (index, content) in textCells.indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.RichText, fieldType: FieldType.RichText,
content: content, content: content,
@ -57,7 +57,7 @@ void main() {
'', '',
]; ];
for (final (index, content) in numberCells.indexed) { for (final (index, content) in numberCells.indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.Number, fieldType: FieldType.Number,
content: content, content: content,
@ -74,7 +74,7 @@ void main() {
'', '',
]; ];
for (final (index, content) in urlCells.indexed) { for (final (index, content) in urlCells.indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.URL, fieldType: FieldType.URL,
content: content, content: content,
@ -135,7 +135,7 @@ void main() {
null, null,
]; ];
for (final (index, percent) in checklistCells.indexed) { for (final (index, percent) in checklistCells.indexed) {
await tester.assertChecklistCellInGrid( tester.assertChecklistCellInGrid(
rowIndex: index, rowIndex: index,
percent: percent, percent: percent,
); );

View File

@ -28,7 +28,7 @@ void main() {
'', '',
]; ];
for (final (index, content) in textCells.indexed) { for (final (index, content) in textCells.indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.RichText, fieldType: FieldType.RichText,
content: content, content: content,
@ -51,7 +51,7 @@ void main() {
'', '',
'', '',
].indexed) { ].indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.RichText, fieldType: FieldType.RichText,
content: content, content: content,
@ -75,7 +75,7 @@ void main() {
'', '',
'', '',
].indexed) { ].indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.RichText, fieldType: FieldType.RichText,
content: content, content: content,
@ -153,7 +153,7 @@ void main() {
'12', '12',
'', '',
].indexed) { ].indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.Number, fieldType: FieldType.Number,
content: content, content: content,
@ -176,7 +176,7 @@ void main() {
'-2', '-2',
'', '',
].indexed) { ].indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.Number, fieldType: FieldType.Number,
content: content, content: content,
@ -255,7 +255,7 @@ void main() {
'2', '2',
'', '',
].indexed) { ].indexed) {
await tester.assertCellContent( tester.assertCellContent(
rowIndex: index, rowIndex: index,
fieldType: FieldType.Number, fieldType: FieldType.Number,
content: content, content: content,

View File

@ -84,7 +84,7 @@ void main() {
await createInlineDatabase(tester, ViewLayoutPB.Grid); await createInlineDatabase(tester, ViewLayoutPB.Grid);
// validate the referenced grid is inserted // validate the inline grid is created
expect( expect(
find.descendant( find.descendant(
of: find.byType(AppFlowyEditor), of: find.byType(AppFlowyEditor),
@ -100,7 +100,7 @@ void main() {
await createInlineDatabase(tester, ViewLayoutPB.Board); await createInlineDatabase(tester, ViewLayoutPB.Board);
// validate the referenced grid is inserted // validate the inline board is created
expect( expect(
find.descendant( find.descendant(
of: find.byType(AppFlowyEditor), of: find.byType(AppFlowyEditor),
@ -116,7 +116,7 @@ void main() {
await createInlineDatabase(tester, ViewLayoutPB.Calendar); await createInlineDatabase(tester, ViewLayoutPB.Calendar);
// validate the referenced grid is inserted // validate the inline calendar is created
expect( expect(
find.descendant( find.descendant(
of: find.byType(AppFlowyEditor), of: find.byType(AppFlowyEditor),

View File

@ -64,7 +64,7 @@ void main() {
paths: [imagePath], paths: [imagePath],
); );
getIt<KeyValueStorage>().set(KVKeys.kCloudType, '0'); await getIt<KeyValueStorage>().set(KVKeys.kCloudType, '0');
await tester.tapButtonWithName( await tester.tapButtonWithName(
LocaleKeys.document_imageBlock_upload_placeholder.tr(), LocaleKeys.document_imageBlock_upload_placeholder.tr(),
); );

View File

@ -33,7 +33,7 @@ void main() {
File(path).writeAsStringSync(str); File(path).writeAsStringSync(str);
} }
// mock get files // mock get files
await mockPickFilePaths( mockPickFilePaths(
paths: testFileNames paths: testFileNames
.map((e) => p.join(context.applicationDataDirectory, e)) .map((e) => p.join(context.applicationDataDirectory, e))
.toList(), .toList(),

View File

@ -34,12 +34,12 @@ extension AppFlowyTestBase on WidgetTester {
String? pathExtension, String? pathExtension,
// use to specify the application data directory, if not specified, a temporary directory will be used. // use to specify the application data directory, if not specified, a temporary directory will be used.
String? dataDirectory, String? dataDirectory,
Size windowsSize = const Size(1600, 1200), Size windowSize = const Size(1600, 1200),
AuthenticatorType? cloudType, AuthenticatorType? cloudType,
String? email, String? email,
}) async { }) async {
// view.physicalSize = windowsSize; // view.physicalSize = windowsSize;
binding.setSurfaceSize(windowsSize); await binding.setSurfaceSize(windowSize);
// addTearDown(() => binding.setSurfaceSize(null)); // addTearDown(() => binding.setSurfaceSize(null));
mockHotKeyManagerHandlers(); mockHotKeyManagerHandlers();

View File

@ -121,7 +121,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
File(path).writeAsStringSync(str); File(path).writeAsStringSync(str);
} }
// mock get files // mock get files
await mockPickFilePaths( mockPickFilePaths(
paths: paths, paths: paths,
); );
await tapDatabaseRawDataButton(); await tapDatabaseRawDataButton();
@ -209,12 +209,12 @@ extension AppFlowyDatabaseTest on WidgetTester {
} }
/// The [fieldName] must be unique in the grid. /// The [fieldName] must be unique in the grid.
Future<void> assertCellContent({ void assertCellContent({
required int rowIndex, required int rowIndex,
required FieldType fieldType, required FieldType fieldType,
required String content, required String content,
int cellIndex = 0, int cellIndex = 0,
}) async { }) {
final findCell = cellFinder(rowIndex, fieldType, cellIndex: cellIndex); final findCell = cellFinder(rowIndex, fieldType, cellIndex: cellIndex);
final findContent = find.descendant( final findContent = find.descendant(
of: findCell, of: findCell,
@ -263,10 +263,10 @@ extension AppFlowyDatabaseTest on WidgetTester {
} }
/// null percent means no progress bar should be found /// null percent means no progress bar should be found
Future<void> assertChecklistCellInGrid({ void assertChecklistCellInGrid({
required int rowIndex, required int rowIndex,
required double? percent, required double? percent,
}) async { }) {
final findCell = cellFinder(rowIndex, FieldType.Checklist); final findCell = cellFinder(rowIndex, FieldType.Checklist);
if (percent == null) { if (percent == null) {
@ -880,14 +880,14 @@ extension AppFlowyDatabaseTest on WidgetTester {
expect(widget.field.fieldType, fieldType); expect(widget.field.fieldType, fieldType);
} }
Future<void> findFieldWithName(String name) async { void findFieldWithName(String name) {
final field = find.byWidgetPredicate( final field = find.byWidgetPredicate(
(widget) => widget is FieldCellButton && widget.field.name == name, (widget) => widget is FieldCellButton && widget.field.name == name,
); );
expect(field, findsOneWidget); expect(field, findsOneWidget);
} }
Future<void> noFieldWithName(String name) async { void noFieldWithName(String name) {
final field = find.byWidgetPredicate( final field = find.byWidgetPredicate(
(widget) => widget is FieldCellButton && widget.field.name == name, (widget) => widget is FieldCellButton && widget.field.name == name,
); );
@ -1559,7 +1559,7 @@ extension AppFlowyDatabaseTest on WidgetTester {
await tapButton(okButton); await tapButton(okButton);
} }
Future<void> assertCurrentDatabaseTagIs(DatabaseLayoutPB layout) async { void assertCurrentDatabaseTagIs(DatabaseLayoutPB layout) {
switch (layout) { switch (layout) {
case DatabaseLayoutPB.Board: case DatabaseLayoutPB.Board:
expect(find.byType(BoardPage), findsOneWidget); expect(find.byType(BoardPage), findsOneWidget);

View File

@ -1,3 +1,4 @@
import 'dart:async';
import 'dart:ui'; import 'dart:ui';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
@ -202,9 +203,11 @@ class EditorOperations {
/// Update the editor's selection /// Update the editor's selection
Future<void> updateSelection(Selection selection) async { Future<void> updateSelection(Selection selection) async {
final editorState = getCurrentEditorState(); final editorState = getCurrentEditorState();
unawaited(
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
selection, selection,
reason: SelectionUpdateReason.uiEvent, reason: SelectionUpdateReason.uiEvent,
),
); );
await tester.pumpAndSettle(const Duration(milliseconds: 200)); await tester.pumpAndSettle(const Duration(milliseconds: 200));
} }

View File

@ -74,9 +74,7 @@ Future<String> mockSaveFilePath(
return path; return path;
} }
Future<List<String>> mockPickFilePaths({ List<String> mockPickFilePaths({required List<String> paths}) {
required List<String> paths,
}) async {
getIt.unregister<FilePickerService>(); getIt.unregister<FilePickerService>();
getIt.registerFactory<FilePickerService>( getIt.registerFactory<FilePickerService>(
() => MockFilePicker( () => MockFilePicker(

View File

@ -50,11 +50,8 @@ class NetworkListener {
} }
}(); }();
final state = NetworkStatePB.create()..ty = networkType; final state = NetworkStatePB.create()..ty = networkType;
UserEventUpdateNetworkState(state).send().then((result) { return UserEventUpdateNetworkState(state).send().then((result) {
result.fold( result.fold((l) {}, (e) => Log.error(e));
(l) {},
(e) => Log.error(e),
);
}); });
} }
} }

View File

@ -11,7 +11,7 @@ import 'package:go_router/go_router.dart';
extension MobileRouter on BuildContext { extension MobileRouter on BuildContext {
Future<void> pushView(ViewPB view, [Map<String, dynamic>? arguments]) async { Future<void> pushView(ViewPB view, [Map<String, dynamic>? arguments]) async {
push( await push(
Uri( Uri(
path: view.routeName, path: view.routeName,
queryParameters: view.queryParameters(arguments), queryParameters: view.queryParameters(arguments),

View File

@ -72,7 +72,7 @@ void showQuickEditField(
BuildContext context, BuildContext context,
String viewId, String viewId,
FieldInfo fieldInfo, FieldInfo fieldInfo,
) async { ) {
showMobileBottomSheet( showMobileBottomSheet(
context, context,
padding: EdgeInsets.zero, padding: EdgeInsets.zero,

View File

@ -348,7 +348,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
}, },
); );
if (newLayout != null && newLayout != databaseLayout) { if (newLayout != null && newLayout != databaseLayout) {
DatabaseViewBackendService.updateLayout( await DatabaseViewBackendService.updateLayout(
viewId: databaseController.viewId, viewId: databaseController.viewId,
layout: newLayout, layout: newLayout,
); );
@ -357,7 +357,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
} }
if (setting == DatabaseViewSettings.board) { if (setting == DatabaseViewSettings.board) {
showMobileBottomSheet<DatabaseLayoutPB>( await showMobileBottomSheet<DatabaseLayoutPB>(
context, context,
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
builder: (context) { builder: (context) {
@ -373,7 +373,7 @@ class DatabaseViewSettingTile extends StatelessWidget {
} }
if (setting == DatabaseViewSettings.calendar) { if (setting == DatabaseViewSettings.calendar) {
showMobileBottomSheet<DatabaseLayoutPB>( await showMobileBottomSheet<DatabaseLayoutPB>(
context, context,
resizeToAvoidBottomInset: false, resizeToAvoidBottomInset: false,
builder: (context) { builder: (context) {

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart'; import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart'; import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart';
@ -38,7 +40,9 @@ class FontSetting extends StatelessWidget {
if (newFont != null && newFont != selectedFont) { if (newFont != null && newFont != selectedFont) {
if (context.mounted) { if (context.mounted) {
context.read<AppearanceSettingsCubit>().setFontFamily(newFont); context.read<AppearanceSettingsCubit>().setFontFamily(newFont);
context.read<DocumentAppearanceCubit>().syncFontFamily(newFont); unawaited(
context.read<DocumentAppearanceCubit>().syncFontFamily(newFont),
);
} }
} }
}, },

View File

@ -100,7 +100,7 @@ class _SelfHostUrlBottomSheetState extends State<SelfHostUrlBottomSheet> {
validateUrl(value).fold( validateUrl(value).fold(
(url) async { (url) async {
await setAppFlowyCloudUrl(Some(url)); await setAppFlowyCloudUrl(Some(url));
runAppFlowy(); await runAppFlowy();
}, },
(err) => Log.error(err), (err) => Log.error(err),
); );

View File

@ -45,7 +45,7 @@ class UserSessionSettingGroup extends StatelessWidget {
labelText: LocaleKeys.settings_menu_logout.tr(), labelText: LocaleKeys.settings_menu_logout.tr(),
onPressed: () async { onPressed: () async {
await getIt<AuthService>().signOut(); await getIt<AuthService>().signOut();
runAppFlowy(); await runAppFlowy();
}, },
), ),
], ],

View File

@ -18,7 +18,7 @@ class NumberCellBloc extends Bloc<NumberCellEvent, NumberCellState> {
void _dispatch() { void _dispatch() {
on<NumberCellEvent>( on<NumberCellEvent>(
(event, emit) async { (event, emit) async {
event.when( await event.when(
initial: () { initial: () {
_startListening(); _startListening();
}, },

View File

@ -242,8 +242,10 @@ class DatabaseController {
); );
} }
Future<void> _loadLayoutSetting() async { Future<void> _loadLayoutSetting() {
_databaseViewBackendSvc.getLayoutSetting(databaseLayout).then((result) { return _databaseViewBackendSvc
.getLayoutSetting(databaseLayout)
.then((result) {
result.fold( result.fold(
(newDatabaseLayoutSetting) { (newDatabaseLayoutSetting) {
databaseLayoutSetting = newDatabaseLayoutSetting; databaseLayoutSetting = newDatabaseLayoutSetting;

View File

@ -47,7 +47,7 @@ class DatabaseGroupBloc extends Bloc<DatabaseGroupEvent, DatabaseGroupState> {
void _dispatch() { void _dispatch() {
on<DatabaseGroupEvent>( on<DatabaseGroupEvent>(
(event, emit) async { (event, emit) async {
event.when( await event.when(
initial: () { initial: () {
_startListening(); _startListening();
}, },

View File

@ -21,7 +21,7 @@ class DatabaseTabBarBloc
: super(DatabaseTabBarState.initial(view)) { : super(DatabaseTabBarState.initial(view)) {
on<DatabaseTabBarEvent>( on<DatabaseTabBarEvent>(
(event, emit) async { (event, emit) async {
event.when( await event.when(
initial: () { initial: () {
_listenInlineViewChanged(); _listenInlineViewChanged();
_loadChildView(); _loadChildView();
@ -93,7 +93,7 @@ class DatabaseTabBarBloc
// Dispose the controller when the tab is removed. // Dispose the controller when the tab is removed.
final controller = final controller =
tabBarControllerByViewId.remove(tabBar.viewId); tabBarControllerByViewId.remove(tabBar.viewId);
controller?.dispose(); await controller?.dispose();
} }
if (index == state.selectedIndex) { if (index == state.selectedIndex) {
@ -186,17 +186,18 @@ class DatabaseTabBarBloc
); );
} }
Future<void> _loadChildView() async { void _loadChildView() async {
ViewBackendService.getChildViews(viewId: state.parentView.id) final viewsOrFail =
.then((viewsOrFail) { await ViewBackendService.getChildViews(viewId: state.parentView.id);
if (isClosed) {
return;
}
viewsOrFail.fold( viewsOrFail.fold(
(views) => add(DatabaseTabBarEvent.didLoadChildViews(views)), (views) {
if (!isClosed) {
add(DatabaseTabBarEvent.didLoadChildViews(views));
}
},
(err) => Log.error(err), (err) => Log.error(err),
); );
});
} }
} }

View File

@ -255,7 +255,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
); );
} }
Future<void> _reorderGroup( void _reorderGroup(
String fromGroupId, String fromGroupId,
String toGroupId, String toGroupId,
Emitter<BoardState> emit, Emitter<BoardState> emit,
@ -275,7 +275,7 @@ class BoardBloc extends Bloc<BoardEvent, BoardState> {
@override @override
Future<void> close() async { Future<void> close() async {
for (final controller in groupControllers.values) { for (final controller in groupControllers.values) {
controller.dispose(); await controller.dispose();
} }
return super.close(); return super.close();
} }

View File

@ -107,8 +107,8 @@ class GroupController {
); );
} }
Future<void> dispose() async { Future<void> dispose() {
_listener.stop(); return _listener.stop();
} }
} }

View File

@ -218,9 +218,9 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
}); });
} }
Future<void> _loadAllEvents() async { void _loadAllEvents() async {
final payload = CalendarEventRequestPB.create()..viewId = viewId; final payload = CalendarEventRequestPB.create()..viewId = viewId;
DatabaseEventGetAllCalendarEvents(payload).send().then((result) { final result = await DatabaseEventGetAllCalendarEvents(payload).send();
result.fold( result.fold(
(events) { (events) {
if (!isClosed) { if (!isClosed) {
@ -229,7 +229,6 @@ class CalendarBloc extends Bloc<CalendarEvent, CalendarState> {
}, },
(r) => Log.error(r), (r) => Log.error(r),
); );
});
} }
List<CalendarEventData<CalendarDayEvent>> _calendarEventDataFromEventPBs( List<CalendarEventData<CalendarDayEvent>> _calendarEventDataFromEventPBs(

View File

@ -90,9 +90,9 @@ class UnscheduleEventsBloc
); );
} }
Future<void> _loadAllEvents() async { void _loadAllEvents() async {
final payload = CalendarEventRequestPB.create()..viewId = viewId; final payload = CalendarEventRequestPB.create()..viewId = viewId;
DatabaseEventGetAllCalendarEvents(payload).send().then((result) { final result = await DatabaseEventGetAllCalendarEvents(payload).send();
result.fold( result.fold(
(events) { (events) {
if (!isClosed) { if (!isClosed) {
@ -101,7 +101,6 @@ class UnscheduleEventsBloc
}, },
(r) => Log.error(r), (r) => Log.error(r),
); );
});
} }
void _startListening() { void _startListening() {

View File

@ -29,7 +29,7 @@ class CheckboxFilterEditorBloc
void _dispatch() { void _dispatch() {
on<CheckboxFilterEditorEvent>( on<CheckboxFilterEditorEvent>(
(event, emit) async { (event, emit) async {
event.when( await event.when(
initial: () async { initial: () async {
_startListening(); _startListening();
}, },

View File

@ -29,7 +29,7 @@ class ChecklistFilterEditorBloc
void _dispatch() { void _dispatch() {
on<ChecklistFilterEditorEvent>( on<ChecklistFilterEditorEvent>(
(event, emit) async { (event, emit) async {
event.when( await event.when(
initial: () async { initial: () async {
_startListening(); _startListening();
}, },

View File

@ -34,7 +34,7 @@ class GridCreateFilterBloc
on<GridCreateFilterEvent>( on<GridCreateFilterEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
initial: () async { initial: () {
_startListening(); _startListening();
}, },
didReceiveFields: (List<FieldInfo> fields) { didReceiveFields: (List<FieldInfo> fields) {

View File

@ -34,7 +34,7 @@ class SelectOptionFilterEditorBloc
on<SelectOptionFilterEditorEvent>( on<SelectOptionFilterEditorEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
initial: () async { initial: () {
_startListening(); _startListening();
_loadOptions(); _loadOptions();
}, },

View File

@ -30,7 +30,7 @@ class TextFilterEditorBloc
on<TextFilterEditorEvent>( on<TextFilterEditorEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
initial: () async { initial: () {
_startListening(); _startListening();
}, },
updateCondition: (TextFilterConditionPB condition) { updateCondition: (TextFilterConditionPB condition) {

View File

@ -31,7 +31,7 @@ class RowDocumentBloc extends Bloc<RowDocumentEvent, RowDocumentState> {
on<RowDocumentEvent>( on<RowDocumentEvent>(
(event, emit) async { (event, emit) async {
await event.when( await event.when(
initial: () async { initial: () {
_getRowDocumentView(); _getRowDocumentView();
}, },
didReceiveRowDocument: (view) { didReceiveRowDocument: (view) {

View File

@ -31,7 +31,7 @@ class CreateSortBloc extends Bloc<CreateSortEvent, CreateSortState> {
on<CreateSortEvent>( on<CreateSortEvent>(
(event, emit) async { (event, emit) async {
event.when( event.when(
initial: () async { initial: () {
_startListening(); _startListening();
}, },
didReceiveFields: (List<FieldInfo> fields) { didReceiveFields: (List<FieldInfo> fields) {

View File

@ -32,8 +32,8 @@ class SortEditorBloc extends Bloc<SortEditorEvent, SortEditorState> {
void _dispatch() { void _dispatch() {
on<SortEditorEvent>( on<SortEditorEvent>(
(event, emit) async { (event, emit) async {
event.when( await event.when(
initial: () async { initial: () {
_startListening(); _startListening();
}, },
didReceiveFields: (List<FieldInfo> fields) { didReceiveFields: (List<FieldInfo> fields) {

View File

@ -98,7 +98,7 @@ class _GridCreateFilterListState extends State<GridCreateFilterList> {
} }
@override @override
Future<void> dispose() async { void dispose() {
editBloc.close(); editBloc.close();
super.dispose(); super.dispose();
} }

View File

@ -119,9 +119,9 @@ class _GridFieldCellState extends State<GridFieldCell> {
} }
@override @override
Future<void> dispose() async { void dispose() {
_bloc.close();
super.dispose(); super.dispose();
await _bloc.close();
} }
} }

View File

@ -97,7 +97,7 @@ class _GridCreateSortListState extends State<GridCreateSortList> {
} }
@override @override
Future<void> dispose() async { void dispose() {
editBloc.close(); editBloc.close();
super.dispose(); super.dispose();
} }

View File

@ -95,7 +95,7 @@ class _RowCardState extends State<RowCard> {
} }
@override @override
Future<void> dispose() async { void dispose() {
rowNotifier.dispose(); rowNotifier.dispose();
_cardBloc.close(); _cardBloc.close();
super.dispose(); super.dispose();

View File

@ -68,7 +68,7 @@ class _NumberCellState extends GridEditableTextCell<EditableNumberCell> {
} }
@override @override
Future<void> dispose() async { void dispose() {
_textEditingController.dispose(); _textEditingController.dispose();
cellBloc.close(); cellBloc.close();
super.dispose(); super.dispose();

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/plugins/database/application/cell/cell_controller.dart'; import 'package:appflowy/plugins/database/application/cell/cell_controller.dart';
import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart'; import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart';
import 'package:appflowy/plugins/database/application/database_controller.dart'; import 'package:appflowy/plugins/database/application/database_controller.dart';
@ -66,7 +68,7 @@ class _TextCellState extends GridEditableTextCell<EditableTextCell> {
} }
@override @override
Future<void> dispose() async { void dispose() {
_textEditingController.dispose(); _textEditingController.dispose();
cellBloc.close(); cellBloc.close();
super.dispose(); super.dispose();

View File

@ -176,7 +176,7 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
await _transactionAdapter.apply(event.$2, editorState); await _transactionAdapter.apply(event.$2, editorState);
// check if the document is empty. // check if the document is empty.
applyRules(); await applyRules();
if (!isClosed) { if (!isClosed) {
// ignore: invalid_use_of_visible_for_testing_member // ignore: invalid_use_of_visible_for_testing_member
@ -197,8 +197,10 @@ class DocumentBloc extends Bloc<DocumentEvent, DocumentState> {
} }
Future<void> applyRules() async { Future<void> applyRules() async {
ensureAtLeastOneParagraphExists(); await Future.wait([
ensureLastNodeIsEditable(); ensureAtLeastOneParagraphExists(),
ensureLastNodeIsEditable(),
]);
} }
Future<void> ensureLastNodeIsEditable() async { Future<void> ensureLastNodeIsEditable() async {

View File

@ -164,10 +164,10 @@ class _DocumentPageState extends State<DocumentPage> {
// } // }
// } // }
Future<void> _onNotificationAction( void _onNotificationAction(
BuildContext context, BuildContext context,
NotificationActionState state, NotificationActionState state,
) async { ) {
if (state.action != null && state.action!.type == ActionType.jumpToBlock) { if (state.action != null && state.action!.type == ActionType.jumpToBlock) {
final path = state.action?.arguments?[ActionArgumentKeys.nodePath]; final path = state.action?.arguments?[ActionArgumentKeys.nodePath];

View File

@ -164,7 +164,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
case _ActionType.delete: case _ActionType.delete:
final transaction = widget.editorState.transaction; final transaction = widget.editorState.transaction;
transaction.deleteNode(widget.node); transaction.deleteNode(widget.node);
widget.editorState.apply(transaction); await widget.editorState.apply(transaction);
break; break;
} }
controller.close(); controller.close();
@ -177,7 +177,7 @@ class _BuiltInPageWidgetState extends State<BuiltInPageWidget> {
Future<void> _deletePage() async { Future<void> _deletePage() async {
final transaction = widget.editorState.transaction; final transaction = widget.editorState.transaction;
transaction.deleteNode(widget.node); transaction.deleteNode(widget.node);
widget.editorState.apply(transaction); await widget.editorState.apply(transaction);
} }
} }

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/mobile_block_action_buttons.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/actions/mobile_block_action_buttons.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_item_list_menu.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/base/selectable_item_list_menu.dart';
@ -310,7 +312,7 @@ class _CodeBlockComponentWidgetState extends State<CodeBlockComponentWidget>
MobileCodeLanguagePickerScreen.routeName, MobileCodeLanguagePickerScreen.routeName,
); );
if (language != null) { if (language != null) {
updateLanguage(language); unawaited(updateLanguage(language));
} }
} }
}, },

View File

@ -101,7 +101,7 @@ extension PasteNodes on EditorState {
// delete the selection first. // delete the selection first.
if (!selection.isCollapsed) { if (!selection.isCollapsed) {
deleteSelection(selection); await deleteSelection(selection);
} }
// fetch selection again.selection = editorState.selection; // fetch selection again.selection = editorState.selection;

View File

@ -20,15 +20,12 @@ SelectionMenuItem inlineGridMenuItem(DocumentBloc documentBloc) =>
handler: (editorState, menuService, context) async { handler: (editorState, menuService, context) async {
// create the view inside current page // create the view inside current page
final parentViewId = documentBloc.view.id; final parentViewId = documentBloc.view.id;
ViewBackendService.createView( final value = await ViewBackendService.createView(
parentViewId: parentViewId, parentViewId: parentViewId,
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
layoutType: ViewLayoutPB.Grid, layoutType: ViewLayoutPB.Grid,
).then(
(value) => value
.swap()
.map((r) => editorState.insertInlinePage(parentViewId, r)),
); );
value.swap().map((r) => editorState.insertInlinePage(parentViewId, r));
}, },
); );
@ -44,15 +41,12 @@ SelectionMenuItem inlineBoardMenuItem(DocumentBloc documentBloc) =>
handler: (editorState, menuService, context) async { handler: (editorState, menuService, context) async {
// create the view inside current page // create the view inside current page
final parentViewId = documentBloc.view.id; final parentViewId = documentBloc.view.id;
ViewBackendService.createView( final value = await ViewBackendService.createView(
parentViewId: parentViewId, parentViewId: parentViewId,
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
layoutType: ViewLayoutPB.Board, layoutType: ViewLayoutPB.Board,
).then(
(value) => value
.swap()
.map((r) => editorState.insertInlinePage(parentViewId, r)),
); );
value.swap().map((r) => editorState.insertInlinePage(parentViewId, r));
}, },
); );
@ -68,14 +62,11 @@ SelectionMenuItem inlineCalendarMenuItem(DocumentBloc documentBloc) =>
handler: (editorState, menuService, context) async { handler: (editorState, menuService, context) async {
// create the view inside current page // create the view inside current page
final parentViewId = documentBloc.view.id; final parentViewId = documentBloc.view.id;
ViewBackendService.createView( final value = await ViewBackendService.createView(
parentViewId: parentViewId, parentViewId: parentViewId,
name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
layoutType: ViewLayoutPB.Calendar, layoutType: ViewLayoutPB.Calendar,
).then(
(value) => value
.swap()
.map((r) => editorState.insertInlinePage(parentViewId, r)),
); );
value.swap().map((r) => editorState.insertInlinePage(parentViewId, r));
}, },
); );

View File

@ -53,7 +53,7 @@ class ChangeCoverPopoverBloc
final updateImageList = currentState.imageNames final updateImageList = currentState.imageNames
.where((path) => path != deleteImage.path) .where((path) => path != deleteImage.path)
.toList(); .toList();
await _updateImagePathsInStorage(updateImageList); _updateImagePathsInStorage(updateImageList);
emit(Loaded(updateImageList)); emit(Loaded(updateImageList));
} }
}, },
@ -69,7 +69,7 @@ class ChangeCoverPopoverBloc
_removeCoverImageFromNode(); _removeCoverImageFromNode();
} }
} }
await _updateImagePathsInStorage([]); _updateImagePathsInStorage([]);
emit(const Loaded([])); emit(const Loaded([]));
} }
}, },
@ -84,14 +84,13 @@ class ChangeCoverPopoverBloc
return imageNames; return imageNames;
} }
imageNames.removeWhere((name) => !File(name).existsSync()); imageNames.removeWhere((name) => !File(name).existsSync());
_prefs.setStringList(kLocalImagesKey, imageNames); unawaited(_prefs.setStringList(kLocalImagesKey, imageNames));
return imageNames; return imageNames;
} }
Future<void> _updateImagePathsInStorage(List<String> imagePaths) async { void _updateImagePathsInStorage(List<String> imagePaths) async {
await _initCompleter.future; await _initCompleter.future;
_prefs.setStringList(kLocalImagesKey, imagePaths); await _prefs.setStringList(kLocalImagesKey, imagePaths);
return;
} }
Future<void> _deleteImageInStorage(String path) async { Future<void> _deleteImageInStorage(String path) async {
@ -99,14 +98,14 @@ class ChangeCoverPopoverBloc
await imageFile.delete(); await imageFile.delete();
} }
Future<void> _removeCoverImageFromNode() async { void _removeCoverImageFromNode() {
final transaction = editorState.transaction; final transaction = editorState.transaction;
transaction.updateNode(node, { transaction.updateNode(node, {
DocumentHeaderBlockKeys.coverType: CoverType.none.toString(), DocumentHeaderBlockKeys.coverType: CoverType.none.toString(),
DocumentHeaderBlockKeys.icon: DocumentHeaderBlockKeys.icon:
node.attributes[DocumentHeaderBlockKeys.icon], node.attributes[DocumentHeaderBlockKeys.icon],
}); });
return editorState.apply(transaction); editorState.apply(transaction);
} }
} }

View File

@ -120,7 +120,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
SizedBox( SizedBox(
height: _calculateOverallHeight(), height: _calculateOverallHeight(),
child: DocumentHeaderToolbar( child: DocumentHeaderToolbar(
onCoverChanged: _saveCover, onIconOrCoverChanged: _saveIconOrCover,
node: widget.node, node: widget.node,
editorState: widget.editorState, editorState: widget.editorState,
hasCover: hasCover, hasCover: hasCover,
@ -133,8 +133,8 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
node: widget.node, node: widget.node,
coverType: coverType, coverType: coverType,
coverDetails: coverDetails, coverDetails: coverDetails,
onCoverChanged: (type, details) => onChangeCover: (type, details) =>
_saveCover(cover: (type, details)), _saveIconOrCover(cover: (type, details)),
), ),
if (hasIcon) if (hasIcon)
Positioned( Positioned(
@ -147,9 +147,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
editorState: widget.editorState, editorState: widget.editorState,
node: widget.node, node: widget.node,
icon: viewIcon, icon: viewIcon,
onIconChanged: (icon) async { onChangeIcon: (icon) => _saveIconOrCover(icon: icon),
_saveCover(icon: icon);
},
), ),
), ),
], ],
@ -169,7 +167,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
} }
} }
Future<void> _saveCover({(CoverType, String?)? cover, String? icon}) async { void _saveIconOrCover({(CoverType, String?)? cover, String? icon}) async {
final transaction = widget.editorState.transaction; final transaction = widget.editorState.transaction;
final coverType = widget.node.attributes[DocumentHeaderBlockKeys.coverType]; final coverType = widget.node.attributes[DocumentHeaderBlockKeys.coverType];
final coverDetails = final coverDetails =
@ -190,7 +188,7 @@ class _DocumentHeaderNodeWidgetState extends State<DocumentHeaderNodeWidget> {
} }
transaction.updateNode(widget.node, attributes); transaction.updateNode(widget.node, attributes);
return widget.editorState.apply(transaction); await widget.editorState.apply(transaction);
} }
} }
@ -202,15 +200,15 @@ class DocumentHeaderToolbar extends StatefulWidget {
required this.editorState, required this.editorState,
required this.hasCover, required this.hasCover,
required this.hasIcon, required this.hasIcon,
required this.onCoverChanged, required this.onIconOrCoverChanged,
}); });
final Node node; final Node node;
final EditorState editorState; final EditorState editorState;
final bool hasCover; final bool hasCover;
final bool hasIcon; final bool hasIcon;
final Future<void> Function({(CoverType, String?)? cover, String? icon}) final void Function({(CoverType, String?)? cover, String? icon})
onCoverChanged; onIconOrCoverChanged;
@override @override
State<DocumentHeaderToolbar> createState() => _DocumentHeaderToolbarState(); State<DocumentHeaderToolbar> createState() => _DocumentHeaderToolbarState();
@ -276,7 +274,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
children.add( children.add(
FlowyButton( FlowyButton(
leftIconSize: const Size.square(18), leftIconSize: const Size.square(18),
onTap: () => widget.onCoverChanged( onTap: () => widget.onIconOrCoverChanged(
cover: PlatformExtension.isDesktopOrWeb cover: PlatformExtension.isDesktopOrWeb
? (CoverType.asset, builtInAssetImages.first) ? (CoverType.asset, builtInAssetImages.first)
: (CoverType.color, '0xffe8e0ff'), : (CoverType.color, '0xffe8e0ff'),
@ -294,7 +292,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
children.add( children.add(
FlowyButton( FlowyButton(
leftIconSize: const Size.square(18), leftIconSize: const Size.square(18),
onTap: () => widget.onCoverChanged(icon: ""), onTap: () => widget.onIconOrCoverChanged(icon: ""),
useIntrinsicWidth: true, useIntrinsicWidth: true,
leftIcon: const Icon( leftIcon: const Icon(
Icons.emoji_emotions_outlined, Icons.emoji_emotions_outlined,
@ -323,7 +321,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
MobileEmojiPickerScreen.routeName, MobileEmojiPickerScreen.routeName,
); );
if (result != null) { if (result != null) {
widget.onCoverChanged(icon: result.emoji); widget.onIconOrCoverChanged(icon: result.emoji);
} }
}, },
); );
@ -340,7 +338,7 @@ class _DocumentHeaderToolbarState extends State<DocumentHeaderToolbar> {
isPopoverOpen = true; isPopoverOpen = true;
return FlowyIconPicker( return FlowyIconPicker(
onSelected: (result) { onSelected: (result) {
widget.onCoverChanged(icon: result.emoji); widget.onIconOrCoverChanged(icon: result.emoji);
_popoverController.close(); _popoverController.close();
}, },
); );
@ -370,14 +368,14 @@ class DocumentCover extends StatefulWidget {
required this.editorState, required this.editorState,
required this.coverType, required this.coverType,
this.coverDetails, this.coverDetails,
required this.onCoverChanged, required this.onChangeCover,
}); });
final Node node; final Node node;
final EditorState editorState; final EditorState editorState;
final CoverType coverType; final CoverType coverType;
final String? coverDetails; final String? coverDetails;
final Future<void> Function(CoverType type, String? details) onCoverChanged; final void Function(CoverType type, String? details) onChangeCover;
@override @override
State<DocumentCover> createState() => DocumentCoverState(); State<DocumentCover> createState() => DocumentCoverState();
@ -459,18 +457,18 @@ class DocumentCoverState extends State<DocumentCover> {
], ],
onSelectedLocalImage: (path) async { onSelectedLocalImage: (path) async {
context.pop(); context.pop();
widget.onCoverChanged(CoverType.file, path); widget.onChangeCover(CoverType.file, path);
}, },
onSelectedAIImage: (_) { onSelectedAIImage: (_) {
throw UnimplementedError(); throw UnimplementedError();
}, },
onSelectedNetworkImage: (url) async { onSelectedNetworkImage: (url) async {
context.pop(); context.pop();
widget.onCoverChanged(CoverType.file, url); widget.onChangeCover(CoverType.file, url);
}, },
onSelectedColor: (color) { onSelectedColor: (color) {
context.pop(); context.pop();
widget.onCoverChanged(CoverType.color, color); widget.onChangeCover(CoverType.color, color);
}, },
), ),
), ),
@ -490,7 +488,7 @@ class DocumentCoverState extends State<DocumentCover> {
SizedBox.square( SizedBox.square(
dimension: 32.0, dimension: 32.0,
child: DeleteCoverButton( child: DeleteCoverButton(
onTap: () => widget.onCoverChanged(CoverType.none, null), onTap: () => widget.onChangeCover(CoverType.none, null),
), ),
), ),
], ],
@ -521,7 +519,7 @@ class DocumentCoverState extends State<DocumentCover> {
final imageFile = File(detail); final imageFile = File(detail);
if (!imageFile.existsSync()) { if (!imageFile.existsSync()) {
WidgetsBinding.instance.addPostFrameCallback((_) { WidgetsBinding.instance.addPostFrameCallback((_) {
widget.onCoverChanged(CoverType.none, null); widget.onChangeCover(CoverType.none, null);
}); });
return const SizedBox.shrink(); return const SizedBox.shrink();
} }
@ -582,14 +580,14 @@ class DocumentCoverState extends State<DocumentCover> {
UploadImageType.url, UploadImageType.url,
UploadImageType.unsplash, UploadImageType.unsplash,
], ],
onSelectedLocalImage: (path) async { onSelectedLocalImage: (path) {
popoverController.close(); popoverController.close();
onCoverChanged(CoverType.file, path); onCoverChanged(CoverType.file, path);
}, },
onSelectedAIImage: (_) { onSelectedAIImage: (_) {
throw UnimplementedError(); throw UnimplementedError();
}, },
onSelectedNetworkImage: (url) async { onSelectedNetworkImage: (url) {
popoverController.close(); popoverController.close();
onCoverChanged(CoverType.file, url); onCoverChanged(CoverType.file, url);
}, },
@ -620,7 +618,7 @@ class DocumentCoverState extends State<DocumentCover> {
details = await saveImageToCloudStorage(details); details = await saveImageToCloudStorage(details);
} }
} }
widget.onCoverChanged(type, details); widget.onChangeCover(type, details);
} }
void setOverlayButtonsHidden(bool value) { void setOverlayButtonsHidden(bool value) {
@ -666,13 +664,13 @@ class DocumentIcon extends StatefulWidget {
required this.node, required this.node,
required this.editorState, required this.editorState,
required this.icon, required this.icon,
required this.onIconChanged, required this.onChangeIcon,
}); });
final Node node; final Node node;
final EditorState editorState; final EditorState editorState;
final String icon; final String icon;
final Future<void> Function(String icon) onIconChanged; final void Function(String icon) onChangeIcon;
@override @override
State<DocumentIcon> createState() => _DocumentIconState(); State<DocumentIcon> createState() => _DocumentIconState();
@ -697,7 +695,7 @@ class _DocumentIconState extends State<DocumentIcon> {
popupBuilder: (BuildContext popoverContext) { popupBuilder: (BuildContext popoverContext) {
return FlowyIconPicker( return FlowyIconPicker(
onSelected: (result) { onSelected: (result) {
widget.onIconChanged(result.emoji); widget.onChangeIcon(result.emoji);
_popoverController.close(); _popoverController.close();
}, },
); );
@ -711,7 +709,7 @@ class _DocumentIconState extends State<DocumentIcon> {
MobileEmojiPickerScreen.routeName, MobileEmojiPickerScreen.routeName,
); );
if (result != null) { if (result != null) {
widget.onIconChanged(result.emoji); widget.onChangeIcon(result.emoji);
} }
}, },
); );

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_item/utils.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_menu_item.dart';
@ -138,6 +140,7 @@ class BlockItems extends StatelessWidget {
_closeKeyboard(selection); _closeKeyboard(selection);
// keep the selection // keep the selection
unawaited(
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
selection, selection,
extraInfo: { extraInfo: {
@ -145,6 +148,7 @@ class BlockItems extends StatelessWidget {
selectionExtraInfoDoNotAttachTextService: true, selectionExtraInfoDoNotAttachTextService: true,
selectionExtraInfoDisableFloatingToolbar: true, selectionExtraInfoDisableFloatingToolbar: true,
}, },
),
); );
keepEditorFocusNotifier.increase(); keepEditorFocusNotifier.increase();
@ -173,9 +177,11 @@ class BlockItems extends StatelessWidget {
}, },
); );
// re-open the keyboard again // re-open the keyboard again
unawaited(
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
selection, selection,
extraInfo: {}, extraInfo: {},
),
); );
} }
} }

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_color_list.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
@ -22,6 +24,7 @@ class ColorItem extends StatelessWidget {
size: const Size(82, 52), size: const Size(82, 52),
onTap: () async { onTap: () async {
service.closeKeyboard(); service.closeKeyboard();
unawaited(
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
editorState.selection, editorState.selection,
extraInfo: { extraInfo: {
@ -29,6 +32,7 @@ class ColorItem extends StatelessWidget {
selectionExtraInfoDisableFloatingToolbar: true, selectionExtraInfoDisableFloatingToolbar: true,
selectionExtraInfoDoNotAttachTextService: true, selectionExtraInfoDoNotAttachTextService: true,
}, },
),
); );
keepEditorFocusNotifier.increase(); keepEditorFocusNotifier.increase();
await showTextColorAndBackgroundColorPicker( await showTextColorAndBackgroundColorPicker(

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart'; import 'package:appflowy/mobile/presentation/setting/font/font_picker_screen.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/_toolbar_theme.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart';
@ -30,12 +32,14 @@ class FontFamilyItem extends StatelessWidget {
onTap: () async { onTap: () async {
final selection = editorState.selection; final selection = editorState.selection;
// disable the floating toolbar // disable the floating toolbar
unawaited(
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
selection, selection,
extraInfo: { extraInfo: {
selectionExtraInfoDisableFloatingToolbar: true, selectionExtraInfoDisableFloatingToolbar: true,
selectionExtraInfoDisableMobileToolbarKey: true, selectionExtraInfoDisableMobileToolbarKey: true,
}, },
),
); );
final newFont = await context final newFont = await context

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/mobile_toolbar_v3/util.dart';
import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:appflowy_editor/appflowy_editor.dart';
@ -93,12 +95,14 @@ class _HeadingOrTextItem extends StatelessWidget {
selectionExtraInfoDisableFloatingToolbar: true, selectionExtraInfoDisableFloatingToolbar: true,
}, },
); );
await editorState.updateSelectionWithReason( unawaited(
editorState.updateSelectionWithReason(
editorState.selection, editorState.selection,
extraInfo: { extraInfo: {
selectionExtraInfoDisableFloatingToolbar: true, selectionExtraInfoDisableFloatingToolbar: true,
selectionExtraInfoDoNotAttachTextService: true, selectionExtraInfoDoNotAttachTextService: true,
}, },
),
); );
} }
} }

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart';
import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart';
import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart'; import 'package:appflowy/mobile/presentation/bottom_sheet/bottom_sheet.dart';
@ -23,6 +25,7 @@ final addBlockToolbarItem = AppFlowyMobileToolbarItem(
// delay to wait the keyboard closed. // delay to wait the keyboard closed.
Future.delayed(const Duration(milliseconds: 100), () async { Future.delayed(const Duration(milliseconds: 100), () async {
unawaited(
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
selection, selection,
extraInfo: { extraInfo: {
@ -30,6 +33,7 @@ final addBlockToolbarItem = AppFlowyMobileToolbarItem(
selectionExtraInfoDisableFloatingToolbar: true, selectionExtraInfoDisableFloatingToolbar: true,
selectionExtraInfoDoNotAttachTextService: true, selectionExtraInfoDoNotAttachTextService: true,
}, },
),
); );
keepEditorFocusNotifier.increase(); keepEditorFocusNotifier.increase();
final didAddBlock = await showAddBlockMenu( final didAddBlock = await showAddBlockMenu(
@ -38,8 +42,10 @@ final addBlockToolbarItem = AppFlowyMobileToolbarItem(
selection: selection!, selection: selection!,
); );
if (didAddBlock != true) { if (didAddBlock != true) {
unawaited(
editorState.updateSelectionWithReason( editorState.updateSelectionWithReason(
selection, selection,
),
); );
} }
}); });

View File

@ -190,14 +190,14 @@ class _AutoCompletionBlockComponentState
Future<void> _onGenerate() async { Future<void> _onGenerate() async {
final loading = Loading(context); final loading = Loading(context);
loading.start(); await loading.start();
await _updateEditingText(); await _updateEditingText();
final userProfile = await UserBackendService.getCurrentUserProfile() final userProfile = await UserBackendService.getCurrentUserProfile()
.then((value) => value.toOption().toNullable()); .then((value) => value.toOption().toNullable());
if (userProfile == null) { if (userProfile == null) {
loading.stop(); await loading.stop();
if (mounted) { if (mounted) {
showSnackBarMessage( showSnackBarMessage(
context, context,
@ -217,10 +217,12 @@ class _AutoCompletionBlockComponentState
await openAIRepository.getStreamedCompletions( await openAIRepository.getStreamedCompletions(
prompt: controller.text, prompt: controller.text,
onStart: () async { onStart: () async {
loading.stop(); await loading.stop();
if (mounted) {
barrierDialog = BarrierDialog(context); barrierDialog = BarrierDialog(context);
barrierDialog?.show(); await barrierDialog?.show();
await _makeSurePreviousNodeIsEmptyParagraphNode(); await _makeSurePreviousNodeIsEmptyParagraphNode();
}
}, },
onProcess: (response) async { onProcess: (response) async {
if (response.choices.isNotEmpty) { if (response.choices.isNotEmpty) {
@ -235,12 +237,14 @@ class _AutoCompletionBlockComponentState
await barrierDialog?.dismiss(); await barrierDialog?.dismiss();
}, },
onError: (error) async { onError: (error) async {
loading.stop(); await loading.stop();
if (mounted) {
showSnackBarMessage( showSnackBarMessage(
context, context,
error.message, error.message,
showCancel: true, showCancel: true,
); );
}
}, },
); );
await _updateGenerationCount(); await _updateGenerationCount();
@ -261,7 +265,7 @@ class _AutoCompletionBlockComponentState
await _makeSurePreviousNodeIsEmptyParagraphNode(); await _makeSurePreviousNodeIsEmptyParagraphNode();
} }
} }
_onExit(); return _onExit();
} }
Future<void> _onRewrite() async { Future<void> _onRewrite() async {
@ -271,7 +275,7 @@ class _AutoCompletionBlockComponentState
} }
final loading = Loading(context); final loading = Loading(context);
loading.start(); await loading.start();
// clear previous response // clear previous response
final selection = startSelection; final selection = startSelection;
if (selection != null) { if (selection != null) {
@ -290,7 +294,7 @@ class _AutoCompletionBlockComponentState
final userProfile = await UserBackendService.getCurrentUserProfile() final userProfile = await UserBackendService.getCurrentUserProfile()
.then((value) => value.toOption().toNullable()); .then((value) => value.toOption().toNullable());
if (userProfile == null) { if (userProfile == null) {
loading.stop(); await loading.stop();
if (mounted) { if (mounted) {
showSnackBarMessage( showSnackBarMessage(
context, context,
@ -308,7 +312,7 @@ class _AutoCompletionBlockComponentState
await openAIRepository.getStreamedCompletions( await openAIRepository.getStreamedCompletions(
prompt: _rewritePrompt(previousOutput), prompt: _rewritePrompt(previousOutput),
onStart: () async { onStart: () async {
loading.stop(); await loading.stop();
await _makeSurePreviousNodeIsEmptyParagraphNode(); await _makeSurePreviousNodeIsEmptyParagraphNode();
}, },
onProcess: (response) async { onProcess: (response) async {
@ -322,12 +326,14 @@ class _AutoCompletionBlockComponentState
}, },
onEnd: () async {}, onEnd: () async {},
onError: (error) async { onError: (error) async {
loading.stop(); await loading.stop();
if (mounted) {
showSnackBarMessage( showSnackBarMessage(
context, context,
error.message, error.message,
showCancel: true, showCancel: true,
); );
}
}, },
); );
await _updateGenerationCount(); await _updateGenerationCount();

View File

@ -128,7 +128,7 @@ class _SmartEditBlockComponentWidgetState
if (state.result.isEmpty) { if (state.result.isEmpty) {
completer.complete(true); completer.complete(true);
} else { } else {
showDialog( await showDialog(
context: context, context: context,
builder: (context) { builder: (context) {
return DiscardDialog( return DiscardDialog(

View File

@ -1,3 +1,5 @@
import 'dart:async';
import 'package:appflowy/core/config/kv_keys.dart'; import 'package:appflowy/core/config/kv_keys.dart';
import 'package:appflowy/util/color_to_hex_string.dart'; import 'package:appflowy/util/color_to_hex_string.dart';
import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart'; import 'package:appflowy/workspace/application/settings/appearance/base_appearance.dart';
@ -96,49 +98,34 @@ class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
Future<void> syncFontSize(double fontSize) async { Future<void> syncFontSize(double fontSize) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
prefs.setDouble(KVKeys.kDocumentAppearanceFontSize, fontSize); await prefs.setDouble(KVKeys.kDocumentAppearanceFontSize, fontSize);
if (isClosed) { if (!isClosed) {
return; emit(state.copyWith(fontSize: fontSize));
} }
emit(
state.copyWith(
fontSize: fontSize,
),
);
} }
Future<void> syncFontFamily(String fontFamily) async { Future<void> syncFontFamily(String fontFamily) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
prefs.setString(KVKeys.kDocumentAppearanceFontFamily, fontFamily); await prefs.setString(KVKeys.kDocumentAppearanceFontFamily, fontFamily);
if (isClosed) { if (!isClosed) {
return; emit(state.copyWith(fontFamily: fontFamily));
} }
emit(
state.copyWith(
fontFamily: fontFamily,
),
);
} }
Future<void> syncDefaultTextDirection(String? direction) async { Future<void> syncDefaultTextDirection(String? direction) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
if (direction == null) { if (direction == null) {
prefs.remove(KVKeys.kDocumentAppearanceDefaultTextDirection); await prefs.remove(KVKeys.kDocumentAppearanceDefaultTextDirection);
} else { } else {
prefs.setString( await prefs.setString(
KVKeys.kDocumentAppearanceDefaultTextDirection, KVKeys.kDocumentAppearanceDefaultTextDirection,
direction, direction,
); );
} }
if (isClosed) { if (!isClosed) {
return;
}
emit( emit(
state.copyWith( state.copyWith(
defaultTextDirection: direction, defaultTextDirection: direction,
@ -146,23 +133,21 @@ class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
), ),
); );
} }
}
Future<void> syncCursorColor(Color? cursorColor) async { Future<void> syncCursorColor(Color? cursorColor) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
if (cursorColor == null) { if (cursorColor == null) {
prefs.remove(KVKeys.kDocumentAppearanceCursorColor); await prefs.remove(KVKeys.kDocumentAppearanceCursorColor);
} else { } else {
prefs.setString( await prefs.setString(
KVKeys.kDocumentAppearanceCursorColor, KVKeys.kDocumentAppearanceCursorColor,
cursorColor.toHexString(), cursorColor.toHexString(),
); );
} }
if (isClosed) { if (!isClosed) {
return;
}
emit( emit(
state.copyWith( state.copyWith(
cursorColor: cursorColor, cursorColor: cursorColor,
@ -170,23 +155,21 @@ class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
), ),
); );
} }
}
Future<void> syncSelectionColor(Color? selectionColor) async { Future<void> syncSelectionColor(Color? selectionColor) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
if (selectionColor == null) { if (selectionColor == null) {
prefs.remove(KVKeys.kDocumentAppearanceSelectionColor); await prefs.remove(KVKeys.kDocumentAppearanceSelectionColor);
} else { } else {
prefs.setString( await prefs.setString(
KVKeys.kDocumentAppearanceSelectionColor, KVKeys.kDocumentAppearanceSelectionColor,
selectionColor.toHexString(), selectionColor.toHexString(),
); );
} }
if (isClosed) { if (!isClosed) {
return;
}
emit( emit(
state.copyWith( state.copyWith(
selectionColor: selectionColor, selectionColor: selectionColor,
@ -195,3 +178,4 @@ class DocumentAppearanceCubit extends Cubit<DocumentAppearance> {
); );
} }
} }
}

View File

@ -171,7 +171,7 @@ class InlinePageReferenceService {
await editorState.insertReferencePage(view, view.layout); await editorState.insertReferencePage(view, view.layout);
} on FlowyError catch (e) { } on FlowyError catch (e) {
if (context.mounted) { if (context.mounted) {
Dialogs.show( return Dialogs.show(
context, context,
child: FlowyErrorPage.message( child: FlowyErrorPage.message(
e.msg, e.msg,

View File

@ -84,8 +84,13 @@ class AppFlowyCloudDeepLink {
Uri? uri, Uri? uri,
) async { ) async {
_stateNotifier?.value = DeepLinkResult(state: DeepLinkState.none); _stateNotifier?.value = DeepLinkResult(state: DeepLinkState.none);
if (uri != null) {
_isAuthCallbackDeeplink(uri).fold( if (uri == null) {
Log.error('onDeepLinkError: Unexpect empty deep link callback');
_completer?.complete(left(AuthError.emptyDeeplink));
_completer = null;
}
return _isAuthCallbackDeeplink(uri!).fold(
(_) async { (_) async {
final deviceId = await getDeviceId(); final deviceId = await getDeviceId();
final payload = OauthSignInPB( final payload = OauthSignInPB(
@ -106,7 +111,7 @@ class AppFlowyCloudDeepLink {
); );
// If there is no completer, runAppFlowy() will be called. // If there is no completer, runAppFlowy() will be called.
if (_completer == null) { if (_completer == null) {
result.fold( await result.fold(
(err) { (err) {
Log.error(err); Log.error(err);
final context = AppGlobals.rootNavKey.currentState?.context; final context = AppGlobals.rootNavKey.currentState?.context;
@ -142,11 +147,6 @@ class AppFlowyCloudDeepLink {
} }
}, },
); );
} else {
Log.error('onDeepLinkError: Unexpect empty deep link callback');
_completer?.complete(left(AuthError.emptyDeeplink));
_completer = null;
}
} }
Either<(), FlowyError> _isAuthCallbackDeeplink(Uri uri) { Either<(), FlowyError> _isAuthCallbackDeeplink(Uri uri) {

View File

@ -11,7 +11,7 @@ class DebugTask extends LaunchTask {
Future<void> initialize(LaunchContext context) async { Future<void> initialize(LaunchContext context) async {
// the hotkey manager is not supported on mobile // the hotkey manager is not supported on mobile
if (PlatformExtension.isMobile && kDebugMode) { if (PlatformExtension.isMobile && kDebugMode) {
SystemChannels.textInput.invokeMethod('TextInput.hide'); await SystemChannels.textInput.invokeMethod('TextInput.hide');
} }
} }

View File

@ -9,7 +9,7 @@ class InitPlatformServiceTask extends LaunchTask {
@override @override
Future<void> initialize(LaunchContext context) async { Future<void> initialize(LaunchContext context) async {
getIt<NetworkListener>().start(); return getIt<NetworkListener>().start();
} }
@override @override

View File

@ -69,7 +69,7 @@ Future<Directory> appFlowyApplicationDataDirectory() async {
switch (integrationMode()) { switch (integrationMode()) {
case IntegrationMode.develop: case IntegrationMode.develop:
final Directory documentsDir = await getApplicationSupportDirectory() final Directory documentsDir = await getApplicationSupportDirectory()
..create(); .then((directory) => directory.create());
return Directory(path.join(documentsDir.path, 'data_dev')).create(); return Directory(path.join(documentsDir.path, 'data_dev')).create();
case IntegrationMode.release: case IntegrationMode.release:
final Directory documentsDir = await getApplicationSupportDirectory(); final Directory documentsDir = await getApplicationSupportDirectory();

View File

@ -37,7 +37,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
title: title, title: title,
); );
windowManager.waitUntilReadyToShow(windowOptions, () async { await windowManager.waitUntilReadyToShow(windowOptions, () async {
await windowManager.show(); await windowManager.show();
await windowManager.focus(); await windowManager.focus();
@ -53,7 +53,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
super.onWindowResize(); super.onWindowResize();
final currentWindowSize = await windowManager.getSize(); final currentWindowSize = await windowManager.getSize();
WindowSizeManager().setSize(currentWindowSize); return WindowSizeManager().setSize(currentWindowSize);
} }
@override @override
@ -61,7 +61,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
super.onWindowMaximize(); super.onWindowMaximize();
final currentWindowSize = await windowManager.getSize(); final currentWindowSize = await windowManager.getSize();
WindowSizeManager().setSize(currentWindowSize); return WindowSizeManager().setSize(currentWindowSize);
} }
@override @override
@ -69,7 +69,7 @@ class InitAppWindowTask extends LaunchTask with WindowListener {
super.onWindowMoved(); super.onWindowMoved();
final position = await windowManager.getPosition(); final position = await windowManager.getPosition();
WindowSizeManager().setPosition(position); return WindowSizeManager().setPosition(position);
} }
@override @override

View File

@ -228,7 +228,7 @@ Completer<Either<FlowyError, UserProfilePB>> supabaseLoginCompleter({
user.email ?? user.newEmail ?? '', user.email ?? user.newEmail ?? '',
); );
// Only cancel the subscription if the Event is signedIn. // Only cancel the subscription if the Event is signedIn.
subscription.cancel(); await subscription.cancel();
completer.complete(response); completer.complete(response);
} }
}); });

View File

@ -32,11 +32,10 @@ class EncryptSecretBloc extends Bloc<EncryptSecretEvent, EncryptSecretState> {
..encryptionSign = user.encryptionSign ..encryptionSign = user.encryptionSign
..encryptionType = user.encryptionType ..encryptionType = user.encryptionType
..userId = user.id; ..userId = user.id;
UserEventSetEncryptionSecret(payload).send().then((result) { final result = await UserEventSetEncryptionSecret(payload).send();
if (!isClosed) { if (!isClosed) {
add(EncryptSecretEvent.didFinishCheck(result)); add(EncryptSecretEvent.didFinishCheck(result));
} }
});
emit( emit(
state.copyWith( state.copyWith(
loadingState: const LoadingState.loading(), loadingState: const LoadingState.loading(),

View File

@ -27,7 +27,7 @@ class SupabaseRealtimeService {
}, },
onInvalidAuth: (message) async { onInvalidAuth: (message) async {
Log.error(message); Log.error(message);
channel?.unsubscribe(); await channel?.unsubscribe();
channel = null; channel = null;
if (!isLoggingOut) { if (!isLoggingOut) {
isLoggingOut = true; isLoggingOut = true;

View File

@ -31,14 +31,10 @@ class WorkspaceErrorBloc
final payload = ResetWorkspacePB.create() final payload = ResetWorkspacePB.create()
..workspaceId = userFolder.workspaceId ..workspaceId = userFolder.workspaceId
..uid = userFolder.uid; ..uid = userFolder.uid;
UserEventResetWorkspace(payload).send().then( final result = await UserEventResetWorkspace(payload).send();
(result) { if (!isClosed) {
if (isClosed) {
return;
}
add(WorkspaceErrorEvent.didResetWorkspace(result)); add(WorkspaceErrorEvent.didResetWorkspace(result));
}, }
);
}, },
didResetWorkspace: (result) { didResetWorkspace: (result) {
result.fold( result.fold(

View File

@ -61,10 +61,10 @@ class AuthRouter {
); );
} }
Future<void> pushEncryptionScreen( void pushEncryptionScreen(
BuildContext context, BuildContext context,
UserProfilePB userProfile, UserProfilePB userProfile,
) async { ) {
// After log in,push EncryptionScreen on the top SignInScreen // After log in,push EncryptionScreen on the top SignInScreen
context.push( context.push(
EncryptSecretScreen.routeName, EncryptSecretScreen.routeName,
@ -104,12 +104,11 @@ class SplashRouter {
}, },
); );
FolderEventGetCurrentWorkspaceSetting().send().then((result) { final result = await FolderEventGetCurrentWorkspaceSetting().send();
result.fold( result.fold(
(workspaceSettingPB) => pushHomeScreen(context), (workspaceSettingPB) => pushHomeScreen(context),
(r) => null, (r) => null,
); );
});
} }
void pushHomeScreen( void pushHomeScreen(

View File

@ -102,7 +102,7 @@ class MobileSignInScreen extends StatelessWidget {
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
), ),
onTap: () async { onTap: () {
context.push(MobileLaunchSettingsPage.routeName); context.push(MobileLaunchSettingsPage.routeName);
}, },
); );

View File

@ -68,7 +68,7 @@ class SplashScreen extends StatelessWidget {
/// After a user is authenticated, this function checks if encryption is required. /// After a user is authenticated, this function checks if encryption is required.
final result = await UserEventCheckEncryptionSign().send(); final result = await UserEventCheckEncryptionSign().send();
result.fold( await result.fold(
(check) async { (check) async {
/// If encryption is needed, the user is navigated to the encryption screen. /// If encryption is needed, the user is navigated to the encryption screen.
/// Otherwise, it fetches the current workspace for the user and navigates them /// Otherwise, it fetches the current workspace for the user and navigates them

View File

@ -28,7 +28,7 @@ class MenuUserBloc extends Bloc<MenuUserEvent, MenuUserState> {
Future<void> close() async { Future<void> close() async {
await _userListener.stop(); await _userListener.stop();
await _userWorkspaceListener.stop(); await _userWorkspaceListener.stop();
super.close(); return super.close();
} }
void _dispatch() { void _dispatch() {

View File

@ -68,7 +68,7 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
/// with the AppTheme named [themeName]. /// with the AppTheme named [themeName].
Future<void> setTheme(String themeName) async { Future<void> setTheme(String themeName) async {
_appearanceSettings.theme = themeName; _appearanceSettings.theme = themeName;
_saveAppearanceSettings(); unawaited(_saveAppearanceSettings());
emit(state.copyWith(appTheme: await AppTheme.fromName(themeName))); emit(state.copyWith(appTheme: await AppTheme.fromName(themeName)));
} }
@ -236,25 +236,21 @@ class AppearanceSettingsCubit extends Cubit<AppearanceSettingsState> {
} }
Future<void> _saveDateTimeSettings() async { Future<void> _saveDateTimeSettings() async {
UserSettingsBackendService() final result = await UserSettingsBackendService()
.setDateTimeSettings(_dateTimeSettings) .setDateTimeSettings(_dateTimeSettings);
.then((result) {
result.fold( result.fold(
(error) => Log.error(error), (error) => Log.error(error),
(_) => null, (_) => null,
); );
});
} }
Future<void> _saveAppearanceSettings() async { Future<void> _saveAppearanceSettings() async {
UserSettingsBackendService() final result = await UserSettingsBackendService()
.setAppearanceSetting(_appearanceSettings) .setAppearanceSetting(_appearanceSettings);
.then((result) {
result.fold( result.fold(
(l) => null, (l) => null,
(error) => Log.error(error), (error) => Log.error(error),
); );
});
} }
} }

View File

@ -22,7 +22,7 @@ class AppFlowyCloudSettingBloc
@override @override
Future<void> close() async { Future<void> close() async {
_listener.stop(); await _listener.stop();
return super.close(); return super.close();
} }

View File

@ -44,7 +44,7 @@ class ApplicationDataStorage {
await directory.create(recursive: true); await directory.create(recursive: true);
} }
setPath(path); await setPath(path);
} }
Future<void> setPath(String path) async { Future<void> setPath(String path) async {

View File

@ -38,20 +38,18 @@ class NotificationSettingsCubit extends Cubit<NotificationSettingsState> {
), ),
); );
_saveNotificationSettings(); await _saveNotificationSettings();
} }
Future<void> _saveNotificationSettings() async { Future<void> _saveNotificationSettings() async {
await _initCompleter.future; await _initCompleter.future;
UserSettingsBackendService() final result = await UserSettingsBackendService()
.setNotificationSettings(_notificationSettings) .setNotificationSettings(_notificationSettings);
.then((result) {
result.fold( result.fold(
(error) => Log.error(error), (error) => Log.error(error),
(r) => null, (r) => null,
); );
});
} }
} }

View File

@ -25,11 +25,11 @@ class SettingFileImportBloc
emit( emit(
state.copyWith(loadingState: const LoadingState.loading()), state.copyWith(loadingState: const LoadingState.loading()),
); );
UserEventImportAppFlowyDataFolder(payload).send().then((result) { final result =
await UserEventImportAppFlowyDataFolder(payload).send();
if (!isClosed) { if (!isClosed) {
add(SettingFileImportEvent.finishImport(result)); add(SettingFileImportEvent.finishImport(result));
} }
});
}, },
finishImport: (result) { finishImport: (result) {
result.fold( result.fold(

View File

@ -32,7 +32,7 @@ class SettingsDialogBloc
@override @override
Future<void> close() async { Future<void> close() async {
await _userListener.stop(); await _userListener.stop();
super.close(); await super.close();
} }
void _dispatch() { void _dispatch() {

View File

@ -26,7 +26,7 @@ class SupabaseCloudSettingBloc
@override @override
Future<void> close() async { Future<void> close() async {
_listener.stop(); await _listener.stop();
return super.close(); return super.close();
} }
@ -50,7 +50,7 @@ class SupabaseCloudSettingBloc
}, },
enableSync: (bool enable) async { enableSync: (bool enable) async {
final update = UpdateCloudConfigPB.create()..enableSync = enable; final update = UpdateCloudConfigPB.create()..enableSync = enable;
updateCloudConfig(update); await updateCloudConfig(update);
}, },
didReceiveSetting: (CloudSettingPB setting) { didReceiveSetting: (CloudSettingPB setting) {
emit( emit(

View File

@ -24,7 +24,7 @@ class SettingsUserViewBloc extends Bloc<SettingsUserEvent, SettingsUserState> {
@override @override
Future<void> close() async { Future<void> close() async {
await _userListener.stop(); await _userListener.stop();
super.close(); return super.close();
} }
void _dispatch() { void _dispatch() {

View File

@ -134,7 +134,7 @@ class ViewBloc extends Bloc<ViewEvent, ViewState> {
(error) => state.copyWith(successOrFailure: right(error)), (error) => state.copyWith(successOrFailure: right(error)),
), ),
); );
RecentService().updateRecentViews([view.id], false); await RecentService().updateRecentViews([view.id], false);
}, },
duplicate: (e) async { duplicate: (e) async {
final result = await ViewBackendService.duplicate(view: view); final result = await ViewBackendService.duplicate(view: view);

View File

@ -23,7 +23,7 @@ Future<void> createViewAndShowRenameDialogIfNeeded(
); );
final showRenameDialog = value.fold(() => false, (r) => r); final showRenameDialog = value.fold(() => false, (r) => r);
if (context.mounted && showRenameDialog) { if (context.mounted && showRenameDialog) {
NavigatorTextFieldDialog( await NavigatorTextFieldDialog(
title: dialogTitle, title: dialogTitle,
value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), value: LocaleKeys.menuAppHeader_defaultNewPageName.tr(),
autoSelectAllText: true, autoSelectAllText: true,

View File

@ -301,7 +301,7 @@ class EmojiPickerState extends State<EmojiPicker> {
) async { ) async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
final emojiJson = jsonEncode(emojis); final emojiJson = jsonEncode(emojis);
prefs.setString(title, emojiJson); await prefs.setString(title, emojiJson);
} }
// Returns list of recently used emoji from cache // Returns list of recently used emoji from cache
@ -335,6 +335,6 @@ class EmojiPickerState extends State<EmojiPicker> {
min(widget.config.recentsLimit, recentEmojiList.length), min(widget.config.recentsLimit, recentEmojiList.length),
); );
// save locally // save locally
prefs.setString('recent', jsonEncode(recentEmojiList)); await prefs.setString('recent', jsonEncode(recentEmojiList));
} }
} }

View File

@ -63,7 +63,7 @@ class AppFlowyCloudViewSetting extends StatelessWidget {
const AppFlowyCloudEnableSync(), const AppFlowyCloudEnableSync(),
const VSpace(12), const VSpace(12),
RestartButton( RestartButton(
onClick: () async { onClick: () {
NavigatorAlertDialog( NavigatorAlertDialog(
title: LocaleKeys.settings_menu_restartAppTip.tr(), title: LocaleKeys.settings_menu_restartAppTip.tr(),
confirm: () async { confirm: () async {
@ -176,7 +176,7 @@ class AppFlowyCloudURLs extends StatelessWidget {
), ),
const VSpace(8), const VSpace(8),
RestartButton( RestartButton(
onClick: () async { onClick: () {
NavigatorAlertDialog( NavigatorAlertDialog(
title: LocaleKeys.settings_menu_restartAppTip.tr(), title: LocaleKeys.settings_menu_restartAppTip.tr(),
confirm: () { confirm: () {

View File

@ -235,7 +235,7 @@ class _OpenStorageButton extends StatelessWidget {
onPressed: () async { onPressed: () async {
final uri = Directory(usingPath).uri; final uri = Directory(usingPath).uri;
if (await canLaunchUrl(uri)) { if (await canLaunchUrl(uri)) {
launchUrl(uri); await launchUrl(uri);
} }
}, },
); );

View File

@ -534,7 +534,7 @@ class SettingLogoutButton extends StatelessWidget {
fontSize: 13, fontSize: 13,
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
onTap: () async { onTap: () {
NavigatorAlertDialog( NavigatorAlertDialog(
title: logoutPromptMessage(), title: logoutPromptMessage(),
confirm: () async { confirm: () async {

View File

@ -34,7 +34,7 @@ class ThemeUploadLearnMoreButton extends StatelessWidget {
await launchUrl(uri); await launchUrl(uri);
} else { } else {
if (context.mounted) { if (context.mounted) {
Dialogs.show( await Dialogs.show(
context, context,
child: FlowyDialog( child: FlowyDialog(
child: FlowyErrorPage.message( child: FlowyErrorPage.message(

View File

@ -129,10 +129,10 @@ class _BubbleActionListState extends State<BubbleActionList> {
class _DebugToast { class _DebugToast {
void show() async { void show() async {
var debugInfo = ""; String debugInfo = "";
debugInfo += await _getDeviceInfo(); debugInfo += await _getDeviceInfo();
debugInfo += await _getDocumentPath(); debugInfo += await _getDocumentPath();
Clipboard.setData(ClipboardData(text: debugInfo)); await Clipboard.setData(ClipboardData(text: debugInfo));
showMessageToast(LocaleKeys.questionBubble_debug_success.tr()); showMessageToast(LocaleKeys.questionBubble_debug_success.tr());
} }

View File

@ -62,7 +62,7 @@ void main() {
await gridResponseFuture(); await gridResponseFuture();
final textField = context.textFieldContext(); final textField = context.textFieldContext();
service.insertTextFilter( await service.insertTextFilter(
fieldId: textField.id, fieldId: textField.id,
condition: TextFilterConditionPB.TextIsEmpty, condition: TextFilterConditionPB.TextIsEmpty,
content: "", content: "",
@ -94,11 +94,11 @@ void main() {
await gridResponseFuture(); await gridResponseFuture();
final controller = context.makeTextCellController(0); final controller = context.makeTextCellController(0);
controller.saveCellData("edit text cell content"); await controller.saveCellData("edit text cell content");
await gridResponseFuture(); await gridResponseFuture();
assert(gridBloc.state.rowInfos.length == 2); assert(gridBloc.state.rowInfos.length == 2);
controller.saveCellData(""); await controller.saveCellData("");
await gridResponseFuture(); await gridResponseFuture();
assert(gridBloc.state.rowInfos.length == 3); assert(gridBloc.state.rowInfos.length == 3);
}); });

View File

@ -16,7 +16,7 @@ void main() {
final service = FilterBackendService(viewId: context.gridView.id); final service = FilterBackendService(viewId: context.gridView.id);
final controller = context.makeCheckboxCellController(0); final controller = context.makeCheckboxCellController(0);
controller.saveCellData("Yes"); await controller.saveCellData("Yes");
await gridResponseFuture(); await gridResponseFuture();
// create a new filter // create a new filter
@ -37,7 +37,7 @@ void main() {
final service = FilterBackendService(viewId: context.gridView.id); final service = FilterBackendService(viewId: context.gridView.id);
final controller = context.makeCheckboxCellController(0); final controller = context.makeCheckboxCellController(0);
controller.saveCellData("Yes"); await controller.saveCellData("Yes");
await gridResponseFuture(); await gridResponseFuture();
// create a new filter // create a new filter

View File

@ -21,7 +21,6 @@ Future<GridTestContext> createTestFilterGrid(AppFlowyGridTest gridTest) async {
final result = await context.gridController.open(); final result = await context.gridController.open();
await editCells(context); await editCells(context);
await gridResponseFuture(milliseconds: 500);
result.fold((l) => null, (r) => throw Exception(r)); result.fold((l) => null, (r) => throw Exception(r));
return context; return context;
}, },
@ -36,7 +35,8 @@ Future<void> editCells(GridTestContext context) async {
final controller0 = context.makeTextCellController(0); final controller0 = context.makeTextCellController(0);
final controller1 = context.makeTextCellController(1); final controller1 = context.makeTextCellController(1);
controller0.saveCellData('A'); await controller0.saveCellData('A');
await gridResponseFuture();
await controller1.saveCellData('B');
await gridResponseFuture(); await gridResponseFuture();
controller1.saveCellData('B');
} }

View File

@ -117,7 +117,7 @@ void main() {
commandShortcutEvent.updateCommand(command: newCommand); commandShortcutEvent.updateCommand(command: newCommand);
//saving the updated shortcuts //saving the updated shortcuts
service.saveAllShortcuts(currentCommandShortcuts); await service.saveAllShortcuts(currentCommandShortcuts);
//now directly fetching the shortcuts from loadShortcuts //now directly fetching the shortcuts from loadShortcuts
final commandShortcuts = await service.getCustomizeShortcuts(); final commandShortcuts = await service.getCustomizeShortcuts();

View File

@ -1,4 +1,3 @@
import 'package:appflowy/main.dart';
import 'package:appflowy/startup/launch_configuration.dart'; import 'package:appflowy/startup/launch_configuration.dart';
import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/startup.dart';
import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart';
@ -11,18 +10,8 @@ import 'package:flowy_infra/uuid.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
import 'package:integration_test/integration_test.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
class AppFlowyIntegrateTest {
static Future<AppFlowyIntegrateTest> ensureInitialized() async {
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
SharedPreferences.setMockInitialValues({});
main();
return AppFlowyIntegrateTest();
}
}
class AppFlowyUnitTest { class AppFlowyUnitTest {
late UserProfilePB userProfile; late UserProfilePB userProfile;
late UserBackendService userService; late UserBackendService userService;