diff --git a/frontend/appflowy_flutter/integration_test/util/common_operations.dart b/frontend/appflowy_flutter/integration_test/util/common_operations.dart index c1bd100dd0..12b38cf78a 100644 --- a/frontend/appflowy_flutter/integration_test/util/common_operations.dart +++ b/frontend/appflowy_flutter/integration_test/util/common_operations.dart @@ -306,7 +306,7 @@ extension CommonOperations on WidgetTester { KVKeys.showRenameDialogWhenCreatingNewFile, (value) => bool.parse(value), ); - final showRenameDialog = settingsOrFailure.fold(() => false, (r) => r); + final showRenameDialog = settingsOrFailure ?? false; if (showRenameDialog) { await tapOKButton(); } diff --git a/frontend/appflowy_flutter/lib/core/config/kv.dart b/frontend/appflowy_flutter/lib/core/config/kv.dart index 971f9ab246..b7c845b547 100644 --- a/frontend/appflowy_flutter/lib/core/config/kv.dart +++ b/frontend/appflowy_flutter/lib/core/config/kv.dart @@ -1,10 +1,9 @@ -import 'package:dartz/dartz.dart'; import 'package:shared_preferences/shared_preferences.dart'; abstract class KeyValueStorage { Future set(String key, String value); - Future> get(String key); - Future> getWithFormat( + Future get(String key); + Future getWithFormat( String key, T Function(String value) formatter, ); @@ -17,26 +16,26 @@ class DartKeyValue implements KeyValueStorage { SharedPreferences get sharedPreferences => _sharedPreferences!; @override - Future> get(String key) async { + Future get(String key) async { await _initSharedPreferencesIfNeeded(); final value = sharedPreferences.getString(key); if (value != null) { - return Some(value); + return value; } - return none(); + return null; } @override - Future> getWithFormat( + Future getWithFormat( String key, T Function(String value) formatter, ) async { final value = await get(key); - return value.fold( - () => none(), - (s) => Some(formatter(s)), - ); + if (value == null) { + return null; + } + return formatter(value); } @override diff --git a/frontend/appflowy_flutter/lib/core/config/kv_keys.dart b/frontend/appflowy_flutter/lib/core/config/kv_keys.dart index 4c4e4264c5..e4be228133 100644 --- a/frontend/appflowy_flutter/lib/core/config/kv_keys.dart +++ b/frontend/appflowy_flutter/lib/core/config/kv_keys.dart @@ -49,7 +49,7 @@ class KVKeys { static const String kCloudType = 'kCloudType'; static const String kAppflowyCloudBaseURL = 'kAppFlowyCloudBaseURL'; - static const String kSupabaseURL = 'kSupbaseURL'; + static const String kSupabaseURL = 'kSupabaseURL'; static const String kSupabaseAnonKey = 'kSupabaseAnonKey'; /// The key for saving the text scale factor. diff --git a/frontend/appflowy_flutter/lib/core/helpers/helpers.dart b/frontend/appflowy_flutter/lib/core/helpers/helpers.dart index fd832306e8..e325b1a7bb 100644 --- a/frontend/appflowy_flutter/lib/core/helpers/helpers.dart +++ b/frontend/appflowy_flutter/lib/core/helpers/helpers.dart @@ -1,2 +1 @@ export 'target_platform.dart'; -export 'url_validator.dart'; diff --git a/frontend/appflowy_flutter/lib/core/helpers/url_validator.dart b/frontend/appflowy_flutter/lib/core/helpers/url_validator.dart deleted file mode 100644 index bfead5619d..0000000000 --- a/frontend/appflowy_flutter/lib/core/helpers/url_validator.dart +++ /dev/null @@ -1,21 +0,0 @@ -import 'package:dartz/dartz.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; -part 'url_validator.freezed.dart'; - -Either parseValidUrl(String url) { - try { - final uri = Uri.parse(url); - if (uri.scheme.isEmpty || uri.host.isEmpty) { - return left(const UriFailure.invalidSchemeHost()); - } - return right(uri); - } on FormatException { - return left(const UriFailure.invalidUriFormat()); - } -} - -@freezed -class UriFailure with _$UriFailure { - const factory UriFailure.invalidSchemeHost() = _InvalidSchemeHost; - const factory UriFailure.invalidUriFormat() = _InvalidUriFormat; -} diff --git a/frontend/appflowy_flutter/lib/core/notification/document_notification.dart b/frontend/appflowy_flutter/lib/core/notification/document_notification.dart index 584d54cbe2..4dcaf3fa23 100644 --- a/frontend/appflowy_flutter/lib/core/notification/document_notification.dart +++ b/frontend/appflowy_flutter/lib/core/notification/document_notification.dart @@ -3,11 +3,11 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/notification_helper.dart'; import 'package:appflowy_backend/protobuf/flowy-document/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; typedef DocumentNotificationCallback = void Function( DocumentNotification, - Either, + FlowyResult, ); class DocumentNotificationParser diff --git a/frontend/appflowy_flutter/lib/core/notification/folder_notification.dart b/frontend/appflowy_flutter/lib/core/notification/folder_notification.dart index 66db7a966c..46cba8cbfe 100644 --- a/frontend/appflowy_flutter/lib/core/notification/folder_notification.dart +++ b/frontend/appflowy_flutter/lib/core/notification/folder_notification.dart @@ -1,17 +1,18 @@ import 'dart:async'; import 'dart:typed_data'; -import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; -import 'package:dartz/dartz.dart'; + import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'notification_helper.dart'; // Folder typedef FolderNotificationCallback = void Function( FolderNotification, - Either, + FlowyResult, ); class FolderNotificationParser @@ -27,7 +28,7 @@ class FolderNotificationParser typedef FolderNotificationHandler = Function( FolderNotification ty, - Either result, + FlowyResult result, ); class FolderNotificationListener { diff --git a/frontend/appflowy_flutter/lib/core/notification/grid_notification.dart b/frontend/appflowy_flutter/lib/core/notification/grid_notification.dart index 6a0f5d8bcd..4d67f0bbb0 100644 --- a/frontend/appflowy_flutter/lib/core/notification/grid_notification.dart +++ b/frontend/appflowy_flutter/lib/core/notification/grid_notification.dart @@ -1,17 +1,18 @@ import 'dart:async'; import 'dart:typed_data'; -import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; -import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; + import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'notification_helper.dart'; // DatabasePB typedef DatabaseNotificationCallback = void Function( DatabaseNotification, - Either, + FlowyResult, ); class DatabaseNotificationParser @@ -27,7 +28,7 @@ class DatabaseNotificationParser typedef DatabaseNotificationHandler = Function( DatabaseNotification ty, - Either result, + FlowyResult result, ); class DatabaseNotificationListener { diff --git a/frontend/appflowy_flutter/lib/core/notification/notification_helper.dart b/frontend/appflowy_flutter/lib/core/notification/notification_helper.dart index 4bd988b015..e91549641e 100644 --- a/frontend/appflowy_flutter/lib/core/notification/notification_helper.dart +++ b/frontend/appflowy_flutter/lib/core/notification/notification_helper.dart @@ -1,6 +1,7 @@ import 'dart:typed_data'; + import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class NotificationParser { NotificationParser({ @@ -11,7 +12,7 @@ class NotificationParser { }); String? id; - void Function(T, Either) callback; + void Function(T, FlowyResult) callback; E Function(Uint8List) errorParser; T? Function(int) tyParser; @@ -30,10 +31,10 @@ class NotificationParser { if (subject.hasError()) { final bytes = Uint8List.fromList(subject.error); final error = errorParser(bytes); - callback(ty, right(error)); + callback(ty, FlowyResult.failure(error)); } else { final bytes = Uint8List.fromList(subject.payload); - callback(ty, left(bytes)); + callback(ty, FlowyResult.success(bytes)); } } } diff --git a/frontend/appflowy_flutter/lib/core/notification/user_notification.dart b/frontend/appflowy_flutter/lib/core/notification/user_notification.dart index eca76f0eeb..741f26967c 100644 --- a/frontend/appflowy_flutter/lib/core/notification/user_notification.dart +++ b/frontend/appflowy_flutter/lib/core/notification/user_notification.dart @@ -1,17 +1,18 @@ import 'dart:async'; import 'dart:typed_data'; + +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'notification_helper.dart'; // User typedef UserNotificationCallback = void Function( UserNotification, - Either, + FlowyResult, ); class UserNotificationParser @@ -27,7 +28,7 @@ class UserNotificationParser typedef UserNotificationHandler = Function( UserNotification ty, - Either result, + FlowyResult result, ); class UserNotificationListener { diff --git a/frontend/appflowy_flutter/lib/date/date_service.dart b/frontend/appflowy_flutter/lib/date/date_service.dart index bfd5a825ce..bf49bce7a5 100644 --- a/frontend/appflowy_flutter/lib/date/date_service.dart +++ b/frontend/appflowy_flutter/lib/date/date_service.dart @@ -1,19 +1,25 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-date/entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class DateService { - static Future> queryDate(String search) async { + static Future> queryDate( + String search, + ) async { final query = DateQueryPB.create()..query = search; - final result = (await DateEventQueryDate(query).send()).swap(); - return result.fold((l) => left(l), (r) { - final date = DateTime.tryParse(r.date); - if (date != null) { - return right(date); - } - - return left(FlowyError(msg: 'Could not parse Date (NLP) from String')); - }); + final result = await DateEventQueryDate(query).send(); + return result.fold( + (s) { + final date = DateTime.tryParse(s.date); + if (date != null) { + return FlowyResult.success(date); + } + return FlowyResult.failure( + FlowyError(msg: 'Could not parse Date (NLP) from String'), + ); + }, + (e) => FlowyResult.failure(e), + ); } } diff --git a/frontend/appflowy_flutter/lib/env/cloud_env.dart b/frontend/appflowy_flutter/lib/env/cloud_env.dart index 783b8177d1..45dd135e98 100644 --- a/frontend/appflowy_flutter/lib/env/cloud_env.dart +++ b/frontend/appflowy_flutter/lib/env/cloud_env.dart @@ -4,7 +4,6 @@ import 'package:appflowy/env/backend_env.dart'; import 'package:appflowy/env/env.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:dartz/dartz.dart'; /// Sets the cloud type for the application. /// @@ -52,7 +51,7 @@ const String kAppflowyCloudUrl = "https://beta.appflowy.cloud"; /// Future getAuthenticatorType() async { final value = await getIt().get(KVKeys.kCloudType); - if (value.isNone() && !integrationMode().isUnitTest) { + if (value == null && !integrationMode().isUnitTest) { // if the cloud type is not set, then set it to AppFlowy Cloud as default. await useAppFlowyBetaCloudWithURL( kAppflowyCloudUrl, @@ -61,7 +60,7 @@ Future getAuthenticatorType() async { return AuthenticatorType.appflowyCloud; } - switch (value.getOrElse(() => "0")) { + switch (value ?? "0") { case "0": return AuthenticatorType.local; case "1": @@ -177,16 +176,13 @@ AuthenticatorType currentCloudType() { return getIt().authenticatorType; } -Future _setAppFlowyCloudUrl(Option url) async { - await url.fold( - () => getIt().set(KVKeys.kAppflowyCloudBaseURL, ""), - (s) => getIt().set(KVKeys.kAppflowyCloudBaseURL, s), - ); +Future _setAppFlowyCloudUrl(String? url) async { + await getIt().set(KVKeys.kAppflowyCloudBaseURL, url ?? ''); } Future useSelfHostedAppFlowyCloudWithURL(String url) async { await _setAuthenticatorType(AuthenticatorType.appflowyCloudSelfHost); - await _setAppFlowyCloudUrl(Some(url)); + await _setAppFlowyCloudUrl(url); } Future useAppFlowyBetaCloudWithURL( @@ -194,7 +190,7 @@ Future useAppFlowyBetaCloudWithURL( AuthenticatorType authenticatorType, ) async { await _setAuthenticatorType(authenticatorType); - await _setAppFlowyCloudUrl(Some(url)); + await _setAppFlowyCloudUrl(url); } Future useLocalServer() async { @@ -206,7 +202,7 @@ Future useSupabaseCloud({ required String anonKey, }) async { await _setAuthenticatorType(AuthenticatorType.supabase); - await setSupbaseServer(Some(url), Some(anonKey)); + await setSupabaseServer(url, anonKey); } /// Use getIt() to get the shared environment. @@ -314,10 +310,7 @@ Future getAppFlowyCloudConfig( Future getAppFlowyCloudUrl() async { final result = await getIt().get(KVKeys.kAppflowyCloudBaseURL); - return result.fold( - () => kAppflowyCloudUrl, - (url) => url, - ); + return result ?? kAppflowyCloudUrl; } Future _getAppFlowyCloudWSUrl(String baseURL) async { @@ -339,27 +332,30 @@ Future _getAppFlowyCloudGotrueUrl(String baseURL) async { return "$baseURL/gotrue"; } -Future setSupbaseServer( - Option url, - Option anonKey, +Future setSupabaseServer( + String? url, + String? anonKey, ) async { assert( - (url.isSome() && anonKey.isSome()) || (url.isNone() && anonKey.isNone()), + (url != null && anonKey != null) || (url == null && anonKey == null), "Either both Supabase URL and anon key must be set, or both should be unset", ); - await url.fold( - () => getIt().remove(KVKeys.kSupabaseURL), - (s) => getIt().set(KVKeys.kSupabaseURL, s), - ); - await anonKey.fold( - () => getIt().remove(KVKeys.kSupabaseAnonKey), - (s) => getIt().set(KVKeys.kSupabaseAnonKey, s), - ); + if (url == null) { + await getIt().remove(KVKeys.kSupabaseURL); + } else { + await getIt().set(KVKeys.kSupabaseURL, url); + } + + if (anonKey == null) { + await getIt().remove(KVKeys.kSupabaseAnonKey); + } else { + await getIt().set(KVKeys.kSupabaseAnonKey, anonKey); + } } Future getSupabaseCloudConfig() async { - final url = await _getSupbaseUrl(); + final url = await _getSupabaseUrl(); final anonKey = await _getSupabaseAnonKey(); return SupabaseConfiguration( url: url, @@ -367,18 +363,12 @@ Future getSupabaseCloudConfig() async { ); } -Future _getSupbaseUrl() async { +Future _getSupabaseUrl() async { final result = await getIt().get(KVKeys.kSupabaseURL); - return result.fold( - () => "", - (url) => url, - ); + return result ?? ''; } Future _getSupabaseAnonKey() async { final result = await getIt().get(KVKeys.kSupabaseAnonKey); - return result.fold( - () => "", - (url) => url, - ); + return result ?? ''; } diff --git a/frontend/appflowy_flutter/lib/mobile/application/user_profile/user_profile_bloc.dart b/frontend/appflowy_flutter/lib/mobile/application/user_profile/user_profile_bloc.dart index e3d43c4a51..7edec07cc1 100644 --- a/frontend/appflowy_flutter/lib/mobile/application/user_profile/user_profile_bloc.dart +++ b/frontend/appflowy_flutter/lib/mobile/application/user_profile/user_profile_bloc.dart @@ -31,8 +31,8 @@ class UserProfileBloc extends Bloc { ); final userProfile = userOrFailure.fold( - (error) => null, (userProfilePB) => userProfilePB, + (error) => null, ); if (workspaceSetting == null || userProfile == null) { diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart index b8e5edd92a..bb21a6ed20 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/base/mobile_view_page.dart @@ -13,7 +13,7 @@ import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart' hide State; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; @@ -40,7 +40,7 @@ class MobileViewPage extends StatefulWidget { } class _MobileViewPageState extends State { - late final Future> future; + late final Future> future; @override void initState() { diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/favorite/mobile_favorite_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/favorite/mobile_favorite_page.dart index 1ed2a7ea20..d6e9a18272 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/favorite/mobile_favorite_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/favorite/mobile_favorite_page.dart @@ -35,10 +35,12 @@ class MobileFavoriteScreen extends StatelessWidget { }, (error) => null, ); - final userProfile = - snapshots.data?[1].fold((error) => null, (userProfilePB) { - return userProfilePB as UserProfilePB?; - }); + final userProfile = snapshots.data?[1].fold( + (userProfilePB) { + return userProfilePB as UserProfilePB?; + }, + (error) => null, + ); // In the unlikely case either of the above is null, eg. // when a workspace is already open this can happen. diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart index 9c296774a0..cab7da1fc7 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_page.dart @@ -41,10 +41,12 @@ class MobileHomeScreen extends StatelessWidget { }, (error) => null, ); - final userProfile = - snapshots.data?[1].fold((error) => null, (userProfilePB) { - return userProfilePB as UserProfilePB?; - }); + final userProfile = snapshots.data?[1].fold( + (userProfilePB) { + return userProfilePB as UserProfilePB?; + }, + (error) => null, + ); // In the unlikely case either of the above is null, eg. // when a workspace is already open this can happen. diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_setting_page.dart b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_setting_page.dart index c01257a474..39c11298a4 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_setting_page.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/home/mobile_home_setting_page.dart @@ -35,12 +35,15 @@ class _MobileHomeSettingPageState extends State { return const Center(child: CircularProgressIndicator.adaptive()); } - final userProfile = snapshot.data?.fold((error) { - errorMsg = error.msg; - return null; - }, (userProfile) { - return userProfile; - }); + final userProfile = snapshot.data?.fold( + (userProfile) { + return userProfile; + }, + (error) { + errorMsg = error.msg; + return null; + }, + ); return Scaffold( appBar: FlowyAppBar( diff --git a/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart b/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart index b83081afec..ea55a16173 100644 --- a/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart +++ b/frontend/appflowy_flutter/lib/mobile/presentation/setting/user_session_setting_group.dart @@ -5,6 +5,7 @@ import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/sign_in_bloc.dart'; import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/sign_in_or_logout_button.dart'; import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart'; +import 'package:appflowy_backend/log.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; @@ -27,12 +28,9 @@ class UserSessionSettingGroup extends StatelessWidget { create: (context) => getIt(), child: BlocConsumer( listener: (context, state) { - state.successOrFail.fold( - () => null, - (result) => result.fold( - (l) {}, - (r) async => runAppFlowy(), - ), + state.successOrFail?.fold( + (result) => runAppFlowy(), + (e) => Log.error(e), ); }, builder: (context, state) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_listener.dart index eb6939c646..e074a9b283 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_listener.dart @@ -4,11 +4,11 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flowy_infra/notifier.dart'; typedef UpdateCalculationValue - = Either; + = FlowyResult; class CalculationsListener { CalculationsListener({required this.viewId}); @@ -31,15 +31,15 @@ class CalculationsListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateCalculation: _calculationNotifier?.value = result.fold( - (payload) => left( + (payload) => FlowyResult.success( CalculationChangesetNotificationPB.fromBuffer(payload), ), - (err) => right(err), + (err) => FlowyResult.failure(err), ); default: break; diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_service.dart index 874c565c3e..e3ef8d578e 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/calculations/calculations_service.dart @@ -1,7 +1,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class CalculationsBackendService { const CalculationsBackendService({required this.viewId}); @@ -9,7 +9,9 @@ class CalculationsBackendService { final String viewId; // Get Calculations (initial fetch) - Future> getCalculations() async { + + Future> + getCalculations() async { final payload = DatabaseViewIdPB()..value = viewId; return DatabaseEventGetAllCalculations(payload).send(); diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_editor_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_editor_bloc.dart index ab879b7d8b..2685957a8f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_editor_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/bloc/select_option_editor_bloc.dart @@ -1,12 +1,10 @@ import 'dart:async'; -import 'package:flutter/widgets.dart'; - import 'package:appflowy/plugins/database/application/cell/cell_controller_builder.dart'; import 'package:appflowy/plugins/database/application/cell/select_option_cell_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:flutter/widgets.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -52,7 +50,7 @@ class SelectOptionCellEditorBloc await _createOption(optionName); emit( state.copyWith( - filter: none(), + filter: null, ), ); }, @@ -164,7 +162,7 @@ class SelectOptionCellEditorBloc } // clear the filter - emit(state.copyWith(filter: none())); + emit(state.copyWith(filter: null)); } void _selectMultipleOptions(List optionNames) { @@ -186,12 +184,12 @@ class SelectOptionCellEditorBloc void _filterOption(String optionName, Emitter emit) { final _MakeOptionResult result = _makeOptions( - Some(optionName), + optionName, state.allOptions, ); emit( state.copyWith( - filter: Some(optionName), + filter: optionName, options: result.options, createOption: result.createOption, ), @@ -201,7 +199,7 @@ class SelectOptionCellEditorBloc Future _loadOptions() async { final result = await _selectOptionService.getCellData(); if (isClosed) { - Log.warn("Unexpected closing the bloc"); + Log.warn("Unexpecteded closing the bloc"); return; } @@ -220,28 +218,26 @@ class SelectOptionCellEditorBloc } _MakeOptionResult _makeOptions( - Option filter, + String? filter, List allOptions, ) { final List options = List.from(allOptions); - Option createOption = filter; + String? createOption = filter; - filter.foldRight(null, (filter, previous) { - if (filter.isNotEmpty) { - options.retainWhere((option) { - final name = option.name.toLowerCase(); - final lFilter = filter.toLowerCase(); + if (filter != null && filter.isNotEmpty) { + options.retainWhere((option) { + final name = option.name.toLowerCase(); + final lFilter = filter.toLowerCase(); - if (name == lFilter) { - createOption = none(); - } + if (name == lFilter) { + createOption = null; + } - return name.contains(lFilter); - }); - } else { - createOption = none(); - } - }); + return name.contains(lFilter); + }); + } else { + createOption = null; + } return _MakeOptionResult( options: options, @@ -295,8 +291,8 @@ class SelectOptionEditorState with _$SelectOptionEditorState { required List options, required List allOptions, required List selectedOptions, - required Option createOption, - required Option filter, + required String? createOption, + required String? filter, }) = _SelectOptionEditorState; factory SelectOptionEditorState.initial(SelectOptionCellController context) { @@ -305,8 +301,8 @@ class SelectOptionEditorState with _$SelectOptionEditorState { options: data?.options ?? [], allOptions: data?.options ?? [], selectedOptions: data?.selectOptions ?? [], - createOption: none(), - filter: none(), + createOption: null, + filter: null, ); } } @@ -318,5 +314,5 @@ class _MakeOptionResult { }); List options; - Option createOption; + String? createOption; } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart index 65c17e763c..0e08a7a88c 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_controller.dart @@ -10,7 +10,6 @@ import 'package:appflowy/plugins/database/application/row/row_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:flutter/foundation.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -173,7 +172,7 @@ class CellController { Future saveCellData( D data, { bool debounce = false, - void Function(Option)? onFinish, + void Function(FlowyError?)? onFinish, }) async { _loadDataOperation?.cancel(); if (debounce) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_data_persistence.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_data_persistence.dart index 1b0bc7a03a..56424e376b 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_data_persistence.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_data_persistence.dart @@ -1,5 +1,4 @@ import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; -import 'package:dartz/dartz.dart'; import 'cell_controller.dart'; import 'cell_service.dart'; @@ -7,7 +6,7 @@ import 'cell_service.dart'; /// Save the cell data to disk /// You can extend this class to do custom operations. abstract class CellDataPersistence { - Future> save({ + Future save({ required String viewId, required CellContext cellContext, required D data, @@ -18,7 +17,7 @@ class TextCellDataPersistence implements CellDataPersistence { TextCellDataPersistence(); @override - Future> save({ + Future save({ required String viewId, required CellContext cellContext, required String data, @@ -30,8 +29,8 @@ class TextCellDataPersistence implements CellDataPersistence { ); return fut.then((result) { return result.fold( - (l) => none(), - (err) => Some(err), + (l) => null, + (err) => err, ); }); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_listener.dart index 111b611816..6c2d7ef857 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_listener.dart @@ -4,12 +4,12 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flowy_infra/notifier.dart'; import '../row/row_service.dart'; -typedef UpdateFieldNotifiedValue = Either; +typedef UpdateFieldNotifiedValue = FlowyResult; class CellListener { CellListener({required this.rowId, required this.fieldId}); @@ -29,12 +29,15 @@ class CellListener { ); } - void _handler(DatabaseNotification ty, Either result) { + void _handler( + DatabaseNotification ty, + FlowyResult result, + ) { switch (ty) { case DatabaseNotification.DidUpdateCell: result.fold( - (payload) => _updateCellNotifier?.value = left(unit), - (error) => _updateCellNotifier?.value = right(error), + (payload) => _updateCellNotifier?.value = FlowyResult.success(null), + (error) => _updateCellNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_service.dart index 74437cb280..94e62c6288 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/cell_service.dart @@ -1,16 +1,16 @@ import 'dart:async'; -import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'cell_controller.dart'; class CellBackendService { CellBackendService(); - static Future> updateCell({ + static Future> updateCell({ required String viewId, required CellContext cellContext, required String data, @@ -23,7 +23,7 @@ class CellBackendService { return DatabaseEventUpdateCell(payload).send(); } - static Future> getCell({ + static Future> getCell({ required String viewId, required CellContext cellContext, }) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/checklist_cell_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/checklist_cell_service.dart index 17a8fa0a55..5b89d05643 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/checklist_cell_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/checklist_cell_service.dart @@ -2,7 +2,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/checklist_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:protobuf/protobuf.dart'; class ChecklistCellBackendService { @@ -16,7 +16,7 @@ class ChecklistCellBackendService { final String fieldId; final String rowId; - Future> create({ + Future> create({ required String name, }) { final payload = ChecklistCellDataChangesetPB.create() @@ -28,7 +28,7 @@ class ChecklistCellBackendService { return DatabaseEventUpdateChecklistCell(payload).send(); } - Future> delete({ + Future> delete({ required List optionIds, }) { final payload = ChecklistCellDataChangesetPB.create() @@ -40,7 +40,7 @@ class ChecklistCellBackendService { return DatabaseEventUpdateChecklistCell(payload).send(); } - Future> select({ + Future> select({ required String optionId, }) { final payload = ChecklistCellDataChangesetPB.create() @@ -52,7 +52,7 @@ class ChecklistCellBackendService { return DatabaseEventUpdateChecklistCell(payload).send(); } - Future> updateName({ + Future> updateName({ required SelectOptionPB option, required name, }) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/date_cell_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/date_cell_service.dart index 6bd12a66f7..9a9f75e75f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/date_cell_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/date_cell_service.dart @@ -2,7 +2,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/cell_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/date_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:fixnum/fixnum.dart'; final class DateCellBackendService { @@ -17,7 +17,7 @@ final class DateCellBackendService { final CellIdPB cellId; - Future> update({ + Future> update({ required bool includeTime, required bool isRange, DateTime? date, @@ -52,7 +52,7 @@ final class DateCellBackendService { return DatabaseEventUpdateDateCell(payload).send(); } - Future> clear() { + Future> clear() { final payload = DateCellChangesetPB.create() ..cellId = cellId ..clearFlag = true; diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/cell/select_option_cell_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/cell/select_option_cell_service.dart index 906496c18a..8d5a6cd849 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/cell/select_option_cell_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/cell/select_option_cell_service.dart @@ -1,9 +1,9 @@ import 'package:appflowy/plugins/database/application/field/type_option/type_option_service.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/cell_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class SelectOptionCellBackendService { SelectOptionCellBackendService({ @@ -16,7 +16,7 @@ class SelectOptionCellBackendService { final String fieldId; final String rowId; - Future> create({ + Future> create({ required String name, bool isSelected = true, }) { @@ -34,13 +34,13 @@ class SelectOptionCellBackendService { return DatabaseEventInsertOrUpdateSelectOption(payload).send(); }, - (r) => right(r), + (r) => FlowyResult.failure(r), ); }, ); } - Future> update({ + Future> update({ required SelectOptionPB option, }) { final payload = RepeatedSelectOptionPayload() @@ -52,7 +52,7 @@ class SelectOptionCellBackendService { return DatabaseEventInsertOrUpdateSelectOption(payload).send(); } - Future> delete({ + Future> delete({ required Iterable options, }) { final payload = RepeatedSelectOptionPayload() @@ -64,7 +64,7 @@ class SelectOptionCellBackendService { return DatabaseEventDeleteSelectOption(payload).send(); } - Future> getCellData() { + Future> getCellData() { final payload = CellIdPB() ..viewId = viewId ..fieldId = fieldId @@ -73,7 +73,7 @@ class SelectOptionCellBackendService { return DatabaseEventGetSelectOptionCellData(payload).send(); } - Future> select({ + Future> select({ required Iterable optionIds, }) { final payload = SelectOptionCellChangesetPB() @@ -83,7 +83,7 @@ class SelectOptionCellBackendService { return DatabaseEventUpdateSelectOptionCell(payload).send(); } - Future> unSelect({ + Future> unSelect({ required Iterable optionIds, }) { final payload = SelectOptionCellChangesetPB() diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart b/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart index 09ee5e153f..a9712f9ea8 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/database_controller.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:appflowy/plugins/database/application/field/field_controller.dart'; import 'package:appflowy/plugins/database/application/view/view_cache.dart'; import 'package:appflowy_backend/log.dart'; @@ -10,17 +12,16 @@ import 'package:appflowy_backend/protobuf/flowy-database2/row_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; 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 'dart:async'; -import 'package:dartz/dartz.dart'; import 'package:flutter/material.dart'; import 'database_view_service.dart'; import 'defines.dart'; +import 'group/group_listener.dart'; import 'layout/layout_service.dart'; import 'layout/layout_setting_listener.dart'; import 'row/row_cache.dart'; -import 'group/group_listener.dart'; typedef OnGroupConfigurationChanged = void Function(List); typedef OnGroupByField = void Function(List); @@ -136,7 +137,7 @@ class DatabaseController { } } - Future> open() async { + Future> open() async { return _databaseViewBackendSvc.openDatabase().then((result) { return result.fold( (DatabasePB database) async { @@ -157,21 +158,21 @@ class DatabaseController { return Future(() async { await _loadGroups(); await _loadLayoutSetting(); - return left(fields); + return FlowyResult.success(fields); }); }, (err) { Log.error(err); - return right(err); + return FlowyResult.failure(err); }, ); }, - (err) => right(err), + (err) => FlowyResult.failure(err), ); }); } - Future> moveGroupRow({ + Future> moveGroupRow({ required RowMetaPB fromRow, required String fromGroupId, required String toGroupId, @@ -185,7 +186,7 @@ class DatabaseController { ); } - Future> moveRow({ + Future> moveRow({ required String fromRowId, required String toRowId, }) { @@ -195,7 +196,7 @@ class DatabaseController { ); } - Future> moveGroup({ + Future> moveGroup({ required String fromGroupId, required String toGroupId, }) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/database_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/database_service.dart index ebfdbdfd2d..8d237f9114 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/database_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/database_service.dart @@ -1,13 +1,16 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class DatabaseBackendService { - static Future, FlowyError>> + static Future, FlowyError>> getAllDatabases() { return DatabaseEventGetDatabases().send().then((result) { - return result.fold((l) => left(l.items), (r) => right(r)); + return result.fold( + (l) => FlowyResult.success(l.items), + (r) => FlowyResult.failure(r), + ); }); } } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/database_view_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/database_view_service.dart index e4c36a3c54..a28819e2db 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/database_view_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/database_view_service.dart @@ -3,7 +3,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'layout/layout_service.dart'; @@ -12,15 +12,15 @@ class DatabaseViewBackendService { final String viewId; - /// Returns the datbaase id associated with the view. - Future> getDatabaseId() async { + /// Returns the database id associated with the view. + Future> getDatabaseId() async { final payload = DatabaseViewIdPB(value: viewId); return DatabaseEventGetDatabaseId(payload) .send() - .then((value) => value.leftMap((l) => l.value)); + .then((value) => value.map((l) => l.value)); } - static Future> updateLayout({ + static Future> updateLayout({ required String viewId, required DatabaseLayoutPB layout, }) { @@ -31,12 +31,12 @@ class DatabaseViewBackendService { return FolderEventUpdateView(payload).send(); } - Future> openDatabase() async { + Future> openDatabase() async { final payload = DatabaseViewIdPB(value: viewId); return DatabaseEventGetDatabase(payload).send(); } - Future> moveGroupRow({ + Future> moveGroupRow({ required RowId fromRowId, required String fromGroupId, required String toGroupId, @@ -55,7 +55,7 @@ class DatabaseViewBackendService { return DatabaseEventMoveGroupRow(payload).send(); } - Future> moveRow({ + Future> moveRow({ required String fromRowId, required String toRowId, }) { @@ -67,7 +67,7 @@ class DatabaseViewBackendService { return DatabaseEventMoveRow(payload).send(); } - Future> moveGroup({ + Future> moveGroup({ required String fromGroupId, required String toGroupId, }) { @@ -79,7 +79,7 @@ class DatabaseViewBackendService { return DatabaseEventMoveGroup(payload).send(); } - Future, FlowyError>> getFields({ + Future, FlowyError>> getFields({ List? fieldIds, }) { final payload = GetFieldPayloadPB.create()..viewId = viewId; @@ -88,11 +88,14 @@ class DatabaseViewBackendService { payload.fieldIds = RepeatedFieldIdPB(items: fieldIds); } return DatabaseEventGetFields(payload).send().then((result) { - return result.fold((l) => left(l.items), (r) => right(r)); + return result.fold( + (l) => FlowyResult.success(l.items), + (r) => FlowyResult.failure(r), + ); }); } - Future> getLayoutSetting( + Future> getLayoutSetting( DatabaseLayoutPB layoutType, ) { final payload = DatabaseLayoutMetaPB.create() @@ -101,7 +104,7 @@ class DatabaseViewBackendService { return DatabaseEventGetLayoutSetting(payload).send(); } - Future> updateLayoutSetting({ + Future> updateLayoutSetting({ required DatabaseLayoutPB layoutType, BoardLayoutSettingPB? boardLayoutSetting, CalendarLayoutSettingPB? calendarLayoutSetting, @@ -121,12 +124,12 @@ class DatabaseViewBackendService { return DatabaseEventSetLayoutSetting(payload).send(); } - Future> closeView() { + Future> closeView() { final request = ViewIdPB(value: viewId); return FolderEventCloseView(request).send(); } - Future> loadGroups() { + Future> loadGroups() { final payload = DatabaseViewIdPB(value: viewId); return DatabaseEventGetGroups(payload).send(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/defines.dart b/frontend/appflowy_flutter/lib/plugins/database/application/defines.dart index d21f533f42..88e9fc4f77 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/defines.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/defines.dart @@ -5,7 +5,7 @@ import 'package:appflowy/plugins/database/grid/presentation/widgets/filter/filte import 'package:appflowy/plugins/database/grid/presentation/widgets/sort/sort_info.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'field/field_info.dart'; @@ -38,7 +38,7 @@ class LoadingState with _$LoadingState { const factory LoadingState.idle() = _Idle; const factory LoadingState.loading() = _Loading; const factory LoadingState.finish( - Either successOrFail, + FlowyResult successOrFail, ) = _Finish; const LoadingState._(); diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_controller.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_controller.dart index a95350516e..59822261af 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_controller.dart @@ -20,8 +20,8 @@ import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.da import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:collection/collection.dart'; -import 'package:dartz/dartz.dart'; import 'package:flutter/foundation.dart'; import '../setting/setting_service.dart'; @@ -382,7 +382,7 @@ class FieldController { ); } - /// Listen for databse setting changes in the backend. + /// Listen for database setting changes in the backend. void _listenOnSettingChanges() { _settingListener.start( onSettingUpdated: (result) { @@ -581,7 +581,7 @@ class FieldController { } /// Load all of the fields. This is required when opening the database - Future> loadFields({ + Future> loadFields({ required List fieldIds, }) async { final result = await _databaseViewBackendSvc.getFields(fieldIds: fieldIds); @@ -589,7 +589,7 @@ class FieldController { () => result.fold( (newFields) async { if (_isDisposed) { - return left(unit); + return FlowyResult.success(null); } _fieldNotifier.fieldInfos = @@ -602,54 +602,54 @@ class FieldController { ]); _updateFieldInfos(); - return left(unit); + return FlowyResult.success(null); }, - (err) => right(err), + (err) => FlowyResult.failure(err), ), ); } /// Load all the filters from the backend. Required by `loadFields` - Future> _loadFilters() async { + Future> _loadFilters() async { return _filterBackendSvc.getAllFilters().then((result) { return result.fold( (filterPBs) { _filterNotifier?.filters = _filterInfoListFromPBs(filterPBs); - return left(unit); + return FlowyResult.success(null); }, - (err) => right(err), + (err) => FlowyResult.failure(err), ); }); } /// Load all the sorts from the backend. Required by `loadFields` - Future> _loadSorts() async { + Future> _loadSorts() async { return _sortBackendSvc.getAllSorts().then((result) { return result.fold( (sortPBs) { _sortNotifier?.sorts = _sortInfoListFromPBs(sortPBs); - return left(unit); + return FlowyResult.success(null); }, - (err) => right(err), + (err) => FlowyResult.failure(err), ); }); } /// Load all the field settings from the backend. Required by `loadFields` - Future> _loadAllFieldSettings() async { + Future> _loadAllFieldSettings() async { return _fieldSettingsBackendSvc.getAllFieldSettings().then((result) { return result.fold( (fieldSettingsList) { _fieldSettings.clear(); _fieldSettings.addAll(fieldSettingsList); - return left(unit); + return FlowyResult.success(null); }, - (err) => right(err), + (err) => FlowyResult.failure(err), ); }); } - Future> _loadSettings() async { + Future> _loadSettings() async { return SettingBackendService(viewId: viewId).getSetting().then( (result) => result.fold( (setting) { @@ -658,9 +658,9 @@ class FieldController { _groupConfigurationByFieldId[configuration.fieldId] = configuration; } - return left(unit); + return FlowyResult.success(null); }, - (err) => right(err), + (err) => FlowyResult.failure(err), ), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_editor_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_editor_bloc.dart index 5c6c774108..955a4701b2 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_editor_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_editor_bloc.dart @@ -4,7 +4,7 @@ import 'package:appflowy/plugins/database/application/field_settings/field_setti import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -111,7 +111,7 @@ class FieldEditorBloc extends Bloc { ); } - void _logIfError(Either result) { + void _logIfError(FlowyResult result) { result.fold( (l) => null, (err) => Log.error(err), diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_listener.dart index 19c2f447e9..f620c92931 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_listener.dart @@ -5,7 +5,7 @@ import 'package:appflowy/core/notification/grid_notification.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flowy_infra/notifier.dart'; typedef UpdateFieldNotifiedValue = FieldPB; @@ -30,7 +30,7 @@ class SingleFieldListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateField: @@ -51,7 +51,7 @@ class SingleFieldListener { } typedef UpdateFieldsNotifiedValue - = Either; + = FlowyResult; class FieldsListener { FieldsListener({required this.viewId}); @@ -72,13 +72,16 @@ class FieldsListener { ); } - void _handler(DatabaseNotification ty, Either result) { + void _handler( + DatabaseNotification ty, + FlowyResult result, + ) { switch (ty) { case DatabaseNotification.DidUpdateFields: result.fold( (payload) => updateFieldsNotifier?.value = - left(DatabaseFieldChangesetPB.fromBuffer(payload)), - (error) => updateFieldsNotifier?.value = right(error), + FlowyResult.success(DatabaseFieldChangesetPB.fromBuffer(payload)), + (error) => updateFieldsNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_service.dart index a416ddc2d5..6574b903a4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/field_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/field_service.dart @@ -3,7 +3,7 @@ import 'dart:typed_data'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; /// FieldService provides many field-related interfaces event functions. Check out /// `rust-lib/flowy-database/event_map.rs` for a list of events and their @@ -16,7 +16,7 @@ class FieldBackendService { /// Create a field in a database view. The position will only be applicable /// in this view; for other views it will be appended to the end - static Future> createField({ + static Future> createField({ required String viewId, FieldType fieldType = FieldType.RichText, String? fieldName, @@ -35,7 +35,7 @@ class FieldBackendService { } /// Reorder a field within a database view - static Future> moveField({ + static Future> moveField({ required String viewId, required String fromFieldId, required String toFieldId, @@ -50,7 +50,7 @@ class FieldBackendService { } /// Delete a field - static Future> deleteField({ + static Future> deleteField({ required String viewId, required String fieldId, }) { @@ -63,7 +63,7 @@ class FieldBackendService { } /// Duplicate a field - static Future> duplicateField({ + static Future> duplicateField({ required String viewId, required String fieldId, }) { @@ -76,7 +76,7 @@ class FieldBackendService { } /// Update a field's properties - Future> updateField({ + Future> updateField({ String? name, bool? frozen, }) { @@ -96,7 +96,7 @@ class FieldBackendService { } /// Change a field's type - static Future> updateFieldType({ + static Future> updateFieldType({ required String viewId, required String fieldId, required FieldType fieldType, @@ -110,7 +110,7 @@ class FieldBackendService { } /// Update a field's type option data - static Future> updateFieldTypeOption({ + static Future> updateFieldTypeOption({ required String viewId, required String fieldId, required List typeOptionData, @@ -124,14 +124,14 @@ class FieldBackendService { } /// Returns the primary field of the view. - static Future> getPrimaryField({ + static Future> getPrimaryField({ required String viewId, }) { final payload = DatabaseViewIdPB.create()..value = viewId; return DatabaseEventGetPrimaryField(payload).send(); } - Future> createBefore({ + Future> createBefore({ FieldType fieldType = FieldType.RichText, String? fieldName, Uint8List? typeOptionData, @@ -148,7 +148,7 @@ class FieldBackendService { ); } - Future> createAfter({ + Future> createAfter({ FieldType fieldType = FieldType.RichText, String? fieldName, Uint8List? typeOptionData, @@ -165,7 +165,7 @@ class FieldBackendService { ); } - Future> updateType({ + Future> updateType({ required FieldType fieldType, }) => updateFieldType( @@ -174,9 +174,9 @@ class FieldBackendService { fieldType: fieldType, ); - Future> delete() => + Future> delete() => deleteField(viewId: viewId, fieldId: fieldId); - Future> duplicate() => + Future> duplicate() => duplicateField(viewId: viewId, fieldId: fieldId); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/select_option_type_option_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/select_option_type_option_bloc.dart index d62cd8b8c5..cd1db30fc6 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/select_option_type_option_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/select_option_type_option_bloc.dart @@ -1,5 +1,4 @@ import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -28,10 +27,10 @@ class SelectOptionTypeOptionBloc emit(state.copyWith(options: options)); }, addingOption: () { - emit(state.copyWith(isEditingOption: true, newOptionName: none())); + emit(state.copyWith(isEditingOption: true, newOptionName: null)); }, endAddingOption: () { - emit(state.copyWith(isEditingOption: false, newOptionName: none())); + emit(state.copyWith(isEditingOption: false, newOptionName: null)); }, updateOption: (option) { final List options = @@ -69,13 +68,13 @@ class SelectOptionTypeOptionState with _$SelectOptionTypeOptionState { const factory SelectOptionTypeOptionState({ required List options, required bool isEditingOption, - required Option newOptionName, + required String? newOptionName, }) = _SelectOptionTypeOptionState; factory SelectOptionTypeOptionState.initial(List options) => SelectOptionTypeOptionState( options: options, isEditingOption: false, - newOptionName: none(), + newOptionName: null, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/type_option_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/type_option_service.dart index 15c9683f05..a222e69853 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/type_option_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field/type_option/type_option_service.dart @@ -1,7 +1,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class TypeOptionBackendService { TypeOptionBackendService({ @@ -12,7 +12,7 @@ class TypeOptionBackendService { final String viewId; final String fieldId; - Future> newOption({ + Future> newOption({ required String name, }) { final payload = CreateSelectOptionPayloadPB.create() diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_listener.dart index 6262e16f3b..1313939091 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_listener.dart @@ -3,10 +3,10 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flowy_infra/notifier.dart'; -typedef FieldSettingsValue = Either; +typedef FieldSettingsValue = FlowyResult; class FieldSettingsListener { FieldSettingsListener({required this.viewId}); @@ -29,14 +29,14 @@ class FieldSettingsListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateFieldSettings: result.fold( (payload) => _fieldSettingsNotifier?.value = - left(FieldSettingsPB.fromBuffer(payload)), - (error) => _fieldSettingsNotifier?.value = right(error), + FlowyResult.success(FieldSettingsPB.fromBuffer(payload)), + (error) => _fieldSettingsNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_service.dart index 47ac8e9ded..916371f752 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/field_settings/field_settings_service.dart @@ -1,14 +1,14 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class FieldSettingsBackendService { FieldSettingsBackendService({required this.viewId}); final String viewId; - Future> getFieldSettings( + Future> getFieldSettings( String fieldId, ) { final id = FieldIdPB(fieldId: fieldId); @@ -25,14 +25,14 @@ class FieldSettingsBackendService { fieldSetting.visibility = FieldVisibility.AlwaysShown; } - return left(fieldSetting); + return FlowyResult.success(fieldSetting); }, - (r) => right(r), + (r) => FlowyResult.failure(r), ); }); } - Future, FlowyError>> getAllFieldSettings() { + Future, FlowyError>> getAllFieldSettings() { final payload = DatabaseViewIdPB()..value = viewId; return DatabaseEventGetAllFieldSettings(payload).send().then((result) { @@ -47,14 +47,14 @@ class FieldSettingsBackendService { fieldSettings.add(fieldSetting); } - return left(fieldSettings); + return FlowyResult.success(fieldSettings); }, - (r) => right(r), + (r) => FlowyResult.failure(r), ); }); } - Future> updateFieldSettings({ + Future> updateFieldSettings({ required String fieldId, FieldVisibility? fieldVisibility, double? width, diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_listener.dart index ed6294f676..f1b0a82723 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_listener.dart @@ -1,15 +1,15 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/filter_changeset.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; typedef UpdateFilterNotifiedValue - = Either; + = FlowyResult; class FiltersListener { FiltersListener({required this.viewId}); @@ -32,14 +32,15 @@ class FiltersListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateFilter: result.fold( - (payload) => _filterNotifier?.value = - left(FilterChangesetNotificationPB.fromBuffer(payload)), - (error) => _filterNotifier?.value = right(error), + (payload) => _filterNotifier?.value = FlowyResult.success( + FilterChangesetNotificationPB.fromBuffer(payload), + ), + (error) => _filterNotifier?.value = FlowyResult.failure(error), ); break; default: @@ -103,7 +104,7 @@ class FilterListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateFilter: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_service.dart index 03056a980c..a44cc13731 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/filter/filter_service.dart @@ -1,10 +1,8 @@ -import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/checkbox_filter.pbserver.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/checklist_filter.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/date_filter.pbserver.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/number_filter.pb.dart'; @@ -12,6 +10,8 @@ import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.p import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/text_filter.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/util.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:fixnum/fixnum.dart' as $fixnum; class FilterBackendService { @@ -19,18 +19,18 @@ class FilterBackendService { final String viewId; - Future, FlowyError>> getAllFilters() { + Future, FlowyError>> getAllFilters() { final payload = DatabaseViewIdPB()..value = viewId; return DatabaseEventGetAllFilters(payload).send().then((result) { return result.fold( - (repeated) => left(repeated.items), - (r) => right(r), + (repeated) => FlowyResult.success(repeated.items), + (r) => FlowyResult.failure(r), ); }); } - Future> insertTextFilter({ + Future> insertTextFilter({ required String fieldId, String? filterId, required TextFilterConditionPB condition, @@ -48,7 +48,7 @@ class FilterBackendService { ); } - Future> insertCheckboxFilter({ + Future> insertCheckboxFilter({ required String fieldId, String? filterId, required CheckboxFilterConditionPB condition, @@ -63,7 +63,7 @@ class FilterBackendService { ); } - Future> insertNumberFilter({ + Future> insertNumberFilter({ required String fieldId, String? filterId, required NumberFilterConditionPB condition, @@ -81,7 +81,7 @@ class FilterBackendService { ); } - Future> insertDateFilter({ + Future> insertDateFilter({ required String fieldId, String? filterId, required DateFilterConditionPB condition, @@ -120,7 +120,7 @@ class FilterBackendService { ); } - Future> insertURLFilter({ + Future> insertURLFilter({ required String fieldId, String? filterId, required TextFilterConditionPB condition, @@ -138,7 +138,7 @@ class FilterBackendService { ); } - Future> insertSelectOptionFilter({ + Future> insertSelectOptionFilter({ required String fieldId, required FieldType fieldType, required SelectOptionConditionPB condition, @@ -157,7 +157,7 @@ class FilterBackendService { ); } - Future> insertChecklistFilter({ + Future> insertChecklistFilter({ required String fieldId, required ChecklistFilterConditionPB condition, String? filterId, @@ -173,7 +173,7 @@ class FilterBackendService { ); } - Future> insertFilter({ + Future> insertFilter({ required String fieldId, String? filterId, required FieldType fieldType, @@ -194,16 +194,16 @@ class FilterBackendService { ..updateFilter = insertFilterPayload; return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( - (l) => left(l), + (l) => FlowyResult.success(l), (err) { Log.error(err); - return right(err); + return FlowyResult.failure(err); }, ); }); } - Future> deleteFilter({ + Future> deleteFilter({ required String fieldId, required String filterId, required FieldType fieldType, @@ -220,10 +220,10 @@ class FilterBackendService { return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( - (l) => left(l), + (l) => FlowyResult.success(l), (err) { Log.error(err); - return right(err); + return FlowyResult.failure(err); }, ); }); diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/group/group_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/group/group_listener.dart index b22371737c..212bce80c3 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/group/group_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/group/group_listener.dart @@ -1,17 +1,17 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/group_changeset.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; typedef GroupConfigurationUpdateValue - = Either, FlowyError>; -typedef GroupUpdateValue = Either; -typedef GroupByNewFieldValue = Either, FlowyError>; + = FlowyResult, FlowyError>; +typedef GroupUpdateValue = FlowyResult; +typedef GroupByNewFieldValue = FlowyResult, FlowyError>; class DatabaseGroupListener { DatabaseGroupListener(this.viewId); @@ -37,21 +37,22 @@ class DatabaseGroupListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateNumOfGroups: result.fold( (payload) => _numOfGroupsNotifier?.value = - left(GroupChangesPB.fromBuffer(payload)), - (error) => _numOfGroupsNotifier?.value = right(error), + FlowyResult.success(GroupChangesPB.fromBuffer(payload)), + (error) => _numOfGroupsNotifier?.value = FlowyResult.failure(error), ); break; case DatabaseNotification.DidGroupByField: result.fold( - (payload) => _groupByFieldNotifier?.value = - left(GroupChangesPB.fromBuffer(payload).initialGroups), - (error) => _groupByFieldNotifier?.value = right(error), + (payload) => _groupByFieldNotifier?.value = FlowyResult.success( + GroupChangesPB.fromBuffer(payload).initialGroups, + ), + (error) => _groupByFieldNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/group/group_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/group/group_service.dart index c7fe72d95d..69703d7748 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/group/group_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/group/group_service.dart @@ -1,14 +1,14 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/group.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class GroupBackendService { GroupBackendService(this.viewId); final String viewId; - Future> groupByField({ + Future> groupByField({ required String fieldId, }) { final payload = GroupByFieldPayloadPB.create() @@ -18,7 +18,7 @@ class GroupBackendService { return DatabaseEventSetGroupByField(payload).send(); } - Future> updateGroup({ + Future> updateGroup({ required String groupId, required String fieldId, String? name, @@ -38,7 +38,7 @@ class GroupBackendService { return DatabaseEventUpdateGroup(payload).send(); } - Future> createGroup({ + Future> createGroup({ required String name, String groupConfigId = "", }) { @@ -49,7 +49,7 @@ class GroupBackendService { return DatabaseEventCreateGroup(payload).send(); } - Future> deleteGroup({ + Future> deleteGroup({ required String groupId, }) { final payload = DeleteGroupPayloadPB.create() diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/layout/layout_setting_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/layout/layout_setting_listener.dart index 0d016e148f..fd213f74be 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/layout/layout_setting_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/layout/layout_setting_listener.dart @@ -1,12 +1,12 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; -typedef LayoutSettingsValue = Either; +typedef LayoutSettingsValue = FlowyResult; class DatabaseLayoutSettingListener { DatabaseLayoutSettingListener(this.viewId); @@ -30,14 +30,14 @@ class DatabaseLayoutSettingListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateLayoutSettings: result.fold( (payload) => _settingNotifier?.value = - left(DatabaseLayoutSettingPB.fromBuffer(payload)), - (error) => _settingNotifier?.value = right(error), + FlowyResult.success(DatabaseLayoutSettingPB.fromBuffer(payload)), + (error) => _settingNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_listener.dart index 2e1b78d3b3..3d033128a8 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_listener.dart @@ -2,9 +2,9 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; +import 'package:appflowy_result/appflowy_result.dart'; typedef DidFetchRowCallback = void Function(DidFetchRowPB); typedef RowMetaCallback = void Function(RowMetaPB); @@ -34,7 +34,7 @@ class RowListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateRowMeta: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_meta_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_meta_listener.dart index 4836ec7a12..1b7e66fd75 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_meta_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_meta_listener.dart @@ -2,9 +2,9 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; +import 'package:appflowy_result/appflowy_result.dart'; typedef RowMetaCallback = void Function(RowMetaPB); @@ -26,7 +26,7 @@ class RowMetaListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateRowMeta: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_service.dart index 18ece0708d..8479120d7b 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/row/row_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/row/row_service.dart @@ -1,7 +1,7 @@ -import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import '../field/field_info.dart'; @@ -12,7 +12,7 @@ class RowBackendService { final String viewId; - static Future> createRow({ + static Future> createRow({ required String viewId, String? groupId, void Function(RowDataBuilder builder)? withCells, @@ -43,7 +43,7 @@ class RowBackendService { return DatabaseEventCreateRow(payload).send(); } - Future> createRowBefore(RowId rowId) { + Future> createRowBefore(RowId rowId) { return createRow( viewId: viewId, position: OrderObjectPositionTypePB.Before, @@ -51,7 +51,7 @@ class RowBackendService { ); } - Future> createRowAfter(RowId rowId) { + Future> createRowAfter(RowId rowId) { return createRow( viewId: viewId, position: OrderObjectPositionTypePB.After, @@ -59,7 +59,7 @@ class RowBackendService { ); } - static Future> getRow({ + static Future> getRow({ required String viewId, required String rowId, }) { @@ -70,7 +70,7 @@ class RowBackendService { return DatabaseEventGetRowMeta(payload).send(); } - Future> getRowMeta(RowId rowId) { + Future> getRowMeta(RowId rowId) { final payload = RowIdPB.create() ..viewId = viewId ..rowId = rowId; @@ -78,7 +78,7 @@ class RowBackendService { return DatabaseEventGetRowMeta(payload).send(); } - Future> updateMeta({ + Future> updateMeta({ required String rowId, String? iconURL, String? coverURL, @@ -102,7 +102,7 @@ class RowBackendService { return DatabaseEventUpdateRowMeta(payload).send(); } - static Future> deleteRow( + static Future> deleteRow( String viewId, RowId rowId, ) { @@ -113,7 +113,7 @@ class RowBackendService { return DatabaseEventDeleteRow(payload).send(); } - static Future> duplicateRow( + static Future> duplicateRow( String viewId, RowId rowId, ) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_listener.dart index 2778e841ab..34dfba53d4 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_listener.dart @@ -1,13 +1,14 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; -import 'package:dartz/dartz.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; -typedef UpdateSettingNotifiedValue = Either; +typedef UpdateSettingNotifiedValue + = FlowyResult; class DatabaseSettingListener { DatabaseSettingListener({required this.viewId}); @@ -26,14 +27,17 @@ class DatabaseSettingListener { DatabaseNotificationListener(objectId: viewId, handler: _handler); } - void _handler(DatabaseNotification ty, Either result) { + void _handler( + DatabaseNotification ty, + FlowyResult result, + ) { switch (ty) { case DatabaseNotification.DidUpdateSettings: result.fold( - (payload) => _updateSettingNotifier?.value = left( + (payload) => _updateSettingNotifier?.value = FlowyResult.success( DatabaseViewSettingPB.fromBuffer(payload), ), - (error) => _updateSettingNotifier?.value = right(error), + (error) => _updateSettingNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_service.dart index d0a1c8a312..d34fab1aea 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/setting/setting_service.dart @@ -1,15 +1,15 @@ -import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class SettingBackendService { const SettingBackendService({required this.viewId}); final String viewId; - Future> getSetting() { + Future> getSetting() { final payload = DatabaseViewIdPB.create()..value = viewId; return DatabaseEventGetDatabaseSetting(payload).send(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/share_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/application/share_bloc.dart index 4abc77aef2..1beaaedbfb 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/share_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/share_bloc.dart @@ -1,12 +1,14 @@ import 'dart:io'; + import 'package:appflowy/workspace/application/settings/share/export_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:dartz/dartz.dart'; +import 'package:freezed_annotation/freezed_annotation.dart'; + part 'share_bloc.freezed.dart'; class DatabaseShareBloc extends Bloc { @@ -35,9 +37,9 @@ class DatabaseShareBloc extends Bloc { result.fold( (l) { _saveCSVToPath(l.data, event.path); - return left(unit); + return FlowyResult.success(null); }, - (r) => right(r), + (r) => FlowyResult.failure(r), ), ), ); @@ -61,6 +63,6 @@ class DatabaseShareState with _$DatabaseShareState { const factory DatabaseShareState.initial() = _Initial; const factory DatabaseShareState.loading() = _Loading; const factory DatabaseShareState.finish( - Either successOrFail, + FlowyResult successOrFail, ) = _Finish; } diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_listener.dart index 64960d087c..83c9310331 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_listener.dart @@ -1,13 +1,14 @@ import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; -typedef SortNotifiedValue = Either; +typedef SortNotifiedValue + = FlowyResult; class SortsListener { SortsListener({required this.viewId}); @@ -29,14 +30,15 @@ class SortsListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateSort: result.fold( - (payload) => _notifier?.value = - left(SortChangesetNotificationPB.fromBuffer(payload)), - (error) => _notifier?.value = right(error), + (payload) => _notifier?.value = FlowyResult.success( + SortChangesetNotificationPB.fromBuffer(payload), + ), + (error) => _notifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_service.dart b/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_service.dart index 72634e67d2..12255afb7f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/sort/sort_service.dart @@ -1,28 +1,28 @@ -import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/setting_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class SortBackendService { SortBackendService({required this.viewId}); final String viewId; - Future, FlowyError>> getAllSorts() { + Future, FlowyError>> getAllSorts() { final payload = DatabaseViewIdPB()..value = viewId; return DatabaseEventGetAllSorts(payload).send().then((result) { return result.fold( - (repeated) => left(repeated.items), - (r) => right(r), + (repeated) => FlowyResult.success(repeated.items), + (r) => FlowyResult.failure(r), ); }); } - Future> updateSort({ + Future> updateSort({ required String sortId, required String fieldId, required SortConditionPB condition, @@ -38,16 +38,16 @@ class SortBackendService { ..updateSort = insertSortPayload; return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( - (l) => left(l), + (l) => FlowyResult.success(l), (err) { Log.error(err); - return right(err); + return FlowyResult.failure(err); }, ); }); } - Future> insertSort({ + Future> insertSort({ required String fieldId, required SortConditionPB condition, }) { @@ -61,16 +61,16 @@ class SortBackendService { ..updateSort = insertSortPayload; return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( - (l) => left(l), + (l) => FlowyResult.success(l), (err) { Log.error(err); - return right(err); + return FlowyResult.failure(err); }, ); }); } - Future> reorderSort({ + Future> reorderSort({ required String fromSortId, required String toSortId, }) { @@ -84,7 +84,7 @@ class SortBackendService { return DatabaseEventUpdateDatabaseSetting(payload).send(); } - Future> deleteSort({ + Future> deleteSort({ required String fieldId, required String sortId, }) { @@ -98,23 +98,23 @@ class SortBackendService { return DatabaseEventUpdateDatabaseSetting(payload).send().then((result) { return result.fold( - (l) => left(l), + (l) => FlowyResult.success(l), (err) { Log.error(err); - return right(err); + return FlowyResult.failure(err); }, ); }); } - Future> deleteAllSorts() { + Future> deleteAllSorts() { final payload = DatabaseViewIdPB(value: viewId); return DatabaseEventDeleteAllSorts(payload).send().then((result) { return result.fold( - (l) => left(l), + (l) => FlowyResult.success(l), (err) { Log.error(err); - return right(err); + return FlowyResult.failure(err); }, ); }); diff --git a/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart b/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart index c07ea4b4c1..595c013904 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/application/view/view_listener.dart @@ -1,19 +1,20 @@ import 'dart:async'; import 'dart:typed_data'; + import 'package:appflowy/core/notification/grid_notification.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart'; -import 'package:dartz/dartz.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/view_entities.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; typedef RowsVisibilityNotifierValue - = Either; + = FlowyResult; -typedef NumberOfRowsNotifierValue = Either; -typedef ReorderAllRowsNotifierValue = Either, FlowyError>; -typedef SingleRowNotifierValue = Either; +typedef NumberOfRowsNotifierValue = FlowyResult; +typedef ReorderAllRowsNotifierValue = FlowyResult, FlowyError>; +typedef SingleRowNotifierValue = FlowyResult; class DatabaseViewListener { DatabaseViewListener({required this.viewId}); @@ -51,34 +52,38 @@ class DatabaseViewListener { _reorderSingleRow?.addPublishListener(onReorderSingleRow); } - void _handler(DatabaseNotification ty, Either result) { + void _handler( + DatabaseNotification ty, + FlowyResult result, + ) { switch (ty) { case DatabaseNotification.DidUpdateViewRowsVisibility: result.fold( (payload) => _rowsVisibility?.value = - left(RowsVisibilityChangePB.fromBuffer(payload)), - (error) => _rowsVisibility?.value = right(error), + FlowyResult.success(RowsVisibilityChangePB.fromBuffer(payload)), + (error) => _rowsVisibility?.value = FlowyResult.failure(error), ); break; case DatabaseNotification.DidUpdateViewRows: result.fold( - (payload) => - _rowsNotifier?.value = left(RowsChangePB.fromBuffer(payload)), - (error) => _rowsNotifier?.value = right(error), + (payload) => _rowsNotifier?.value = + FlowyResult.success(RowsChangePB.fromBuffer(payload)), + (error) => _rowsNotifier?.value = FlowyResult.failure(error), ); break; case DatabaseNotification.DidReorderRows: result.fold( - (payload) => _reorderAllRows?.value = - left(ReorderAllRowsPB.fromBuffer(payload).rowOrders), - (error) => _reorderAllRows?.value = right(error), + (payload) => _reorderAllRows?.value = FlowyResult.success( + ReorderAllRowsPB.fromBuffer(payload).rowOrders, + ), + (error) => _reorderAllRows?.value = FlowyResult.failure(error), ); break; case DatabaseNotification.DidReorderSingleRow: result.fold( (payload) => _reorderSingleRow?.value = - left(ReorderSingleRowPB.fromBuffer(payload)), - (error) => _reorderSingleRow?.value = right(error), + FlowyResult.success(ReorderSingleRowPB.fromBuffer(payload)), + (error) => _reorderSingleRow?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart index e0619f2171..026a1a4db5 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/application/board_bloc.dart @@ -1,8 +1,6 @@ import 'dart:async'; import 'dart:collection'; -import 'package:flutter/foundation.dart'; - import 'package:appflowy/plugins/database/application/defines.dart'; import 'package:appflowy/plugins/database/application/field/field_info.dart'; import 'package:appflowy/plugins/database/application/group/group_service.dart'; @@ -12,7 +10,8 @@ import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_board/appflowy_board.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:protobuf/protobuf.dart' hide FieldInfo; @@ -20,7 +19,6 @@ import 'package:protobuf/protobuf.dart' hide FieldInfo; import '../../application/database_controller.dart'; import '../../application/field/field_controller.dart'; import '../../application/row/row_cache.dart'; - import 'group_controller.dart'; part 'board_bloc.freezed.dart'; @@ -141,10 +139,10 @@ class BoardBloc extends Bloc { _groupItemStartEditing(group, row, true); }, didReceiveGridUpdate: (DatabasePB grid) { - emit(state.copyWith(grid: Some(grid))); + emit(state.copyWith(grid: grid)); }, didReceiveError: (FlowyError error) { - emit(state.copyWith(noneOrError: some(error))); + emit(state.copyWith(noneOrError: error)); }, didReceiveGroups: (List groups) { final hiddenGroups = _filterHiddenGroups(hideUngrouped, groups); @@ -450,11 +448,15 @@ class BoardBloc extends Bloc { (grid) { databaseController.setIsLoading(false); emit( - state.copyWith(loadingState: LoadingState.finish(left(unit))), + state.copyWith( + loadingState: LoadingState.finish(FlowyResult.success(null)), + ), ); }, (err) => emit( - state.copyWith(loadingState: LoadingState.finish(right(err))), + state.copyWith( + loadingState: LoadingState.finish(FlowyResult.failure(err)), + ), ), ); } @@ -543,12 +545,12 @@ class BoardEvent with _$BoardEvent { class BoardState with _$BoardState { const factory BoardState({ required String viewId, - required Option grid, + required DatabasePB? grid, required List groupIds, required bool isEditingHeader, required bool isEditingRow, required LoadingState loadingState, - required Option noneOrError, + required FlowyError? noneOrError, required BoardLayoutSettingPB? layoutSettings, String? editingHeaderId, BoardEditingRow? editingRow, @@ -557,12 +559,12 @@ class BoardState with _$BoardState { }) = _BoardState; factory BoardState.initial(String viewId) => BoardState( - grid: none(), + grid: null, viewId: viewId, groupIds: [], isEditingHeader: false, isEditingRow: false, - noneOrError: none(), + noneOrError: null, loadingState: const LoadingState.loading(), layoutSettings: null, hiddenGroups: [], diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/application/group_controller.dart b/frontend/appflowy_flutter/lib/plugins/database/board/application/group_controller.dart index 9f7511dbb1..5f1b8c9609 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/application/group_controller.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/application/group_controller.dart @@ -1,12 +1,12 @@ -import 'package:appflowy/plugins/database/application/row/row_service.dart'; -import 'package:appflowy_backend/log.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'dart:typed_data'; import 'package:appflowy/core/notification/grid_notification.dart'; +import 'package:appflowy/plugins/database/application/row/row_service.dart'; +import 'package:appflowy_backend/log.dart'; +import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flowy_infra/notifier.dart'; -import 'package:dartz/dartz.dart'; import 'package:protobuf/protobuf.dart'; typedef OnGroupError = void Function(FlowyError); @@ -112,7 +112,8 @@ class GroupController { } } -typedef UpdateGroupNotifiedValue = Either; +typedef UpdateGroupNotifiedValue + = FlowyResult; class SingleGroupListener { SingleGroupListener(this.group); @@ -134,14 +135,14 @@ class SingleGroupListener { void _handler( DatabaseNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DatabaseNotification.DidUpdateGroupRow: result.fold( (payload) => _groupNotifier?.value = - left(GroupRowsNotificationPB.fromBuffer(payload)), - (error) => _groupNotifier?.value = right(error), + FlowyResult.success(GroupRowsNotificationPB.fromBuffer(payload)), + (error) => _groupNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/plugins/database/board/application/toolbar/board_setting_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/board/application/toolbar/board_setting_bloc.dart index 3c4c2abb3a..ea2e1b9314 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/board/application/toolbar/board_setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/board/application/toolbar/board_setting_bloc.dart @@ -1,4 +1,3 @@ -import 'package:dartz/dartz.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -11,7 +10,7 @@ class BoardSettingBloc extends Bloc { (event, emit) async { event.when( performAction: (action) { - emit(state.copyWith(selectedAction: Some(action))); + emit(state.copyWith(selectedAction: action)); }, ); }, @@ -30,11 +29,11 @@ class BoardSettingEvent with _$BoardSettingEvent { @freezed class BoardSettingState with _$BoardSettingState { const factory BoardSettingState({ - required Option selectedAction, + required BoardSettingAction? selectedAction, }) = _BoardSettingState; - factory BoardSettingState.initial() => BoardSettingState( - selectedAction: none(), + factory BoardSettingState.initial() => const BoardSettingState( + selectedAction: null, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/application/calendar_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/application/calendar_bloc.dart index 8826621778..b8edc4229f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/application/calendar_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/application/calendar_bloc.dart @@ -7,8 +7,8 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:calendar_view/calendar_view.dart'; -import 'package:dartz/dartz.dart'; import 'package:fixnum/fixnum.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -44,15 +44,13 @@ class CalendarBloc extends Bloc { }, didReceiveCalendarSettings: (CalendarLayoutSettingPB settings) { // If the field id changed, reload all events - state.settings.fold(() => null, (oldSetting) { - if (oldSetting.fieldId != settings.fieldId) { - _loadAllEvents(); - } - }); - emit(state.copyWith(settings: Some(settings))); + if (state.settings?.fieldId != settings.fieldId) { + _loadAllEvents(); + } + emit(state.copyWith(settings: settings)); }, didReceiveDatabaseUpdate: (DatabasePB database) { - emit(state.copyWith(database: Some(database))); + emit(state.copyWith(database: database)); }, didLoadAllEvents: (events) { final calenderEvents = _calendarEventDataFromEventPBs(events); @@ -132,45 +130,47 @@ class CalendarBloc extends Bloc { (database) { databaseController.setIsLoading(false); emit( - state.copyWith(loadingState: LoadingState.finish(left(unit))), + state.copyWith( + loadingState: LoadingState.finish(FlowyResult.success(null)), + ), ); }, (err) => emit( - state.copyWith(loadingState: LoadingState.finish(right(err))), + state.copyWith( + loadingState: LoadingState.finish(FlowyResult.failure(err)), + ), ), ); } Future _createEvent(DateTime date) async { - return state.settings.fold( - () { - Log.warn('Calendar settings not found'); - }, - (settings) async { - final dateField = _getCalendarFieldInfo(settings.fieldId); - if (dateField != null) { - final newRow = await RowBackendService.createRow( - viewId: viewId, - withCells: (builder) => builder.insertDate(dateField, date), - ).then( - (result) => result.fold( - (newRow) => newRow, - (err) { - Log.error(err); - return null; - }, - ), - ); + final settings = state.settings; + if (settings == null) { + Log.warn('Calendar settings not found'); + return; + } + final dateField = _getCalendarFieldInfo(settings.fieldId); + if (dateField != null) { + final newRow = await RowBackendService.createRow( + viewId: viewId, + withCells: (builder) => builder.insertDate(dateField, date), + ).then( + (result) => result.fold( + (newRow) => newRow, + (err) { + Log.error(err); + return null; + }, + ), + ); - if (newRow != null) { - final event = await _loadEvent(newRow.id); - if (event != null && !isClosed) { - add(CalendarEvent.didCreateEvent(event)); - } - } + if (newRow != null) { + final event = await _loadEvent(newRow.id); + if (event != null && !isClosed) { + add(CalendarEvent.didCreateEvent(event)); } - }, - ); + } + } } Future _moveEvent(CalendarDayEvent event, DateTime date) async { @@ -412,7 +412,7 @@ class CalendarEvent with _$CalendarEvent { @freezed class CalendarState with _$CalendarState { const factory CalendarState({ - required Option database, + required DatabasePB? database, // events by row id required Events allEvents, required Events initialEvents, @@ -420,19 +420,19 @@ class CalendarState with _$CalendarState { CalendarEventData? newEvent, CalendarEventData? updateEvent, required List deleteEventIds, - required Option settings, + required CalendarLayoutSettingPB? settings, required LoadingState loadingState, - required Option noneOrError, + required FlowyError? noneOrError, }) = _CalendarState; - factory CalendarState.initial() => CalendarState( - database: none(), + factory CalendarState.initial() => const CalendarState( + database: null, allEvents: [], initialEvents: [], deleteEventIds: [], - settings: none(), - noneOrError: none(), - loadingState: const LoadingState.loading(), + settings: null, + noneOrError: null, + loadingState: LoadingState.loading(), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/application/unschedule_event_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/application/unschedule_event_bloc.dart index 9b3dff7d2b..208906f00b 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/application/unschedule_event_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/application/unschedule_event_bloc.dart @@ -5,7 +5,6 @@ import 'package:appflowy/plugins/database/application/row/row_service.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; -import 'package:dartz/dartz.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -160,13 +159,13 @@ class UnscheduleEventsEvent with _$UnscheduleEventsEvent { @freezed class UnscheduleEventsState with _$UnscheduleEventsState { const factory UnscheduleEventsState({ - required Option database, + required DatabasePB? database, required List allEvents, required List unscheduleEvents, }) = _UnscheduleEventsState; - factory UnscheduleEventsState.initial() => UnscheduleEventsState( - database: none(), + factory UnscheduleEventsState.initial() => const UnscheduleEventsState( + database: null, allEvents: [], unscheduleEvents: [], ); diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart index 64ca08e00a..40769d2303 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_event_card.dart @@ -145,10 +145,7 @@ class _EventCardState extends State { margin: EdgeInsets.zero, offset: const Offset(10.0, 0), popupBuilder: (BuildContext popoverContext) { - final settings = context.watch().state.settings.fold( - () => null, - (layoutSettings) => layoutSettings, - ); + final settings = context.watch().state.settings; if (settings == null) { return const SizedBox.shrink(); } diff --git a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart index 9382ad3de5..1d1a147026 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/calendar/presentation/calendar_page.dart @@ -1,5 +1,3 @@ -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'; @@ -20,12 +18,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'; @@ -167,8 +165,7 @@ class _CalendarPageState extends State { return _buildCalendar( context, _eventController, - state.settings - .foldLeft(0, (previous, a) => a.firstDayOfWeek), + state.settings?.firstDayOfWeek ?? 0, ); }, ); diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/application/calculations/calculations_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/application/calculations/calculations_bloc.dart index 28d8b820e8..e41fa61b2f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/application/calculations/calculations_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/application/calculations/calculations_bloc.dart @@ -2,7 +2,6 @@ import 'package:appflowy/plugins/database/application/calculations/calculations_ import 'package:appflowy/plugins/database/application/calculations/calculations_service.dart'; import 'package:appflowy/plugins/database/application/field/field_controller.dart'; import 'package:appflowy/plugins/database/application/field/field_info.dart'; -import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/calculation_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_settings_entities.pbenum.dart'; import 'package:bloc/bloc.dart'; @@ -133,7 +132,7 @@ class CalculationsBloc extends Bloc { final calculationsOrFailure = await _calculationsService.getCalculations(); final RepeatedCalculationsPB? calculations = - calculationsOrFailure.getLeftOrNull(); + calculationsOrFailure.fold((s) => s, (e) => null); if (calculations != null) { final calculationMap = {}; for (final calculation in calculations.items) { diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_create_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_create_bloc.dart index 57d1d1deb5..624ef06d6a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_create_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/application/filter/filter_create_bloc.dart @@ -11,7 +11,7 @@ import 'package:appflowy_backend/protobuf/flowy-database2/number_filter.pb.dart' import 'package:appflowy_backend/protobuf/flowy-database2/select_option_filter.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/text_filter.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -91,7 +91,9 @@ class GridCreateFilterBloc fieldController.addListener(onReceiveFields: _onFieldFn); } - Future> _createDefaultFilter(FieldInfo field) async { + Future> _createDefaultFilter( + FieldInfo field, + ) async { final fieldId = field.id; switch (field.fieldType) { case FieldType.Checkbox: @@ -144,7 +146,7 @@ class GridCreateFilterBloc ); } - return left(unit); + return FlowyResult.success(null); } @override diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/application/grid_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/application/grid_bloc.dart index d7a5d901fa..01178d9b3f 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/application/grid_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/application/grid_bloc.dart @@ -9,7 +9,7 @@ import 'package:appflowy/plugins/database/grid/presentation/widgets/sort/sort_in import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -65,7 +65,7 @@ class GridBloc extends Bloc { databaseController.moveRow(fromRowId: fromRow, toRowId: toRow); }, didReceiveGridUpdate: (grid) { - emit(state.copyWith(grid: Some(grid))); + emit(state.copyWith(grid: grid)); }, didReceiveFieldUpdate: (fields) { emit( @@ -147,11 +147,15 @@ class GridBloc extends Bloc { (grid) { databaseController.setIsLoading(false); emit( - state.copyWith(loadingState: LoadingState.finish(left(unit))), + state.copyWith( + loadingState: LoadingState.finish(FlowyResult.success(null)), + ), ); }, (err) => emit( - state.copyWith(loadingState: LoadingState.finish(right(err))), + state.copyWith( + loadingState: LoadingState.finish(FlowyResult.failure(err)), + ), ), ); } @@ -186,7 +190,7 @@ class GridEvent with _$GridEvent { class GridState with _$GridState { const factory GridState({ required String viewId, - required Option grid, + required DatabasePB? grid, required List fields, required List rowInfos, required int rowCount, @@ -204,7 +208,7 @@ class GridState with _$GridState { rowInfos: [], rowCount: 0, createdRow: null, - grid: none(), + grid: null, viewId: viewId, reorderable: true, loadingState: const LoadingState.loading(), diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/application/sort/sort_create_bloc.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/application/sort/sort_create_bloc.dart index cdeb37bd88..22dabf671a 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/application/sort/sort_create_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/application/sort/sort_create_bloc.dart @@ -4,13 +4,12 @@ import 'package:appflowy/plugins/database/application/field/field_info.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/sort_entities.pbserver.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import '../../../application/field/field_controller.dart'; import '../../../application/sort/sort_service.dart'; - import 'util.dart'; part 'sort_create_bloc.freezed.dart'; @@ -88,7 +87,9 @@ class CreateSortBloc extends Bloc { fieldController.addListener(onReceiveFields: _onFieldFn); } - Future> _createDefaultSort(FieldInfo field) async { + Future> _createDefaultSort( + FieldInfo field, + ) async { final result = await _sortBackendSvc.insertSort( fieldId: field.id, condition: SortConditionPB.Ascending, diff --git a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/type_option/select/select_option.dart b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/type_option/select/select_option.dart index 90e32c9225..619260a631 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/type_option/select/select_option.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/grid/presentation/widgets/header/type_option/select/select_option.dart @@ -1,17 +1,17 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/database/application/field/type_option/select_option_type_option_bloc.dart'; import 'package:appflowy/plugins/database/application/field/type_option/select_type_option_actions.dart'; import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart'; import 'package:appflowy/plugins/database/widgets/cell_editor/extension.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.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:flowy_infra_ui/style_widget/hover.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:appflowy/generated/locale_keys.g.dart'; import 'select_option_editor.dart'; @@ -218,7 +218,7 @@ class _CreateOptionTextFieldState extends State { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - final text = state.newOptionName.foldRight("", (a, previous) => a); + final text = state.newOptionName ?? ''; return Padding( padding: const EdgeInsets.symmetric(horizontal: 14.0), child: FlowyTextField( diff --git a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart index a047f64de3..1ea14faaa9 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/tab_bar/tab_bar_view.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/plugins/database/application/database_controller.dart'; import 'package:appflowy/plugins/database/application/tab_bar_bloc.dart'; import 'package:appflowy/plugins/database/grid/presentation/layout/sizes.dart'; @@ -12,6 +10,7 @@ import 'package:appflowy/workspace/presentation/widgets/view_title_bar.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'desktop/tab_bar_header.dart'; @@ -221,11 +220,10 @@ class DatabasePluginWidgetBuilder extends PluginWidgetBuilder { @override Widget buildWidget({PluginContext? context, required bool shrinkWrap}) { notifier.isDeleted.addListener(() { - notifier.isDeleted.value.fold(() => null, (deletedView) { - if (deletedView.hasIndex()) { - context?.onDeleted(notifier.view, deletedView.index); - } - }); + final deletedView = notifier.isDeleted.value; + if (deletedView != null && deletedView.hasIndex()) { + context?.onDeleted(notifier.view, deletedView.index); + } }); return DatabaseTabBarView( key: ValueKey(notifier.view.id), diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart index 3b759295c7..71cce3a114 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/mobile_select_option_editor.dart @@ -260,17 +260,15 @@ class _OptionList extends StatelessWidget { final List cells = []; // create an option cell - state.createOption.fold( - () => null, - (createOption) { - cells.add( - _CreateOptionCell( - optionName: createOption, - onTap: () => onCreateOption(createOption), - ), - ); - }, - ); + final createOption = state.createOption; + if (createOption != null) { + cells.add( + _CreateOptionCell( + optionName: createOption, + onTap: () => onCreateOption(createOption), + ), + ); + } cells.addAll( state.options.map( diff --git a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_editor.dart b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_editor.dart index f10f83fcc0..a71e783dac 100644 --- a/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_editor.dart +++ b/frontend/appflowy_flutter/lib/plugins/database/widgets/cell_editor/select_option_editor.dart @@ -12,11 +12,11 @@ import 'package:flowy_infra_ui/style_widget/hover.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import '../../application/cell/bloc/select_option_editor_bloc.dart'; import '../../grid/presentation/layout/sizes.dart'; import '../../grid/presentation/widgets/common/type_option_separator.dart'; import '../../grid/presentation/widgets/header/type_option/select/select_option_editor.dart'; import 'extension.dart'; -import '../../application/cell/bloc/select_option_editor_bloc.dart'; import 'select_option_text_field.dart'; const double _editorPanelWidth = 300; @@ -95,12 +95,10 @@ class _OptionList extends StatelessWidget { ), ]; - state.createOption.fold( - () => null, - (createOption) { - cells.add(_CreateOptionCell(name: createOption)); - }, - ); + final createOption = state.createOption; + if (createOption != null) { + cells.add(_CreateOptionCell(name: createOption)); + } return ListView.separated( shrinkWrap: true, diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart index 99eaba7d96..e85a6567f8 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/doc_bloc.dart @@ -1,7 +1,5 @@ import 'dart:async'; -import 'package:flutter/foundation.dart'; - import 'package:appflowy/plugins/document/application/doc_service.dart'; import 'package:appflowy/plugins/document/application/document_data_pb_extension.dart'; import 'package:appflowy/plugins/document/application/editor_transaction_adapter.dart'; @@ -23,7 +21,8 @@ import 'package:appflowy_editor/appflowy_editor.dart' Selection, Position, paragraphNode; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flutter/foundation.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -77,25 +76,28 @@ class DocumentBloc extends Bloc { _onViewChanged(); _onDocumentChanged(); await editorState.fold( - (l) async => emit( - state.copyWith( - error: l, - editorState: null, - isLoading: false, - ), - ), - (r) async { + (s) async { final result = await getIt().getUser(); - final userProfilePB = result.fold((l) => null, (r) => r); + final userProfilePB = result.fold( + (s) => s, + (e) => null, + ); emit( state.copyWith( error: null, - editorState: r, + editorState: s, isLoading: false, userProfilePB: userProfilePB, ), ); }, + (f) async => emit( + state.copyWith( + error: f, + editorState: null, + isLoading: false, + ), + ), ); }, moveToTrash: () async { @@ -124,13 +126,12 @@ class DocumentBloc extends Bloc { void _onViewChanged() { _viewListener.start( onViewMoveToTrash: (r) { - r.swap().map((r) => add(const DocumentEvent.moveToTrash())); + r.map((r) => add(const DocumentEvent.moveToTrash())); }, onViewDeleted: (r) { - r.swap().map((r) => add(const DocumentEvent.moveToTrash())); + r.map((r) => add(const DocumentEvent.moveToTrash())); }, - onViewRestored: (r) => - r.swap().map((r) => add(const DocumentEvent.restore())), + onViewRestored: (r) => r.map((r) => add(const DocumentEvent.restore())), ); } @@ -150,11 +151,11 @@ class DocumentBloc extends Bloc { } /// Fetch document - Future> _fetchDocumentState() async { + Future> _fetchDocumentState() async { final result = await _documentService.openDocument(viewId: view.id); return result.fold( - (l) => left(l), - (r) async => right(await _initAppFlowyEditorState(r)), + (s) async => FlowyResult.success(await _initAppFlowyEditorState(s)), + (e) => FlowyResult.failure(e), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart b/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart index 9009ea52ff..31497e85ac 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/doc_service.dart @@ -2,56 +2,56 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class DocumentService { // unused now. - Future> createDocument({ + Future> createDocument({ required ViewPB view, }) async { final canOpen = await openDocument(viewId: view.id); - if (canOpen.isRight()) { - return const Right(unit); + if (canOpen.isSuccess()) { + return FlowyResult.success(null); } final payload = CreateDocumentPayloadPB()..documentId = view.id; final result = await DocumentEventCreateDocument(payload).send(); - return result.swap(); + return result; } - Future> openDocument({ + Future> openDocument({ required String viewId, }) async { final payload = OpenDocumentPayloadPB()..documentId = viewId; final result = await DocumentEventOpenDocument(payload).send(); - return result.swap(); + return result; } - Future> getBlockFromDocument({ + Future> getBlockFromDocument({ required DocumentDataPB document, required String blockId, }) async { final block = document.blocks[blockId]; if (block != null) { - return right(block); + return FlowyResult.success(block); } - return left( + return FlowyResult.failure( FlowyError( msg: 'Block($blockId) not found in Document(${document.pageId})', ), ); } - Future> closeDocument({ + Future> closeDocument({ required ViewPB view, }) async { final payload = CloseDocumentPayloadPB()..documentId = view.id; final result = await DocumentEventCloseDocument(payload).send(); - return result.swap(); + return result; } - Future> applyAction({ + Future> applyAction({ required String documentId, required Iterable actions, }) async { @@ -60,7 +60,7 @@ class DocumentService { actions: actions, ); final result = await DocumentEventApplyAction(payload).send(); - return result.swap(); + return result; } /// Creates a new external text. @@ -68,7 +68,7 @@ class DocumentService { /// Normally, it's used to the block that needs sync long text. /// /// the delta parameter is the json representation of the delta. - Future> createExternalText({ + Future> createExternalText({ required String documentId, required String textId, String? delta, @@ -79,7 +79,7 @@ class DocumentService { delta: delta, ); final result = await DocumentEventCreateText(payload).send(); - return result.swap(); + return result; } /// Updates the external text. @@ -87,7 +87,7 @@ class DocumentService { /// this function is compatible with the [createExternalText] function. /// /// the delta parameter is the json representation of the delta too. - Future> updateExternalText({ + Future> updateExternalText({ required String documentId, required String textId, String? delta, @@ -98,11 +98,11 @@ class DocumentService { delta: delta, ); final result = await DocumentEventApplyTextDeltaEvent(payload).send(); - return result.swap(); + return result; } /// Upload a file to the cloud storage. - Future> uploadFile({ + Future> uploadFile({ required String localFilePath, bool isAsync = true, }) async { @@ -114,14 +114,14 @@ class DocumentService { isAsync: isAsync, ); final result = await DocumentEventUploadFile(payload).send(); - return result.swap(); + return result; }, (r) async { - return left(FlowyError(msg: 'Workspace not found')); + return FlowyResult.failure(FlowyError(msg: 'Workspace not found')); }); } /// Download a file from the cloud storage. - Future> downloadFile({ + Future> downloadFile({ required String url, }) async { final workspace = await FolderEventReadCurrentWorkspace().send(); @@ -130,9 +130,9 @@ class DocumentService { url: url, ); final result = await DocumentEventDownloadFile(payload).send(); - return result.swap(); + return result; }, (r) async { - return left(FlowyError(msg: 'Workspace not found')); + return FlowyResult.failure(FlowyError(msg: 'Workspace not found')); }); } } diff --git a/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart index 2a9f881073..0760749c12 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/application/share_bloc.dart @@ -4,7 +4,7 @@ import 'package:appflowy/workspace/application/export/document_exporter.dart'; import 'package:appflowy_backend/protobuf/flowy-document/entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -28,8 +28,9 @@ class DocShareBloc extends Bloc { emit( DocShareState.finish( result.fold( - (error) => right(error), - (markdown) => left(_saveMarkdownToPath(markdown, event.path)), + (markdown) => + FlowyResult.success(_saveMarkdownToPath(markdown, event.path)), + (error) => FlowyResult.failure(error), ), ), ); @@ -55,6 +56,6 @@ class DocShareState with _$DocShareState { const factory DocShareState.initial() = _Initial; const factory DocShareState.loading() = _Loading; const factory DocShareState.finish( - Either successOrFail, + FlowyResult successOrFail, ) = _Finish; } diff --git a/frontend/appflowy_flutter/lib/plugins/document/document.dart b/frontend/appflowy_flutter/lib/plugins/document/document.dart index e6b0abebe2..829248653b 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/document.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/document.dart @@ -1,14 +1,12 @@ library document_plugin; -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/document_page.dart'; +import 'package:appflowy/plugins/document/presentation/favorite/favorite_button.dart'; import 'package:appflowy/plugins/document/presentation/more/cubit/document_appearance_cubit.dart'; import 'package:appflowy/plugins/document/presentation/more/more_button.dart'; import 'package:appflowy/plugins/document/presentation/share/share_button.dart'; -import 'package:appflowy/plugins/document/presentation/favorite/favorite_button.dart'; import 'package:appflowy/plugins/util.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/presentation/home/home_stack.dart'; @@ -18,6 +16,7 @@ import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.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'; class DocumentPluginBuilder extends PluginBuilder { @@ -90,14 +89,10 @@ class DocumentPluginWidgetBuilder extends PluginWidgetBuilder @override Widget buildWidget({PluginContext? context, required bool shrinkWrap}) { notifier.isDeleted.addListener(() { - notifier.isDeleted.value.fold( - () => null, - (deletedView) { - if (deletedView.hasIndex()) { - deletedViewIndex = deletedView.index; - } - }, - ); + final deletedView = notifier.isDeleted.value; + if (deletedView != null && deletedView.hasIndex()) { + deletedViewIndex = deletedView.index; + } }); return BlocBuilder( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart index 6535904a43..d7e8194867 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/built_in_page_widget.dart @@ -1,23 +1,22 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/plugins.dart'; import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/application/tabs/tabs_bloc.dart'; +import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:appflowy/workspace/presentation/widgets/pop_up_action.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; -import 'package:dartz/dartz.dart' as dartz; +import 'package:appflowy_popover/appflowy_popover.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/style_widget/icon_button.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; -import 'package:appflowy/generated/locale_keys.g.dart'; -import 'package:easy_localization/easy_localization.dart'; - -import 'package:appflowy/workspace/application/view/view_ext.dart'; -import 'package:appflowy_popover/appflowy_popover.dart'; -import 'package:flowy_infra_ui/style_widget/icon_button.dart'; class BuiltInPageWidget extends StatefulWidget { const BuiltInPageWidget({ @@ -36,7 +35,8 @@ class BuiltInPageWidget extends StatefulWidget { } class _BuiltInPageWidgetState extends State { - late Future> future; + late Future> future; + final focusNode = FocusNode(); String get parentViewId => widget.node.attributes[DatabaseBlockKeys.parentID]; @@ -45,14 +45,10 @@ class _BuiltInPageWidgetState extends State { @override void initState() { super.initState(); - future = ViewBackendService() - .getChildView( - parentViewId: parentViewId, - childViewId: childViewId, - ) - .then( - (value) => value.swap(), - ); + future = ViewBackendService().getChildView( + parentViewId: parentViewId, + childViewId: childViewId, + ); } @override @@ -63,9 +59,9 @@ class _BuiltInPageWidgetState extends State { @override Widget build(BuildContext context) { - return FutureBuilder>( + return FutureBuilder>( builder: (context, snapshot) { - final page = snapshot.data?.toOption().toNullable(); + final page = snapshot.data?.toNullable(); if (snapshot.hasData && page != null) { return _build(context, page); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/insert_page_command.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/insert_page_command.dart index 721210d93d..eadb5b43a1 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/insert_page_command.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/base/insert_page_command.dart @@ -87,7 +87,7 @@ extension InsertDatabase on EditorState { // get the database id that the view is associated with final databaseId = await DatabaseViewBackendService(viewId: view.id) .getDatabaseId() - .then((value) => value.swap().toOption().toNullable()); + .then((value) => value.toNullable()); if (databaseId == null) { throw StateError( @@ -101,7 +101,7 @@ extension InsertDatabase on EditorState { name: "$prefix ${view.name}", layoutType: view.layout, databaseId: databaseId, - ).then((value) => value.swap().toOption().toNullable()); + ).then((value) => value.toNullable()); if (ref == null) { throw FlowyError( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/database/inline_database_menu_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/database/inline_database_menu_item.dart index 989abcc3ec..ff5df802d1 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/database/inline_database_menu_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/database/inline_database_menu_item.dart @@ -25,7 +25,7 @@ SelectionMenuItem inlineGridMenuItem(DocumentBloc documentBloc) => name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), layoutType: ViewLayoutPB.Grid, ); - value.swap().map((r) => editorState.insertInlinePage(parentViewId, r)); + value.map((r) => editorState.insertInlinePage(parentViewId, r)); }, ); @@ -46,7 +46,7 @@ SelectionMenuItem inlineBoardMenuItem(DocumentBloc documentBloc) => name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), layoutType: ViewLayoutPB.Board, ); - value.swap().map((r) => editorState.insertInlinePage(parentViewId, r)); + value.map((r) => editorState.insertInlinePage(parentViewId, r)); }, ); @@ -68,6 +68,6 @@ SelectionMenuItem inlineCalendarMenuItem(DocumentBloc documentBloc) => name: LocaleKeys.menuAppHeader_defaultNewPageName.tr(), layoutType: ViewLayoutPB.Calendar, ); - value.swap().map((r) => editorState.insertInlinePage(parentViewId, r)); + value.map((r) => editorState.insertInlinePage(parentViewId, r)); }, ); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart index 09b0ac3bec..560661d157 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker.dart @@ -1,18 +1,18 @@ import 'dart:io'; + import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart'; import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; -import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; - import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/style_widget/button.dart'; +import 'package:flowy_infra_ui/style_widget/snap_bar.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/rounded_button.dart'; +import 'package:flowy_infra_ui/widget/spacing.dart'; import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; class CoverImagePicker extends StatefulWidget { const CoverImagePicker({ @@ -37,12 +37,13 @@ class _CoverImagePickerState extends State { child: BlocListener( listener: (context, state) { if (state is NetworkImagePicked) { - state.successOrFail.isRight() - ? showSnapBar( - context, - LocaleKeys.document_plugins_cover_invalidImageUrl.tr(), - ) - : null; + state.successOrFail.fold( + (s) {}, + (e) => showSnapBar( + context, + LocaleKeys.document_plugins_cover_invalidImageUrl.tr(), + ), + ); } if (state is Done) { state.successOrFail.fold( diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart index 72147e49c2..316f2ddd8f 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/header/custom_cover_picker_bloc.dart @@ -4,7 +4,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/workspace/application/settings/prelude.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/file_picker/file_picker_service.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -36,11 +36,15 @@ class CoverImagePickerBloc emit(const CoverImagePickerState.loading()); final validateImage = await _validateURL(urlSubmit.path); if (validateImage) { - emit(CoverImagePickerState.networkImage(left(urlSubmit.path))); + emit( + CoverImagePickerState.networkImage( + FlowyResult.success(urlSubmit.path), + ), + ); } else { emit( CoverImagePickerState.networkImage( - right( + FlowyResult.failure( FlowyError( msg: LocaleKeys.document_plugins_cover_couldNotFetchImage .tr(), @@ -65,11 +69,11 @@ class CoverImagePickerBloc emit(const CoverImagePickerState.loading()); final saveImage = await _saveToGallery(saveToGallery.previousState); if (saveImage != null) { - emit(CoverImagePickerState.done(left(saveImage))); + emit(CoverImagePickerState.done(FlowyResult.success(saveImage))); } else { emit( CoverImagePickerState.done( - right( + FlowyResult.failure( FlowyError( msg: LocaleKeys.document_plugins_cover_imageSavingFailed .tr(), @@ -208,11 +212,11 @@ class CoverImagePickerState with _$CoverImagePickerState { const factory CoverImagePickerState.initial() = Initial; const factory CoverImagePickerState.loading() = Loading; const factory CoverImagePickerState.networkImage( - Either successOrFail, + FlowyResult successOrFail, ) = NetworkImagePicked; const factory CoverImagePickerState.fileImage(String path) = FileImagePicked; const factory CoverImagePickerState.done( - Either, FlowyError> successOrFail, + FlowyResult, FlowyError> successOrFail, ) = Done; } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/image_util.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/image_util.dart index d6a31bb7ea..c03ce0b5ae 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/image_util.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/image_util.dart @@ -43,13 +43,13 @@ Future<(String? path, String? errorMessage)> saveImageToCloudStorage( isAsync: false, ); return result.fold( - (l) => (null, l.msg), - (r) async { + (s) async { await CustomImageCacheManager().putFile( - r.url, + s.url, File(localImagePath).readAsBytesSync(), ); - return (r.url, null); + return (s.url, null); }, + (e) => (null, e.msg), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/open_ai_image_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/open_ai_image_widget.dart index 775b6f273d..9cd6320518 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/open_ai_image_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/open_ai_image_widget.dart @@ -4,7 +4,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/error.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart'; import 'package:appflowy/startup/startup.dart'; -import 'package:dartz/dartz.dart' hide State; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flutter/material.dart'; @@ -22,7 +22,7 @@ class OpenAIImageWidget extends StatefulWidget { } class _OpenAIImageWidgetState extends State { - Future>>? future; + Future, OpenAIError>>? future; String query = ''; @override @@ -63,19 +63,12 @@ class _OpenAIImageWidgetState extends State { return const CircularProgressIndicator.adaptive(); } return data.fold( - (l) => Center( - child: FlowyText( - l.message, - maxLines: 3, - textAlign: TextAlign.center, - ), - ), - (r) => GridView.count( + (s) => GridView.count( crossAxisCount: 3, mainAxisSpacing: 16.0, crossAxisSpacing: 10.0, childAspectRatio: 4 / 3, - children: r + children: s .map( (e) => GestureDetector( onTap: () => widget.onSelectNetworkImage(e), @@ -84,6 +77,13 @@ class _OpenAIImageWidgetState extends State { ) .toList(), ), + (e) => Center( + child: FlowyText( + e.message, + maxLines: 3, + textAlign: TextAlign.center, + ), + ), ); }, ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/stability_ai_image_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/stability_ai_image_widget.dart index d1764a76ac..0d5d986d10 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/stability_ai_image_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/stability_ai_image_widget.dart @@ -6,7 +6,7 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart'; import 'package:appflowy/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_error.dart'; import 'package:appflowy/startup/startup.dart'; -import 'package:dartz/dartz.dart' hide State; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/uuid.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -27,7 +27,7 @@ class StabilityAIImageWidget extends StatefulWidget { } class _StabilityAIImageWidgetState extends State { - Future>>? future; + Future, StabilityAIRequestError>>? future; String query = ''; @override @@ -70,19 +70,12 @@ class _StabilityAIImageWidgetState extends State { return const CircularProgressIndicator.adaptive(); } return data.fold( - (l) => Center( - child: FlowyText( - l.message, - maxLines: 3, - textAlign: TextAlign.center, - ), - ), - (r) => GridView.count( + (s) => GridView.count( crossAxisCount: 3, mainAxisSpacing: 16.0, crossAxisSpacing: 10.0, childAspectRatio: 4 / 3, - children: r.map( + children: s.map( (e) { final base64Image = base64Decode(e); return GestureDetector( @@ -100,6 +93,13 @@ class _StabilityAIImageWidgetState extends State { }, ).toList(), ), + (e) => Center( + child: FlowyText( + e.message, + maxLines: 3, + textAlign: TextAlign.center, + ), + ), ); }, ), diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/upload_image_menu.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/upload_image_menu.dart index fab96db524..4c9de6b07d 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/upload_image_menu.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/image/upload_image_menu.dart @@ -76,12 +76,12 @@ class _UploadImageMenuState extends State { UserBackendService.getCurrentUserProfile().then( (value) { final supportOpenAI = value.fold( - (l) => false, - (r) => r.openaiKey.isNotEmpty, + (s) => s.openaiKey.isNotEmpty, + (e) => false, ); final supportStabilityAI = value.fold( - (l) => false, - (r) => r.stabilityAiKey.isNotEmpty, + (s) => s.stabilityAiKey.isNotEmpty, + (e) => false, ); if (supportOpenAI != this.supportOpenAI || supportStabilityAI != this.supportStabilityAI) { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/link_preview/link_preview_cache.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/link_preview/link_preview_cache.dart index 51454f5c14..6688cfe304 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/link_preview/link_preview_cache.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/link_preview/link_preview_cache.dart @@ -12,7 +12,7 @@ class LinkPreviewDataCache implements LinkPreviewDataCacheInterface { url, (value) => LinkPreviewData.fromJson(jsonDecode(value)), ); - return option.fold(() => null, (a) => a); + return option; } @override diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart index 8d6457c650..fc32143ff9 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/mention/mention_page_block.dart @@ -126,7 +126,7 @@ class _MentionPageBlockState extends State { Future fetchView(String pageId) async { final view = await ViewBackendService.getView(pageId).then( - (value) => value.swap().toOption().toNullable(), + (value) => value.toNullable(), ); if (view == null) { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart index 45e8aa3eaf..60306540a8 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/service/openai_client.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:appflowy/plugins/document/presentation/editor_plugins/openai/service/text_edit.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:http/http.dart' as http; import 'error.dart'; @@ -33,7 +33,7 @@ abstract class OpenAIRepository { /// [maxTokens] is the maximum number of tokens to generate /// [temperature] is the temperature of the model /// - Future> getCompletions({ + Future> getCompletions({ required String prompt, String? suffix, int maxTokens = 2048, @@ -58,7 +58,7 @@ abstract class OpenAIRepository { /// [instruction] is the instruction text /// [temperature] is the temperature of the model /// - Future> getEdits({ + Future> getEdits({ required String input, required String instruction, double temperature = 0.3, @@ -70,7 +70,7 @@ abstract class OpenAIRepository { /// [n] is the number of images to generate /// /// the result is a list of urls - Future>> generateImage({ + Future, OpenAIError>> generateImage({ required String prompt, int n = 1, }); @@ -91,7 +91,7 @@ class HttpOpenAIRepository implements OpenAIRepository { }; @override - Future> getCompletions({ + Future> getCompletions({ required String prompt, String? suffix, int maxTokens = 2048, @@ -113,7 +113,7 @@ class HttpOpenAIRepository implements OpenAIRepository { ); if (response.statusCode == 200) { - return Right( + return FlowyResult.success( TextCompletionResponse.fromJson( json.decode( utf8.decode(response.bodyBytes), @@ -121,7 +121,9 @@ class HttpOpenAIRepository implements OpenAIRepository { ), ); } else { - return Left(OpenAIError.fromJson(json.decode(response.body)['error'])); + return FlowyResult.failure( + OpenAIError.fromJson(json.decode(response.body)['error']), + ); } } @@ -206,7 +208,7 @@ class HttpOpenAIRepository implements OpenAIRepository { } @override - Future> getEdits({ + Future> getEdits({ required String input, required String instruction, double temperature = 0.3, @@ -227,7 +229,7 @@ class HttpOpenAIRepository implements OpenAIRepository { ); if (response.statusCode == 200) { - return Right( + return FlowyResult.success( TextEditResponse.fromJson( json.decode( utf8.decode(response.bodyBytes), @@ -235,12 +237,14 @@ class HttpOpenAIRepository implements OpenAIRepository { ), ); } else { - return Left(OpenAIError.fromJson(json.decode(response.body)['error'])); + return FlowyResult.failure( + OpenAIError.fromJson(json.decode(response.body)['error']), + ); } } @override - Future>> generateImage({ + Future, OpenAIError>> generateImage({ required String prompt, int n = 1, }) async { @@ -266,12 +270,14 @@ class HttpOpenAIRepository implements OpenAIRepository { .expand((e) => e) .map((e) => e.toString()) .toList(); - return Right(urls); + return FlowyResult.success(urls); } else { - return Left(OpenAIError.fromJson(json.decode(response.body)['error'])); + return FlowyResult.failure( + OpenAIError.fromJson(json.decode(response.body)['error']), + ); } } catch (error) { - return Left(OpenAIError(message: error.toString())); + return FlowyResult.failure(OpenAIError(message: error.toString())); } } } diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/auto_completion_node_widget.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/auto_completion_node_widget.dart index 56eed31926..7f8778b39e 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/auto_completion_node_widget.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/auto_completion_node_widget.dart @@ -193,7 +193,7 @@ class _AutoCompletionBlockComponentState await _updateEditingText(); final userProfile = await UserBackendService.getCurrentUserProfile() - .then((value) => value.toOption().toNullable()); + .then((value) => value.toNullable()); if (userProfile == null) { await loading.stop(); if (mounted) { @@ -290,7 +290,7 @@ class _AutoCompletionBlockComponentState } // generate new response final userProfile = await UserBackendService.getCurrentUserProfile() - .then((value) => value.toOption().toNullable()); + .then((value) => value.toNullable()); if (userProfile == null) { await loading.stop(); if (mounted) { diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_toolbar_item.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_toolbar_item.dart index a25966c342..a0f7002889 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_toolbar_item.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/openai/widgets/smart_edit_toolbar_item.dart @@ -41,8 +41,8 @@ class _SmartEditActionListState extends State { UserBackendService.getCurrentUserProfile().then((value) { setState(() { isOpenAIEnabled = value.fold( - (l) => false, - (r) => r.openaiKey.isNotEmpty, + (s) => s.openaiKey.isNotEmpty, + (_) => false, ); }); }); diff --git a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart index 7cae9c11b9..c3cbd11c97 100644 --- a/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart +++ b/frontend/appflowy_flutter/lib/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_client.dart @@ -2,7 +2,7 @@ import 'dart:async'; import 'dart:convert'; import 'package:appflowy/plugins/document/presentation/editor_plugins/stability_ai/stability_ai_error.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:http/http.dart' as http; enum StabilityAIRequestType { @@ -25,7 +25,7 @@ abstract class StabilityAIRepository { /// [n] is the number of images to generate /// /// the return value is a list of base64 encoded images - Future>> generateImage({ + Future, StabilityAIRequestError>> generateImage({ required String prompt, int n = 1, }); @@ -46,7 +46,7 @@ class HttpStabilityAIRepository implements StabilityAIRepository { }; @override - Future>> generateImage({ + Future, StabilityAIRequestError>> generateImage({ required String prompt, int n = 1, }) async { @@ -76,16 +76,16 @@ class HttpStabilityAIRepository implements StabilityAIRepository { (e) => e['base64'].toString(), ) .toList(); - return Right(base64Images); + return FlowyResult.success(base64Images); } else { - return Left( + return FlowyResult.failure( StabilityAIRequestError( data['message'].toString(), ), ); } } catch (error) { - return Left( + return FlowyResult.failure( StabilityAIRequestError( error.toString(), ), diff --git a/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/date_reference.dart b/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/date_reference.dart index 75ac0ead28..6d5012a5d6 100644 --- a/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/date_reference.dart +++ b/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/date_reference.dart @@ -92,8 +92,8 @@ class DateReferenceService { final result = await DateService.queryDate(search); result.fold( - (l) {}, (date) => options.insert(0, _itemFromDate(date)), + (_) {}, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/reminder_reference.dart b/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/reminder_reference.dart index bf06b8e096..cbb2c5e007 100644 --- a/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/reminder_reference.dart +++ b/frontend/appflowy_flutter/lib/plugins/inline_actions/handlers/reminder_reference.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/date/date_service.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/plugins/document/application/doc_bloc.dart'; @@ -13,6 +11,7 @@ import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:fixnum/fixnum.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:nanoid/nanoid.dart'; @@ -111,13 +110,13 @@ class ReminderReferenceService { final result = await DateService.queryDate(search); result.fold( - (l) {}, (date) { // Only insert dates in the future if (DateTime.now().isBefore(date)) { options.insert(0, _itemFromDate(date)); } }, + (_) {}, ); } diff --git a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart index c2ce55cf10..64ce2940c5 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_bloc.dart @@ -3,7 +3,7 @@ import 'package:appflowy/plugins/trash/application/trash_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -26,13 +26,15 @@ class TrashBloc extends Bloc { initial: (e) async { _listener.start(trashUpdated: _listenTrashUpdated); final result = await _service.readTrash(); + emit( result.fold( (object) => state.copyWith( objects: object.items, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ), - (error) => state.copyWith(successOrFailure: right(error)), + (error) => + state.copyWith(successOrFailure: FlowyResult.failure(error)), ), ); }, @@ -60,18 +62,20 @@ class TrashBloc extends Bloc { } Future _handleResult( - Either result, + FlowyResult result, Emitter emit, ) async { emit( result.fold( - (l) => state.copyWith(successOrFailure: left(unit)), - (error) => state.copyWith(successOrFailure: right(error)), + (l) => state.copyWith(successOrFailure: FlowyResult.success(null)), + (error) => state.copyWith(successOrFailure: FlowyResult.failure(error)), ), ); } - void _listenTrashUpdated(Either, FlowyError> trashOrFailed) { + void _listenTrashUpdated( + FlowyResult, FlowyError> trashOrFailed, + ) { trashOrFailed.fold( (trash) { add(TrashEvent.didReceiveTrash(trash)); @@ -103,11 +107,11 @@ class TrashEvent with _$TrashEvent { class TrashState with _$TrashState { const factory TrashState({ required List objects, - required Either successOrFailure, + required FlowyResult successOrFailure, }) = _TrashState; factory TrashState.init() => TrashState( objects: [], - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ); } diff --git a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart index eddf355166..1d1a8f1ed8 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_listener.dart @@ -1,15 +1,16 @@ import 'dart:async'; import 'dart:typed_data'; + import 'package:appflowy/core/notification/folder_notification.dart'; -import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; typedef TrashUpdatedCallback = void Function( - Either, FlowyError> trashOrFailed, + FlowyResult, FlowyError> trashOrFailed, ); class TrashListener { @@ -29,7 +30,7 @@ class TrashListener { void _observableCallback( FolderNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case FolderNotification.DidUpdateTrash: @@ -37,9 +38,9 @@ class TrashListener { result.fold( (payload) { final repeatedTrash = RepeatedTrashPB.fromBuffer(payload); - _trashUpdated!(left(repeatedTrash.items)); + _trashUpdated!(FlowyResult.success(repeatedTrash.items)); }, - (error) => _trashUpdated!(right(error)), + (error) => _trashUpdated!(FlowyResult.failure(error)), ); } break; diff --git a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart index 96ae6be339..b6d319009b 100644 --- a/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart +++ b/frontend/appflowy_flutter/lib/plugins/trash/application/trash_service.dart @@ -1,21 +1,22 @@ import 'dart:async'; -import 'package:dartz/dartz.dart'; + import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/trash.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class TrashService { - Future> readTrash() { + Future> readTrash() { return FolderEventListTrashItems().send(); } - Future> putback(String trashId) { + Future> putback(String trashId) { final id = TrashIdPB.create()..id = trashId; return FolderEventRestoreTrashItem(id).send(); } - Future> deleteViews(List trash) { + Future> deleteViews(List trash) { final items = trash.map((trash) { return TrashIdPB.create()..id = trash; }); @@ -24,11 +25,11 @@ class TrashService { return FolderEventPermanentlyDeleteTrashItem(ids).send(); } - Future> restoreAll() { + Future> restoreAll() { return FolderEventRecoverAllTrashItems().send(); } - Future> deleteAll() { + Future> deleteAll() { return FolderEventPermanentlyDeleteAllTrashItem().send(); } } diff --git a/frontend/appflowy_flutter/lib/plugins/util.dart b/frontend/appflowy_flutter/lib/plugins/util.dart index 7c7c3c317f..d7ec567abe 100644 --- a/frontend/appflowy_flutter/lib/plugins/util.dart +++ b/frontend/appflowy_flutter/lib/plugins/util.dart @@ -1,18 +1,17 @@ import 'package:appflowy/startup/plugin/plugin.dart'; import 'package:appflowy/workspace/application/view/view_listener.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:flutter/material.dart'; -class ViewPluginNotifier extends PluginNotifier> { +class ViewPluginNotifier extends PluginNotifier { ViewPluginNotifier({ required this.view, }) : _viewListener = ViewListener(viewId: view.id) { _viewListener?.start( onViewUpdated: (updatedView) => view = updatedView, onViewMoveToTrash: (result) => result.fold( - (deletedView) => isDeleted.value = some(deletedView), + (deletedView) => isDeleted.value = deletedView, (err) => Log.error(err), ), ); @@ -22,7 +21,7 @@ class ViewPluginNotifier extends PluginNotifier> { final ViewListener? _viewListener; @override - final ValueNotifier> isDeleted = ValueNotifier(none()); + final ValueNotifier isDeleted = ValueNotifier(null); @override void dispose() { diff --git a/frontend/appflowy_flutter/lib/startup/deps_resolver.dart b/frontend/appflowy_flutter/lib/startup/deps_resolver.dart index 5abfc34b79..adca53db85 100644 --- a/frontend/appflowy_flutter/lib/startup/deps_resolver.dart +++ b/frontend/appflowy_flutter/lib/startup/deps_resolver.dart @@ -90,15 +90,15 @@ void _resolveCommonService( () async { final result = await UserBackendService.getCurrentUserProfile(); return result.fold( - (l) { - throw Exception('Failed to get user profile: ${l.msg}'); - }, - (r) { + (s) { return HttpOpenAIRepository( client: http.Client(), - apiKey: r.openaiKey, + apiKey: s.openaiKey, ); }, + (e) { + throw Exception('Failed to get user profile: ${e.msg}'); + }, ); }, ); @@ -107,15 +107,15 @@ void _resolveCommonService( () async { final result = await UserBackendService.getCurrentUserProfile(); return result.fold( - (l) { - throw Exception('Failed to get user profile: ${l.msg}'); - }, - (r) { + (s) { return HttpStabilityAIRepository( client: http.Client(), - apiKey: r.stabilityAiKey, + apiKey: s.stabilityAiKey, ); }, + (e) { + throw Exception('Failed to get user profile: ${e.msg}'); + }, ); }, ); diff --git a/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart b/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart index 9683039465..d8723ac232 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/app_window_size_manager.dart @@ -32,7 +32,7 @@ class WindowSizeManager { final defaultWindowSize = jsonEncode({height: 600.0, width: 800.0}); final windowSize = await getIt().get(KVKeys.windowSize); final size = json.decode( - windowSize.getOrElse(() => defaultWindowSize), + windowSize ?? defaultWindowSize, ); return Size(size[width]!, size[height]!); } @@ -49,12 +49,10 @@ class WindowSizeManager { Future getPosition() async { final position = await getIt().get(KVKeys.windowPosition); - return position.fold( - () => null, - (r) { - final offset = json.decode(r); - return Offset(offset[dx], offset[dy]); - }, - ); + if (position == null) { + return null; + } + final offset = json.decode(position); + return Offset(offset[dx], offset[dy]); } } diff --git a/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart b/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart index 4a52c109f7..7f174428bf 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/appflowy_cloud_task.dart @@ -16,7 +16,7 @@ import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter/material.dart'; import 'package:url_protocol/url_protocol.dart'; @@ -29,7 +29,7 @@ class AppFlowyCloudDeepLink { await _handleUri(uri); }, onError: (Object err, StackTrace stackTrace) { - Log.error('on deeplink stream error: ${err.toString()}', stackTrace); + Log.error('on DeepLink stream error: ${err.toString()}', stackTrace); _deeplinkSubscription?.cancel(); _deeplinkSubscription = null; }, @@ -46,7 +46,7 @@ class AppFlowyCloudDeepLink { final _appLinks = AppLinks(); ValueNotifier? _stateNotifier = ValueNotifier(null); - Completer>? _completer; + Completer>? _completer; // The AppLinks is a singleton, so we need to cancel the previous subscription // before creating a new one. @@ -58,8 +58,8 @@ class AppFlowyCloudDeepLink { _stateNotifier = null; } - void resigerCompleter( - Completer> completer, + void registerCompleter( + Completer> completer, ) { _completer = completer; } @@ -86,11 +86,11 @@ class AppFlowyCloudDeepLink { _stateNotifier?.value = DeepLinkResult(state: DeepLinkState.none); if (uri == null) { - Log.error('onDeepLinkError: Unexpect empty deep link callback'); - _completer?.complete(left(AuthError.emptyDeeplink)); + Log.error('onDeepLinkError: Unexpected empty deep link callback'); + _completer?.complete(FlowyResult.failure(AuthError.emptyDeepLink)); _completer = null; } - return _isAuthCallbackDeeplink(uri!).fold( + return _isAuthCallbackDeepLink(uri!).fold( (_) async { final deviceId = await getDeviceId(); final payload = OauthSignInPB( @@ -101,9 +101,8 @@ class AppFlowyCloudDeepLink { }, ); _stateNotifier?.value = DeepLinkResult(state: DeepLinkState.loading); - final result = await UserEventOauthSignIn(payload) - .send() - .then((value) => value.swap()); + final result = + await UserEventOauthSignIn(payload).send().then((value) => value); _stateNotifier?.value = DeepLinkResult( state: DeepLinkState.finish, @@ -112,6 +111,9 @@ class AppFlowyCloudDeepLink { // If there is no completer, runAppFlowy() will be called. if (_completer == null) { await result.fold( + (_) async { + await runAppFlowy(); + }, (err) { Log.error(err); final context = AppGlobals.rootNavKey.currentState?.context; @@ -122,9 +124,6 @@ class AppFlowyCloudDeepLink { ); } }, - (_) async { - await runAppFlowy(); - }, ); } else { _completer?.complete(result); @@ -132,7 +131,7 @@ class AppFlowyCloudDeepLink { } }, (err) { - Log.error('onDeepLinkError: Unexpect deep link: $err'); + Log.error('onDeepLinkError: Unexpected deep link: $err'); if (_completer == null) { final context = AppGlobals.rootNavKey.currentState?.context; if (context != null) { @@ -142,19 +141,19 @@ class AppFlowyCloudDeepLink { ); } } else { - _completer?.complete(left(err)); + _completer?.complete(FlowyResult.failure(err)); _completer = null; } }, ); } - Either<(), FlowyError> _isAuthCallbackDeeplink(Uri uri) { + FlowyResult _isAuthCallbackDeepLink(Uri uri) { if (uri.fragment.contains('access_token')) { - return left(()); + return FlowyResult.success(null); } - return right( + return FlowyResult.failure( FlowyError.create() ..code = ErrorCode.MissingAuthField ..msg = uri.path, @@ -197,7 +196,7 @@ class DeepLinkResult { DeepLinkResult({required this.state, this.result}); final DeepLinkState state; - final Either? result; + final FlowyResult? result; } enum DeepLinkState { diff --git a/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart b/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart index 3ba8f4bf70..05de151b7a 100644 --- a/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart +++ b/frontend/appflowy_flutter/lib/startup/tasks/generate_router.dart @@ -580,8 +580,8 @@ GoRoute _rootRoute(Widget child) { // Every time before navigating to splash screen, we check if user is already logged in in desktop. It is used to skip showing splash screen when user just changes apperance settings like theme mode. final userResponse = await getIt().getUser(); final routeName = userResponse.fold( - (error) => null, (user) => DesktopHomeScreen.routeName, + (error) => null, ); if (routeName != null && !PlatformExtension.isMobile) return routeName; diff --git a/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart index 737de56eb7..0140316ed2 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_auth_service.dart @@ -2,13 +2,13 @@ import 'dart:async'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/tasks/appflowy_cloud_task.dart'; -import 'package:appflowy/user/application/auth/backend_auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; +import 'package:appflowy/user/application/auth/backend_auth_service.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:url_launcher/url_launcher.dart'; import 'auth_error.dart'; @@ -21,7 +21,7 @@ class AppFlowyCloudAuthService implements AuthService { ); @override - Future> signUp({ + Future> signUp({ required String name, required String email, required String password, @@ -31,7 +31,7 @@ class AppFlowyCloudAuthService implements AuthService { } @override - Future> signInWithEmailPassword({ + Future> signInWithEmailPassword({ required String email, required String password, Map params = const {}, @@ -40,7 +40,7 @@ class AppFlowyCloudAuthService implements AuthService { } @override - Future> signUpWithOAuth({ + Future> signUpWithOAuth({ required String platform, Map params = const {}, }) async { @@ -61,22 +61,23 @@ class AppFlowyCloudAuthService implements AuthService { webOnlyWindowName: '_self', ); - final completer = Completer>(); + final completer = Completer>(); if (isSuccess) { // The [AppFlowyCloudDeepLink] must be registered before using the // [AppFlowyCloudAuthService]. if (getIt.isRegistered()) { - getIt().resigerCompleter(completer); + getIt().registerCompleter(completer); } else { throw Exception('AppFlowyCloudDeepLink is not registered'); } } else { - completer.complete(left(AuthError.signInWithOauthError)); + completer + .complete(FlowyResult.failure(AuthError.signInWithOauthError)); } return completer.future; }, - (r) => left(r), + (r) => FlowyResult.failure(r), ); } @@ -86,14 +87,14 @@ class AppFlowyCloudAuthService implements AuthService { } @override - Future> signUpAsGuest({ + Future> signUpAsGuest({ Map params = const {}, }) async { return _backendAuthService.signUpAsGuest(); } @override - Future> signInWithMagicLink({ + Future> signInWithMagicLink({ required String email, Map params = const {}, }) async { @@ -101,7 +102,7 @@ class AppFlowyCloudAuthService implements AuthService { } @override - Future> getUser() async { + Future> getUser() async { return UserBackendService.getCurrentUserProfile(); } } diff --git a/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_mock_auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_mock_auth_service.dart index df6dc89eb1..deba0f3700 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_mock_auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/af_cloud_mock_auth_service.dart @@ -1,14 +1,14 @@ import 'dart:async'; -import 'package:appflowy/user/application/auth/backend_auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; +import 'package:appflowy/user/application/auth/backend_auth_service.dart'; import 'package:appflowy/user/application/auth/device_id.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flowy_infra/uuid.dart'; /// Only used for testing. @@ -22,7 +22,7 @@ class AppFlowyCloudMockAuthService implements AuthService { BackendAuthService(AuthenticatorPB.Supabase); @override - Future> signUp({ + Future> signUp({ required String name, required String email, required String password, @@ -32,7 +32,7 @@ class AppFlowyCloudMockAuthService implements AuthService { } @override - Future> signInWithEmailPassword({ + Future> signInWithEmailPassword({ required String email, required String password, Map params = const {}, @@ -41,7 +41,7 @@ class AppFlowyCloudMockAuthService implements AuthService { } @override - Future> signUpWithOAuth({ + Future> signUpWithOAuth({ required String platform, Map params = const {}, }) async { @@ -65,12 +65,12 @@ class AppFlowyCloudMockAuthService implements AuthService { Log.info("UserEventOauthSignIn with payload: $payload"); return UserEventOauthSignIn(payload).send().then((value) { value.fold((l) => null, (err) => Log.error(err)); - return value.swap(); + return value; }); }, (r) { Log.error(r); - return left(r); + return FlowyResult.failure(r); }, ); } @@ -81,14 +81,14 @@ class AppFlowyCloudMockAuthService implements AuthService { } @override - Future> signUpAsGuest({ + Future> signUpAsGuest({ Map params = const {}, }) async { return _appFlowyAuthService.signUpAsGuest(); } @override - Future> signInWithMagicLink({ + Future> signInWithMagicLink({ required String email, Map params = const {}, }) async { @@ -96,7 +96,7 @@ class AppFlowyCloudMockAuthService implements AuthService { } @override - Future> getUser() async { + Future> getUser() async { return UserBackendService.getCurrentUserProfile(); } } diff --git a/frontend/appflowy_flutter/lib/user/application/auth/auth_error.dart b/frontend/appflowy_flutter/lib/user/application/auth/auth_error.dart index 1415672d78..2d9858c717 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/auth_error.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/auth_error.dart @@ -22,11 +22,11 @@ class AuthError { ..msg = 'sign in with oauth error -10003' ..code = ErrorCode.UserUnauthorized; - static final emptyDeeplink = FlowyError() - ..msg = 'Unexpected empty deeplink' - ..code = ErrorCode.UnexpectedEmpty; + static final emptyDeepLink = FlowyError() + ..msg = 'Unexpected empty DeepLink' + ..code = ErrorCode.UnexpectedCalendarFieldType; - static final deeplinkError = FlowyError() - ..msg = 'Deeplink error' + static final deepLinkError = FlowyError() + ..msg = 'DeepLink error' ..code = ErrorCode.Internal; } diff --git a/frontend/appflowy_flutter/lib/user/application/auth/auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/auth_service.dart index 82fecd6715..201b682484 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/auth_service.dart @@ -1,6 +1,6 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pbserver.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class AuthServiceMapKeys { const AuthServiceMapKeys._(); @@ -25,7 +25,7 @@ abstract class AuthService { /// /// Returns [UserProfilePB] if the user is authenticated, otherwise returns [FlowyError]. - Future> signInWithEmailPassword({ + Future> signInWithEmailPassword({ required String email, required String password, Map params, @@ -39,7 +39,7 @@ abstract class AuthService { /// - `params`: Additional parameters for registration (optional). /// /// Returns [UserProfilePB] if the user is authenticated, otherwise returns [FlowyError]. - Future> signUp({ + Future> signUp({ required String name, required String email, required String password, @@ -52,7 +52,7 @@ abstract class AuthService { /// - `params`: Additional parameters for OAuth registration (optional). /// /// Returns [UserProfilePB] if the user is authenticated, otherwise returns [FlowyError]. - Future> signUpWithOAuth({ + Future> signUpWithOAuth({ required String platform, Map params, }); @@ -62,7 +62,7 @@ abstract class AuthService { /// - `params`: Additional parameters for guest registration (optional). /// /// Returns a default [UserProfilePB]. - Future> signUpAsGuest({ + Future> signUpAsGuest({ Map params, }); @@ -72,7 +72,7 @@ abstract class AuthService { /// - `params`: Additional parameters for authentication with magic link (optional). /// /// Returns [UserProfilePB] if the user is authenticated, otherwise returns [FlowyError]. - Future> signInWithMagicLink({ + Future> signInWithMagicLink({ required String email, Map params, }); @@ -83,5 +83,5 @@ abstract class AuthService { /// Retrieves the currently authenticated user's profile. /// /// Returns [UserProfilePB] if the user has signed in, otherwise returns [FlowyError]. - Future> getUser(); + Future> getUser(); } diff --git a/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart index 2c60e3e674..c130a98d45 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/backend_auth_service.dart @@ -1,14 +1,14 @@ import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/user_service.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart'; -import 'package:appflowy_backend/protobuf/flowy-user/auth.pb.dart'; -import 'package:dartz/dartz.dart'; -import 'package:easy_localization/easy_localization.dart'; -import 'package:flowy_infra/uuid.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/code.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/auth.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show SignInPayloadPB, SignUpPayloadPB, UserProfilePB; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra/uuid.dart'; import '../../../generated/locale_keys.g.dart'; import 'device_id.dart'; @@ -19,7 +19,7 @@ class BackendAuthService implements AuthService { final AuthenticatorPB authType; @override - Future> signInWithEmailPassword({ + Future> signInWithEmailPassword({ required String email, required String password, Map params = const {}, @@ -30,11 +30,11 @@ class BackendAuthService implements AuthService { ..authType = authType ..deviceId = await getDeviceId(); final response = UserEventSignInWithEmailPassword(request).send(); - return response.then((value) => value.swap()); + return response.then((value) => value); } @override - Future> signUp({ + Future> signUp({ required String name, required String email, required String password, @@ -47,7 +47,7 @@ class BackendAuthService implements AuthService { ..authType = authType ..deviceId = await getDeviceId(); final response = await UserEventSignUp(request).send().then( - (value) => value.swap(), + (value) => value, ); return response; } @@ -61,7 +61,7 @@ class BackendAuthService implements AuthService { } @override - Future> signUpAsGuest({ + Future> signUpAsGuest({ Map params = const {}, }) async { const password = "Guest!@123456"; @@ -76,18 +76,18 @@ class BackendAuthService implements AuthService { ..authType = AuthenticatorPB.Local ..deviceId = await getDeviceId(); final response = await UserEventSignUp(request).send().then( - (value) => value.swap(), + (value) => value, ); return response; } @override - Future> signUpWithOAuth({ + Future> signUpWithOAuth({ required String platform, AuthenticatorPB authType = AuthenticatorPB.Local, Map params = const {}, }) async { - return left( + return FlowyResult.failure( FlowyError.create() ..code = ErrorCode.Internal ..msg = "Unsupported sign up action", @@ -95,16 +95,16 @@ class BackendAuthService implements AuthService { } @override - Future> getUser() async { + Future> getUser() async { return UserBackendService.getCurrentUserProfile(); } @override - Future> signInWithMagicLink({ + Future> signInWithMagicLink({ required String email, Map params = const {}, }) async { - return left( + return FlowyResult.failure( FlowyError.create() ..code = ErrorCode.Internal ..msg = "Unsupported sign up action", diff --git a/frontend/appflowy_flutter/lib/user/application/auth/supabase_auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/supabase_auth_service.dart index 38b3980711..0dc48d7ef7 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/supabase_auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/supabase_auth_service.dart @@ -9,7 +9,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter/foundation.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; @@ -26,7 +26,7 @@ class SupabaseAuthService implements AuthService { ); @override - Future> signUp({ + Future> signUp({ required String name, required String email, required String password, @@ -39,7 +39,7 @@ class SupabaseAuthService implements AuthService { ); final uuid = response.user?.id; if (uuid == null) { - return left(AuthError.supabaseSignUpError); + return FlowyResult.failure(AuthError.supabaseSignUpError); } // assign the uuid to our backend service. // and will transfer this logic to backend later. @@ -54,7 +54,7 @@ class SupabaseAuthService implements AuthService { } @override - Future> signInWithEmailPassword({ + Future> signInWithEmailPassword({ required String email, required String password, Map params = const {}, @@ -66,7 +66,7 @@ class SupabaseAuthService implements AuthService { ); final uuid = response.user?.id; if (uuid == null) { - return Left(AuthError.supabaseSignInError); + return FlowyResult.failure(AuthError.supabaseSignInError); } return _backendAuthService.signInWithEmailPassword( email: email, @@ -77,12 +77,12 @@ class SupabaseAuthService implements AuthService { ); } on AuthException catch (e) { Log.error(e); - return Left(AuthError.supabaseSignInError); + return FlowyResult.failure(AuthError.supabaseSignInError); } } @override - Future> signUpWithOAuth({ + Future> signUpWithOAuth({ required String platform, Map params = const {}, }) async { @@ -110,7 +110,9 @@ class SupabaseAuthService implements AuthService { redirectTo: supabaseLoginCallback, ); if (!response) { - completer.complete(left(AuthError.supabaseSignInWithOauthError)); + completer.complete( + FlowyResult.failure(AuthError.supabaseSignInWithOauthError), + ); } return completer.future; } @@ -122,7 +124,7 @@ class SupabaseAuthService implements AuthService { } @override - Future> signUpAsGuest({ + Future> signUpAsGuest({ Map params = const {}, }) async { // supabase don't support guest login. @@ -131,7 +133,7 @@ class SupabaseAuthService implements AuthService { } @override - Future> signInWithMagicLink({ + Future> signInWithMagicLink({ required String email, Map params = const {}, }) async { @@ -155,19 +157,19 @@ class SupabaseAuthService implements AuthService { } @override - Future> getUser() async { + Future> getUser() async { return UserBackendService.getCurrentUserProfile(); } - Future> getSupabaseUser() async { + Future> getSupabaseUser() async { final user = _auth.currentUser; if (user == null) { - return left(AuthError.supabaseGetUserError); + return FlowyResult.failure(AuthError.supabaseGetUserError); } - return Right(user); + return FlowyResult.success(user); } - Future> _setupAuth({ + Future> _setupAuth({ required Map map, }) async { final payload = OauthSignInPB( @@ -175,7 +177,7 @@ class SupabaseAuthService implements AuthService { map: map, ); - return UserEventOauthSignIn(payload).send().then((value) => value.swap()); + return UserEventOauthSignIn(payload).send().then((value) => value); } } @@ -208,15 +210,15 @@ extension on String { /// a `FlowyError` or a `UserProfilePB`. /// /// Returns: -/// A completer of type `Either`. This completer completes +/// A completer of type `FlowyResult`. This completer completes /// with the response from the [onSuccess] callback when a user signs in. -Completer> supabaseLoginCompleter({ - required Future> Function( +Completer> supabaseLoginCompleter({ + required Future> Function( String userId, String userEmail, ) onSuccess, }) { - final completer = Completer>(); + final completer = Completer>(); late final StreamSubscription subscription; final auth = Supabase.instance.client.auth; diff --git a/frontend/appflowy_flutter/lib/user/application/auth/supabase_mock_auth_service.dart b/frontend/appflowy_flutter/lib/user/application/auth/supabase_mock_auth_service.dart index 829c825e4c..bd2620caaa 100644 --- a/frontend/appflowy_flutter/lib/user/application/auth/supabase_mock_auth_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/auth/supabase_mock_auth_service.dart @@ -1,13 +1,13 @@ import 'dart:async'; -import 'package:appflowy/user/application/auth/backend_auth_service.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; +import 'package:appflowy/user/application/auth/backend_auth_service.dart'; import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:supabase_flutter/supabase_flutter.dart'; import 'auth_error.dart'; @@ -24,7 +24,7 @@ class SupabaseMockAuthService implements AuthService { BackendAuthService(AuthenticatorPB.Supabase); @override - Future> signUp({ + Future> signUp({ required String name, required String email, required String password, @@ -34,7 +34,7 @@ class SupabaseMockAuthService implements AuthService { } @override - Future> signInWithEmailPassword({ + Future> signInWithEmailPassword({ required String email, required String password, Map params = const {}, @@ -43,7 +43,7 @@ class SupabaseMockAuthService implements AuthService { } @override - Future> signUpWithOAuth({ + Future> signUpWithOAuth({ required String platform, Map params = const {}, }) async { @@ -58,7 +58,7 @@ class SupabaseMockAuthService implements AuthService { ); } catch (e) { Log.error(e); - return Left(AuthError.supabaseSignUpError); + return FlowyResult.failure(AuthError.supabaseSignUpError); } } // Check if the user is already logged in. @@ -76,10 +76,10 @@ class SupabaseMockAuthService implements AuthService { ); // Send the sign-in event and handle the response. - return UserEventOauthSignIn(payload).send().then((value) => value.swap()); + return UserEventOauthSignIn(payload).send().then((value) => value); } on AuthException catch (e) { Log.error(e); - return Left(AuthError.supabaseSignInError); + return FlowyResult.failure(AuthError.supabaseSignInError); } } @@ -90,7 +90,7 @@ class SupabaseMockAuthService implements AuthService { } @override - Future> signUpAsGuest({ + Future> signUpAsGuest({ Map params = const {}, }) async { // supabase don't support guest login. @@ -99,7 +99,7 @@ class SupabaseMockAuthService implements AuthService { } @override - Future> signInWithMagicLink({ + Future> signInWithMagicLink({ required String email, Map params = const {}, }) async { @@ -107,7 +107,7 @@ class SupabaseMockAuthService implements AuthService { } @override - Future> getUser() async { + Future> getUser() async { return UserBackendService.getCurrentUserProfile(); } } diff --git a/frontend/appflowy_flutter/lib/user/application/encrypt_secret_bloc.dart b/frontend/appflowy_flutter/lib/user/application/encrypt_secret_bloc.dart index 023b8f6056..19b8101ae8 100644 --- a/frontend/appflowy_flutter/lib/user/application/encrypt_secret_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/encrypt_secret_bloc.dart @@ -3,7 +3,7 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -39,7 +39,7 @@ class EncryptSecretBloc extends Bloc { emit( state.copyWith( loadingState: const LoadingState.loading(), - successOrFail: none(), + successOrFail: null, ), ); }, @@ -47,26 +47,26 @@ class EncryptSecretBloc extends Bloc { await getIt().signOut(); emit( state.copyWith( - successOrFail: none(), + successOrFail: null, isSignOut: true, ), ); }, - didFinishCheck: (Either result) { + didFinishCheck: (result) { result.fold( (unit) { emit( state.copyWith( loadingState: const LoadingState.loading(), - successOrFail: Some(result), + successOrFail: result, ), ); }, (err) { emit( state.copyWith( - loadingState: LoadingState.finish(right(err)), - successOrFail: Some(result), + loadingState: LoadingState.finish(FlowyResult.failure(err)), + successOrFail: result, ), ); }, @@ -94,7 +94,7 @@ class EncryptSecretEvent with _$EncryptSecretEvent { const factory EncryptSecretEvent.setEncryptSecret(String secret) = _SetEncryptSecret; const factory EncryptSecretEvent.didFinishCheck( - Either result, + FlowyResult result, ) = _DidFinishCheck; const factory EncryptSecretEvent.cancelInputSecret() = _CancelInputSecret; } @@ -102,13 +102,13 @@ class EncryptSecretEvent with _$EncryptSecretEvent { @freezed class EncryptSecretState with _$EncryptSecretState { const factory EncryptSecretState({ - required Option> successOrFail, + required FlowyResult? successOrFail, required bool isSignOut, LoadingState? loadingState, }) = _EncryptSecretState; - factory EncryptSecretState.initial() => EncryptSecretState( - successOrFail: none(), + factory EncryptSecretState.initial() => const EncryptSecretState( + successOrFail: null, isSignOut: false, ); } diff --git a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart index abb6903de7..a7fb47b405 100644 --- a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_bloc.dart @@ -59,8 +59,8 @@ class ReminderBloc extends Bloc { final remindersOrFailure = await _reminderService.fetchReminders(); remindersOrFailure.fold( - (error) => Log.error(error), (reminders) => emit(state.copyWith(reminders: reminders)), + (error) => Log.error(error), ); }, remove: (reminderId) async { @@ -68,12 +68,12 @@ class ReminderBloc extends Bloc { await _reminderService.removeReminder(reminderId: reminderId); unitOrFailure.fold( - (error) => Log.error(error), (_) { final reminders = [...state.reminders]; reminders.removeWhere((e) => e.id == reminderId); emit(state.copyWith(reminders: reminders)); }, + (error) => Log.error(error), ); }, add: (reminder) async { @@ -81,11 +81,11 @@ class ReminderBloc extends Bloc { await _reminderService.addReminder(reminder: reminder); return unitOrFailure.fold( - (error) => Log.error(error), (_) { final reminders = [...state.reminders, reminder]; emit(state.copyWith(reminders: reminders)); }, + (error) => Log.error(error), ); }, addById: (reminderId, objectId, scheduledAt, meta) async => add( @@ -115,7 +115,6 @@ class ReminderBloc extends Bloc { ); failureOrUnit.fold( - (error) => Log.error(error), (_) { final index = state.reminders.indexWhere((r) => r.id == reminder.id); @@ -123,6 +122,7 @@ class ReminderBloc extends Bloc { reminders.replaceRange(index, index + 1, [newReminder]); emit(state.copyWith(reminders: reminders)); }, + (error) => Log.error(error), ); }, pressReminder: (reminderId, path, view) { diff --git a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_service.dart b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_service.dart index 4b9aaf1fb3..eed44f9ced 100644 --- a/frontend/appflowy_flutter/lib/user/application/reminder/reminder_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/reminder/reminder_service.dart @@ -1,19 +1,23 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; /// Interface for a Reminder Service that handles /// communication to the backend /// abstract class IReminderService { - Future>> fetchReminders(); + Future, FlowyError>> fetchReminders(); - Future> removeReminder({required String reminderId}); + Future> removeReminder({ + required String reminderId, + }); - Future> addReminder({required ReminderPB reminder}); + Future> addReminder({ + required ReminderPB reminder, + }); - Future> updateReminder({ + Future> updateReminder({ required ReminderPB reminder, }); } @@ -22,37 +26,40 @@ class ReminderService implements IReminderService { const ReminderService(); @override - Future> addReminder({ + Future> addReminder({ required ReminderPB reminder, }) async { final unitOrFailure = await UserEventCreateReminder(reminder).send(); - return unitOrFailure.swap(); + return unitOrFailure; } @override - Future> updateReminder({ + Future> updateReminder({ required ReminderPB reminder, }) async { final unitOrFailure = await UserEventUpdateReminder(reminder).send(); - return unitOrFailure.swap(); + return unitOrFailure; } @override - Future>> fetchReminders() async { + Future, FlowyError>> fetchReminders() async { final resultOrFailure = await UserEventGetAllReminders().send(); - return resultOrFailure.swap().fold((l) => left(l), (r) => right(r.items)); + return resultOrFailure.fold( + (s) => FlowyResult.success(s.items), + (e) => FlowyResult.failure(e), + ); } @override - Future> removeReminder({ + Future> removeReminder({ required String reminderId, }) async { final request = ReminderIdentifierPB(id: reminderId); final unitOrFailure = await UserEventRemoveReminder(request).send(); - return unitOrFailure.swap(); + return unitOrFailure; } } diff --git a/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart b/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart index 665407bcca..0cc39df691 100644 --- a/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/sign_in_bloc.dart @@ -6,7 +6,7 @@ import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -58,8 +58,8 @@ class SignInBloc extends Bloc { emit( state.copyWith( email: value.email, - emailError: none(), - successOrFail: none(), + emailError: null, + successOrFail: null, ), ); }, @@ -67,8 +67,8 @@ class SignInBloc extends Bloc { emit( state.copyWith( password: value.password, - passwordError: none(), - successOrFail: none(), + passwordError: null, + successOrFail: null, ), ); }, @@ -85,20 +85,20 @@ class SignInBloc extends Bloc { emit( state.copyWith( isSubmitting: true, - emailError: none(), - passwordError: none(), - successOrFail: none(), + emailError: null, + passwordError: null, + successOrFail: null, ), ); case DeepLinkState.finish: if (value.result.result != null) { emit( value.result.result!.fold( - (error) => stateFromCode(error), (userProfile) => state.copyWith( isSubmitting: false, - successOrFail: some(left(userProfile)), + successOrFail: FlowyResult.success(userProfile), ), + (error) => stateFromCode(error), ), ); } @@ -108,9 +108,9 @@ class SignInBloc extends Bloc { emit( state.copyWith( isSubmitting: false, - emailError: none(), - passwordError: none(), - successOrFail: none(), + emailError: null, + passwordError: null, + successOrFail: null, ), ); }, @@ -129,11 +129,11 @@ class SignInBloc extends Bloc { ); emit( result.fold( - (error) => stateFromCode(error), (userProfile) => state.copyWith( isSubmitting: false, - successOrFail: some(left(userProfile)), + successOrFail: FlowyResult.success(userProfile), ), + (error) => stateFromCode(error), ), ); } @@ -146,9 +146,9 @@ class SignInBloc extends Bloc { emit( state.copyWith( isSubmitting: true, - emailError: none(), - passwordError: none(), - successOrFail: none(), + emailError: null, + passwordError: null, + successOrFail: null, ), ); @@ -157,11 +157,11 @@ class SignInBloc extends Bloc { ); emit( result.fold( - (error) => stateFromCode(error), (userProfile) => state.copyWith( isSubmitting: false, - successOrFail: some(left(userProfile)), + successOrFail: FlowyResult.success(userProfile), ), + (error) => stateFromCode(error), ), ); } @@ -174,22 +174,23 @@ class SignInBloc extends Bloc { emit( state.copyWith( isSubmitting: true, - emailError: none(), - passwordError: none(), - successOrFail: none(), + emailError: null, + passwordError: null, + successOrFail: null, ), ); final result = await authService.signInWithMagicLink( email: email, ); + emit( result.fold( - (error) => stateFromCode(error), (userProfile) => state.copyWith( isSubmitting: false, - successOrFail: some(left(userProfile)), + successOrFail: FlowyResult.success(userProfile), ), + (error) => stateFromCode(error), ), ); } @@ -201,20 +202,20 @@ class SignInBloc extends Bloc { emit( state.copyWith( isSubmitting: true, - emailError: none(), - passwordError: none(), - successOrFail: none(), + emailError: null, + passwordError: null, + successOrFail: null, ), ); final result = await authService.signUpAsGuest(); emit( result.fold( - (error) => stateFromCode(error), (userProfile) => state.copyWith( isSubmitting: false, - successOrFail: some(left(userProfile)), + successOrFail: FlowyResult.success(userProfile), ), + (error) => stateFromCode(error), ), ); } @@ -224,19 +225,19 @@ class SignInBloc extends Bloc { case ErrorCode.EmailFormatInvalid: return state.copyWith( isSubmitting: false, - emailError: some(error.msg), - passwordError: none(), + emailError: error.msg, + passwordError: null, ); case ErrorCode.PasswordFormatInvalid: return state.copyWith( isSubmitting: false, - passwordError: some(error.msg), - emailError: none(), + passwordError: error.msg, + emailError: null, ); default: return state.copyWith( isSubmitting: false, - successOrFail: some(right(error)), + successOrFail: FlowyResult.failure(error), ); } } @@ -264,15 +265,15 @@ class SignInState with _$SignInState { String? email, String? password, required bool isSubmitting, - required Option passwordError, - required Option emailError, - required Option> successOrFail, + required String? passwordError, + required String? emailError, + required FlowyResult? successOrFail, }) = _SignInState; - factory SignInState.initial() => SignInState( + factory SignInState.initial() => const SignInState( isSubmitting: false, - passwordError: none(), - emailError: none(), - successOrFail: none(), + passwordError: null, + emailError: null, + successOrFail: null, ); } diff --git a/frontend/appflowy_flutter/lib/user/application/sign_up_bloc.dart b/frontend/appflowy_flutter/lib/user/application/sign_up_bloc.dart index a7cd6e29c5..1935d00c6d 100644 --- a/frontend/appflowy_flutter/lib/user/application/sign_up_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/sign_up_bloc.dart @@ -1,10 +1,10 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy_backend/protobuf/flowy-error/code.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -29,8 +29,8 @@ class SignUpBloc extends Bloc { emit( state.copyWith( email: value.email, - emailError: none(), - successOrFail: none(), + emailError: null, + successOrFail: null, ), ); }, @@ -38,8 +38,8 @@ class SignUpBloc extends Bloc { emit( state.copyWith( password: value.password, - passwordError: none(), - successOrFail: none(), + passwordError: null, + successOrFail: null, ), ); }, @@ -47,8 +47,8 @@ class SignUpBloc extends Bloc { emit( state.copyWith( repeatedPassword: value.password, - repeatPasswordError: none(), - successOrFail: none(), + repeatPasswordError: null, + successOrFail: null, ), ); }, @@ -61,7 +61,7 @@ class SignUpBloc extends Bloc { emit( state.copyWith( isSubmitting: true, - successOrFail: none(), + successOrFail: null, ), ); @@ -71,7 +71,7 @@ class SignUpBloc extends Bloc { emit( state.copyWith( isSubmitting: false, - passwordError: some(LocaleKeys.signUp_emptyPasswordError.tr()), + passwordError: LocaleKeys.signUp_emptyPasswordError.tr(), ), ); return; @@ -81,8 +81,7 @@ class SignUpBloc extends Bloc { emit( state.copyWith( isSubmitting: false, - repeatPasswordError: - some(LocaleKeys.signUp_repeatPasswordEmptyError.tr()), + repeatPasswordError: LocaleKeys.signUp_repeatPasswordEmptyError.tr(), ), ); return; @@ -92,8 +91,7 @@ class SignUpBloc extends Bloc { emit( state.copyWith( isSubmitting: false, - repeatPasswordError: - some(LocaleKeys.signUp_unmatchedPasswordError.tr()), + repeatPasswordError: LocaleKeys.signUp_unmatchedPasswordError.tr(), ), ); return; @@ -101,8 +99,8 @@ class SignUpBloc extends Bloc { emit( state.copyWith( - passwordError: none(), - repeatPasswordError: none(), + passwordError: null, + repeatPasswordError: null, ), ); @@ -113,14 +111,14 @@ class SignUpBloc extends Bloc { ); emit( result.fold( - (error) => stateFromCode(error), (profile) => state.copyWith( isSubmitting: false, - successOrFail: some(left(profile)), - emailError: none(), - passwordError: none(), - repeatPasswordError: none(), + successOrFail: FlowyResult.success(profile), + emailError: null, + passwordError: null, + repeatPasswordError: null, ), + (error) => stateFromCode(error), ), ); } @@ -130,21 +128,21 @@ class SignUpBloc extends Bloc { case ErrorCode.EmailFormatInvalid: return state.copyWith( isSubmitting: false, - emailError: some(error.msg), - passwordError: none(), - successOrFail: none(), + emailError: error.msg, + passwordError: null, + successOrFail: null, ); case ErrorCode.PasswordFormatInvalid: return state.copyWith( isSubmitting: false, - passwordError: some(error.msg), - emailError: none(), - successOrFail: none(), + passwordError: error.msg, + emailError: null, + successOrFail: null, ); default: return state.copyWith( isSubmitting: false, - successOrFail: some(right(error)), + successOrFail: FlowyResult.failure(error), ); } } @@ -167,17 +165,17 @@ class SignUpState with _$SignUpState { String? password, String? repeatedPassword, required bool isSubmitting, - required Option passwordError, - required Option repeatPasswordError, - required Option emailError, - required Option> successOrFail, + required String? passwordError, + required String? repeatPasswordError, + required String? emailError, + required FlowyResult? successOrFail, }) = _SignUpState; - factory SignUpState.initial() => SignUpState( + factory SignUpState.initial() => const SignUpState( isSubmitting: false, - passwordError: none(), - repeatPasswordError: none(), - emailError: none(), - successOrFail: none(), + passwordError: null, + repeatPasswordError: null, + emailError: null, + successOrFail: null, ); } diff --git a/frontend/appflowy_flutter/lib/user/application/splash_bloc.dart b/frontend/appflowy_flutter/lib/user/application/splash_bloc.dart index f603e1cf53..584c730fba 100644 --- a/frontend/appflowy_flutter/lib/user/application/splash_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/splash_bloc.dart @@ -13,8 +13,8 @@ class SplashBloc extends Bloc { getUser: (val) async { final response = await getIt().getUser(); final authState = response.fold( - (error) => AuthState.unauthenticated(error), (user) => AuthState.authenticated(user), + (error) => AuthState.unauthenticated(error), ); emit(state.copyWith(auth: authState)); }, diff --git a/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart b/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart index e47334676a..ba3dcb6cb7 100644 --- a/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart +++ b/frontend/appflowy_flutter/lib/user/application/supabase_realtime.dart @@ -11,7 +11,7 @@ import 'package:supabase_flutter/supabase_flutter.dart'; /// A service to manage realtime interactions with Supabase. /// -/// `SupbaseRealtimeService` handles subscribing to table changes in Supabase +/// `SupabaseRealtimeService` handles subscribing to table changes in Supabase /// based on the authentication state of a user. The service is initialized with /// a reference to a Supabase instance and sets up the necessary subscriptions /// accordingly. @@ -54,25 +54,39 @@ class SupabaseRealtimeService { Future _subscribeTablesChanges() async { final result = await UserBackendService.getCurrentUserProfile(); - result.fold((l) => null, (userProfile) { - Log.info("Start listening supabase table changes"); + result.fold( + (userProfile) { + Log.info("Start listening supabase table changes"); - // https://supabase.com/docs/guides/realtime/postgres-changes + // https://supabase.com/docs/guides/realtime/postgres-changes + + const ops = RealtimeChannelConfig(ack: true); + channel?.unsubscribe(); + channel = supabase.client.channel("table-db-changes", opts: ops); + for (final name in [ + "document", + "folder", + "database", + "database_row", + "w_database", + ]) { + channel?.onPostgresChanges( + event: PostgresChangeEvent.insert, + schema: 'public', + table: 'af_collab_update_$name', + filter: PostgresChangeFilter( + type: PostgresChangeFilterType.eq, + column: 'uid', + value: userProfile.id, + ), + callback: _onPostgresChangesCallback, + ); + } - const ops = RealtimeChannelConfig(ack: true); - channel?.unsubscribe(); - channel = supabase.client.channel("table-db-changes", opts: ops); - for (final name in [ - "document", - "folder", - "database", - "database_row", - "w_database", - ]) { channel?.onPostgresChanges( - event: PostgresChangeEvent.insert, + event: PostgresChangeEvent.update, schema: 'public', - table: 'af_collab_update_$name', + table: 'af_user', filter: PostgresChangeFilter( type: PostgresChangeFilterType.eq, column: 'uid', @@ -80,28 +94,17 @@ class SupabaseRealtimeService { ), callback: _onPostgresChangesCallback, ); - } - channel?.onPostgresChanges( - event: PostgresChangeEvent.update, - schema: 'public', - table: 'af_user', - filter: PostgresChangeFilter( - type: PostgresChangeFilterType.eq, - column: 'uid', - value: userProfile.id, - ), - callback: _onPostgresChangesCallback, - ); - - channel?.subscribe( - (status, [err]) { - Log.info( - "subscribe channel statue: $status, err: $err", - ); - }, - ); - }); + channel?.subscribe( + (status, [err]) { + Log.info( + "subscribe channel statue: $status, err: $err", + ); + }, + ); + }, + (_) => null, + ); } Future dispose() async { diff --git a/frontend/appflowy_flutter/lib/user/application/user_auth_listener.dart b/frontend/appflowy_flutter/lib/user/application/user_auth_listener.dart index 776d537f36..612c1eacd5 100644 --- a/frontend/appflowy_flutter/lib/user/application/user_auth_listener.dart +++ b/frontend/appflowy_flutter/lib/user/application/user_auth_listener.dart @@ -9,7 +9,7 @@ import 'package:appflowy_backend/protobuf/flowy-user/auth.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/notification.pb.dart' as user; import 'package:appflowy_backend/rust_stream.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class UserAuthStateListener { void Function(String)? _onInvalidAuth; @@ -41,7 +41,7 @@ class UserAuthStateListener { void _userNotificationCallback( user.UserNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case user.UserNotification.UserAuthStateChanged: diff --git a/frontend/appflowy_flutter/lib/user/application/user_listener.dart b/frontend/appflowy_flutter/lib/user/application/user_listener.dart index b23689f562..2fbacf3b6b 100644 --- a/frontend/appflowy_flutter/lib/user/application/user_listener.dart +++ b/frontend/appflowy_flutter/lib/user/application/user_listener.dart @@ -1,20 +1,21 @@ import 'dart:async'; +import 'dart:typed_data'; + import 'package:appflowy/core/notification/folder_notification.dart'; import 'package:appflowy/core/notification/user_notification.dart'; -import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'dart:typed_data'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-notification/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-user/notification.pb.dart' as user; +import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; -typedef UserProfileNotifyValue = Either; -typedef AuthNotifyValue = Either; +typedef UserProfileNotifyValue = FlowyResult; +typedef AuthNotifyValue = FlowyResult; class UserListener { UserListener({ @@ -52,14 +53,14 @@ class UserListener { void _userNotificationCallback( user.UserNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case user.UserNotification.DidUpdateUserProfile: result.fold( - (payload) => - _profileNotifier?.value = left(UserProfilePB.fromBuffer(payload)), - (error) => _profileNotifier?.value = right(error), + (payload) => _profileNotifier?.value = + FlowyResult.success(UserProfilePB.fromBuffer(payload)), + (error) => _profileNotifier?.value = FlowyResult.failure(error), ); break; default: @@ -68,7 +69,8 @@ class UserListener { } } -typedef WorkspaceSettingNotifyValue = Either; +typedef WorkspaceSettingNotifyValue + = FlowyResult; class UserWorkspaceListener { UserWorkspaceListener(); @@ -95,14 +97,15 @@ class UserWorkspaceListener { void _handleObservableType( FolderNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case FolderNotification.DidUpdateWorkspaceSetting: result.fold( (payload) => _settingChangedNotifier?.value = - left(WorkspaceSettingPB.fromBuffer(payload)), - (error) => _settingChangedNotifier?.value = right(error), + FlowyResult.success(WorkspaceSettingPB.fromBuffer(payload)), + (error) => + _settingChangedNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/user/application/user_service.dart b/frontend/appflowy_flutter/lib/user/application/user_service.dart index ac76bf5234..44b067475b 100644 --- a/frontend/appflowy_flutter/lib/user/application/user_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/user_service.dart @@ -4,7 +4,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:fixnum/fixnum.dart'; class UserBackendService { @@ -14,13 +14,13 @@ class UserBackendService { final Int64 userId; - static Future> + static Future> getCurrentUserProfile() async { final result = await UserEventGetUserProfile().send(); - return result.swap(); + return result; } - Future> updateUserProfile({ + Future> updateUserProfile({ String? name, String? password, String? email, @@ -57,54 +57,54 @@ class UserBackendService { return UserEventUpdateUserProfile(payload).send(); } - Future> deleteWorkspace({ + Future> deleteWorkspace({ required String workspaceId, }) { throw UnimplementedError(); } - static Future> signOut() { + static Future> signOut() { return UserEventSignOut().send(); } - Future> initUser() async { + Future> initUser() async { return UserEventInitUser().send(); } - static Future> getAnonUser() async { + static Future> getAnonUser() async { return UserEventGetAnonUser().send(); } - static Future> openAnonUser() async { + static Future> openAnonUser() async { return UserEventOpenAnonUser().send(); } - Future, FlowyError>> getWorkspaces() { + Future, FlowyError>> getWorkspaces() { // final request = WorkspaceIdPB.create(); // return FolderEventReadAllWorkspaces(request).send().then((result) { // return result.fold( - // (workspaces) => left(workspaces.items), - // (error) => right(error), + // (workspaces) => FlowyResult.success(workspaces.items), + // (error) => FlowyResult.failure(error), // ); // }); - return Future.value(left([])); + return Future.value(FlowyResult.success([])); } - Future> openWorkspace(String workspaceId) { + Future> openWorkspace(String workspaceId) { final payload = UserWorkspaceIdPB.create()..workspaceId = workspaceId; return UserEventOpenWorkspace(payload).send(); } - Future> getCurrentWorkspace() { + Future> getCurrentWorkspace() { return FolderEventReadCurrentWorkspace().send().then((result) { return result.fold( - (workspace) => left(workspace), - (error) => right(error), + (workspace) => FlowyResult.success(workspace), + (error) => FlowyResult.failure(error), ); }); } - Future> createWorkspace( + Future> createWorkspace( String name, String desc, ) { @@ -113,8 +113,8 @@ class UserBackendService { ..desc = desc; return FolderEventCreateWorkspace(request).send().then((result) { return result.fold( - (workspace) => left(workspace), - (error) => right(error), + (workspace) => FlowyResult.success(workspace), + (error) => FlowyResult.failure(error), ); }); } diff --git a/frontend/appflowy_flutter/lib/user/application/user_settings_service.dart b/frontend/appflowy_flutter/lib/user/application/user_settings_service.dart index ebf15da954..f9718a9134 100644 --- a/frontend/appflowy_flutter/lib/user/application/user_settings_service.dart +++ b/frontend/appflowy_flutter/lib/user/application/user_settings_service.dart @@ -1,9 +1,9 @@ -import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/appflowy_backend.dart'; +import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class UserSettingsBackendService { Future getAppearanceSetting() async { @@ -16,11 +16,11 @@ class UserSettingsBackendService { ); } - Future> getUserSetting() { + Future> getUserSetting() { return UserEventGetUserSetting().send(); } - Future> setAppearanceSetting( + Future> setAppearanceSetting( AppearanceSettingsPB setting, ) { return UserEventSetAppearanceSetting(setting).send(); @@ -36,16 +36,16 @@ class UserSettingsBackendService { ); } - Future> setDateTimeSettings( + Future> setDateTimeSettings( DateTimeSettingsPB settings, ) async { - return (await UserEventSetDateTimeSettings(settings).send()).swap(); + return UserEventSetDateTimeSettings(settings).send(); } - Future> setNotificationSettings( + Future> setNotificationSettings( NotificationSettingsPB settings, ) async { - return (await UserEventSetNotificationSettings(settings).send()).swap(); + return UserEventSetNotificationSettings(settings).send(); } Future getNotificationSettings() async { diff --git a/frontend/appflowy_flutter/lib/user/application/workspace_error_bloc.dart b/frontend/appflowy_flutter/lib/user/application/workspace_error_bloc.dart index c9b9471ad0..ce51fdd10b 100644 --- a/frontend/appflowy_flutter/lib/user/application/workspace_error_bloc.dart +++ b/frontend/appflowy_flutter/lib/user/application/workspace_error_bloc.dart @@ -4,7 +4,7 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -70,7 +70,7 @@ class WorkspaceErrorEvent with _$WorkspaceErrorEvent { const factory WorkspaceErrorEvent.logout() = _DidLogout; const factory WorkspaceErrorEvent.resetWorkspace() = _ResetWorkspace; const factory WorkspaceErrorEvent.didResetWorkspace( - Either result, + FlowyResult result, ) = _DidResetWorkspace; } diff --git a/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_user_profile_result.dart b/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_user_profile_result.dart index 93564bad6f..9abd417df3 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_user_profile_result.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/helpers/handle_user_profile_result.dart @@ -1,12 +1,12 @@ import 'package:appflowy/user/presentation/helpers/helpers.dart'; import 'package:appflowy/user/presentation/presentation.dart'; -import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/protobuf/flowy-error/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter/material.dart'; void handleUserProfileResult( - Either userProfileResult, + FlowyResult userProfileResult, BuildContext context, AuthRouter authRouter, ) { diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/encrypt_secret_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/encrypt_secret_screen.dart index 24fefbfc34..1edd20b671 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/encrypt_secret_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/encrypt_secret_screen.dart @@ -55,17 +55,12 @@ class _EncryptSecretScreenState extends State { listenWhen: (previous, current) => previous.successOrFail != current.successOrFail, listener: (context, state) async { - state.successOrFail.fold( - () {}, - (result) { - result.fold( - (unit) async { - await runAppFlowy(); - }, - (error) { - handleOpenWorkspaceError(context, error); - }, - ); + await state.successOrFail?.fold( + (unit) async { + await runAppFlowy(); + }, + (error) { + handleOpenWorkspaceError(context, error); }, ); }, diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart index 1ebf14dd3d..a9daf2b961 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_in_screen/sign_in_screen.dart @@ -23,14 +23,14 @@ class SignInScreen extends StatelessWidget { create: (context) => getIt(), child: BlocConsumer( listener: (context, state) { - state.successOrFail.fold( - () => null, - (userProfileResult) => handleUserProfileResult( - userProfileResult, + final successOrFail = state.successOrFail; + if (successOrFail != null) { + handleUserProfileResult( + successOrFail, context, getIt(), - ), - ); + ); + } }, builder: (context, state) { final isLoading = context.read().state.isSubmitting; diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_up_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_up_screen.dart index 049279ca4a..8aea8dde55 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/sign_up_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/sign_up_screen.dart @@ -1,21 +1,21 @@ import 'package:appflowy/generated/flowy_svgs.g.dart'; +import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/user/application/sign_up_bloc.dart'; import 'package:appflowy/user/presentation/router.dart'; import 'package:appflowy/user/presentation/widgets/widgets.dart'; +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' + show UserProfilePB; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; +import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/rounded_button.dart'; import 'package:flowy_infra_ui/widget/rounded_input_field.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' - show UserProfilePB; -import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:dartz/dartz.dart'; -import 'package:appflowy/generated/locale_keys.g.dart'; class SignUpScreen extends StatelessWidget { const SignUpScreen({ @@ -32,10 +32,10 @@ class SignUpScreen extends StatelessWidget { create: (context) => getIt(), child: BlocListener( listener: (context, state) { - state.successOrFail.fold( - () => {}, - (result) => _handleSuccessOrFail(context, result), - ); + final successOrFail = state.successOrFail; + if (successOrFail != null) { + _handleSuccessOrFail(context, successOrFail); + } }, child: const Scaffold(body: SignUpForm()), ), @@ -44,7 +44,7 @@ class SignUpScreen extends StatelessWidget { void _handleSuccessOrFail( BuildContext context, - Either result, + FlowyResult result, ) { result.fold( (user) => router.pushWorkspaceStartScreen(context, user), @@ -154,11 +154,7 @@ class PasswordTextField extends StatelessWidget { normalBorderColor: Theme.of(context).colorScheme.outline, errorBorderColor: Theme.of(context).colorScheme.error, cursorColor: Theme.of(context).colorScheme.primary, - errorText: context - .read() - .state - .passwordError - .fold(() => "", (error) => error), + errorText: context.read().state.passwordError ?? '', onChanged: (value) => context .read() .add(SignUpEvent.passwordChanged(value)), @@ -187,11 +183,7 @@ class RepeatPasswordTextField extends StatelessWidget { normalBorderColor: Theme.of(context).colorScheme.outline, errorBorderColor: Theme.of(context).colorScheme.error, cursorColor: Theme.of(context).colorScheme.primary, - errorText: context - .read() - .state - .repeatPasswordError - .fold(() => "", (error) => error), + errorText: context.read().state.repeatPasswordError ?? '', onChanged: (value) => context .read() .add(SignUpEvent.repeatPasswordChanged(value)), @@ -218,11 +210,7 @@ class EmailTextField extends StatelessWidget { normalBorderColor: Theme.of(context).colorScheme.outline, errorBorderColor: Theme.of(context).colorScheme.error, cursorColor: Theme.of(context).colorScheme.primary, - errorText: context - .read() - .state - .emailError - .fold(() => "", (error) => error), + errorText: context.read().state.emailError ?? '', onChanged: (value) => context.read().add(SignUpEvent.emailChanged(value)), ); diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/skip_log_in_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/skip_log_in_screen.dart index af5e66496f..60f49937ec 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/skip_log_in_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/skip_log_in_screen.dart @@ -2,19 +2,19 @@ import 'package:appflowy/core/frameless_window.dart'; import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/startup.dart'; -import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/anon_user_bloc.dart'; +import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/presentation/router.dart'; import 'package:appflowy/user/presentation/widgets/widgets.dart'; import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart'; import 'package:appflowy/workspace/presentation/settings/widgets/settings_language_view.dart'; +import 'package:appflowy_backend/log.dart'; import 'package:appflowy_editor/appflowy_editor.dart' hide Log; import 'package:appflowy_popover/appflowy_popover.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/language.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; -import 'package:appflowy_backend/log.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:url_launcher/url_launcher.dart'; @@ -87,12 +87,12 @@ class _SkipLogInScreenState extends State { Future _autoRegister(BuildContext context) async { final result = await getIt().signUpAsGuest(); result.fold( - (error) { - Log.error(error); - }, (user) { getIt().goHomeScreen(context, user); }, + (error) { + Log.error(error); + }, ); } diff --git a/frontend/appflowy_flutter/lib/user/presentation/screens/splash_screen.dart b/frontend/appflowy_flutter/lib/user/presentation/screens/splash_screen.dart index 51f566dc79..49ceb81383 100644 --- a/frontend/appflowy_flutter/lib/user/presentation/screens/splash_screen.dart +++ b/frontend/appflowy_flutter/lib/user/presentation/screens/splash_screen.dart @@ -105,7 +105,7 @@ class SplashScreen extends StatelessWidget { Future _registerIfNeeded() async { final result = await UserEventGetUserProfile().send(); - if (!result.isLeft()) { + if (result.isFailure()) { await getIt().signUpAsGuest(); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/doc/doc_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/doc/doc_listener.dart index fd35c01831..61ff86edcd 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/doc/doc_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/doc/doc_listener.dart @@ -6,7 +6,7 @@ import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class DocumentListener { DocumentListener({ @@ -36,13 +36,11 @@ class DocumentListener { void _callback( DocumentNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DocumentNotification.DidReceiveUpdate: - result - .swap() - .map((r) => didReceiveUpdate?.call(DocEventPB.fromBuffer(r))); + result.map((r) => didReceiveUpdate?.call(DocEventPB.fromBuffer(r))); break; default: break; diff --git a/frontend/appflowy_flutter/lib/workspace/application/doc/sync_state_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/doc/sync_state_listener.dart index 37122fa31f..6cd57ba0e6 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/doc/sync_state_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/doc/sync_state_listener.dart @@ -6,7 +6,7 @@ import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class DocumentSyncStateListener { DocumentSyncStateListener({ @@ -34,11 +34,11 @@ class DocumentSyncStateListener { void _callback( DocumentNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case DocumentNotification.DidUpdateDocumentSyncState: - result.swap().map( + result.map( (r) { final value = DocumentSyncStatePB.fromBuffer(r); didReceiveSyncState?.call(value); diff --git a/frontend/appflowy_flutter/lib/workspace/application/edit_panel/edit_panel_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/edit_panel/edit_panel_bloc.dart index fc948f7591..52d36033fe 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/edit_panel/edit_panel_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/edit_panel/edit_panel_bloc.dart @@ -1,5 +1,4 @@ import 'package:appflowy/workspace/application/edit_panel/edit_context.dart'; -import 'package:dartz/dartz.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -10,10 +9,10 @@ class EditPanelBloc extends Bloc { on((event, emit) async { await event.map( startEdit: (e) async { - emit(state.copyWith(isEditing: true, editContext: some(e.context))); + emit(state.copyWith(isEditing: true, editContext: e.context)); }, endEdit: (value) async { - emit(state.copyWith(isEditing: false, editContext: none())); + emit(state.copyWith(isEditing: false, editContext: null)); }, ); }); @@ -31,11 +30,11 @@ class EditPanelEvent with _$EditPanelEvent { class EditPanelState with _$EditPanelState { const factory EditPanelState({ required bool isEditing, - required Option editContext, + required EditPanelContext? editContext, }) = _EditPanelState; - factory EditPanelState.initial() => EditPanelState( + factory EditPanelState.initial() => const EditPanelState( isEditing: false, - editContext: none(), + editContext: null, ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/export/document_exporter.dart b/frontend/appflowy_flutter/lib/workspace/application/export/document_exporter.dart index bb8ce9a953..2c89de5381 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/export/document_exporter.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/export/document_exporter.dart @@ -7,7 +7,7 @@ import 'package:appflowy/plugins/document/presentation/editor_plugins/parsers/do import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; const List _customParsers = [ @@ -30,30 +30,35 @@ class DocumentExporter { final ViewPB view; - Future> export(DocumentExportType type) async { + Future> export( + DocumentExportType type, + ) async { final documentService = DocumentService(); final result = await documentService.openDocument(viewId: view.id); - return result.fold((error) => left(error), (r) { - final document = r.toDocument(); - if (document == null) { - return left( - FlowyError( - msg: LocaleKeys.settings_files_exportFileFail.tr(), - ), - ); - } - switch (type) { - case DocumentExportType.json: - return right(jsonEncode(document)); - case DocumentExportType.markdown: - final markdown = documentToMarkdown( - document, - customParsers: _customParsers, + return result.fold( + (r) { + final document = r.toDocument(); + if (document == null) { + return FlowyResult.failure( + FlowyError( + msg: LocaleKeys.settings_files_exportFileFail.tr(), + ), ); - return right(markdown); - case DocumentExportType.text: - throw UnimplementedError(); - } - }); + } + switch (type) { + case DocumentExportType.json: + return FlowyResult.success(jsonEncode(document)); + case DocumentExportType.markdown: + final markdown = documentToMarkdown( + document, + customParsers: _customParsers, + ); + return FlowyResult.success(markdown); + case DocumentExportType.text: + throw UnimplementedError(); + } + }, + (error) => FlowyResult.failure(error), + ); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_bloc.dart index 204d18e025..1f88340cc1 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_bloc.dart @@ -2,7 +2,7 @@ import 'package:appflowy/workspace/application/favorite/favorite_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -69,14 +69,14 @@ class FavoriteBloc extends Bloc { } void _onFavoritesUpdated( - Either favoriteOrFailed, + FlowyResult favoriteOrFailed, bool didFavorite, ) { favoriteOrFailed.fold( - (error) => Log.error(error), (favorite) => didFavorite ? add(FavoriteEvent.didFavorite(favorite)) : add(FavoriteEvent.didUnfavorite(favorite)), + (error) => Log.error(error), ); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_listener.dart index 533f866764..6606ab26eb 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_listener.dart @@ -6,11 +6,11 @@ import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter/foundation.dart'; typedef FavoriteUpdated = void Function( - Either result, + FlowyResult result, bool isFavorite, ); @@ -35,7 +35,7 @@ class FavoriteListener { void _observableCallback( FolderNotification ty, - Either result, + FlowyResult result, ) { if (_favoriteUpdated == null) { return; @@ -46,12 +46,12 @@ class FavoriteListener { (payload) { final view = RepeatedViewPB.fromBuffer(payload); _favoriteUpdated!( - right(view), + FlowyResult.success(view), isFavorite, ); }, (error) => _favoriteUpdated!( - left(error), + FlowyResult.failure(error), isFavorite, ), ); diff --git a/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_service.dart b/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_service.dart index d88a617bce..d9343e2ee3 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/favorite/favorite_service.dart @@ -1,14 +1,14 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class FavoriteService { - Future> readFavorites() { + Future> readFavorites() { return FolderEventReadFavorites().send(); } - Future> toggleFavorite( + Future> toggleFavorite( String viewId, bool favoriteStatus, ) async { diff --git a/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart b/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart index f8fcfbbb76..8fd945aa58 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/home/home_service.dart @@ -1,12 +1,12 @@ import 'dart:async'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; 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'; class HomeService { - Future> readApp({required String appId}) { + Future> readApp({required String appId}) { final payload = ViewIdPB.create()..value = appId; return FolderEventGetView(payload).send(); diff --git a/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart index 90531f1b9f..171bf634a7 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/home/home_setting_bloc.dart @@ -3,7 +3,6 @@ import 'package:appflowy/workspace/application/edit_panel/edit_context.dart'; import 'package:appflowy/workspace/application/settings/appearance/appearance_cubit.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart' show WorkspaceSettingPB; -import 'package:dartz/dartz.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra/time/duration.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -43,10 +42,10 @@ class HomeSettingBloc extends Bloc { await event.map( initial: (_Initial value) {}, setEditPanel: (e) async { - emit(state.copyWith(panelContext: some(e.editContext))); + emit(state.copyWith(panelContext: e.editContext)); }, dismissEditPanel: (value) async { - emit(state.copyWith(panelContext: none())); + emit(state.copyWith(panelContext: null)); }, didReceiveWorkspaceSetting: (_DidReceiveWorkspaceSetting value) { emit(state.copyWith(workspaceSetting: value.setting)); @@ -139,7 +138,7 @@ class HomeSettingEvent with _$HomeSettingEvent { @freezed class HomeSettingState with _$HomeSettingState { const factory HomeSettingState({ - required Option panelContext, + required EditPanelContext? panelContext, required WorkspaceSettingPB workspaceSetting, required bool unauthorized, required bool isMenuCollapsed, @@ -156,7 +155,7 @@ class HomeSettingState with _$HomeSettingState { double screenWidthPx, ) { return HomeSettingState( - panelContext: none(), + panelContext: null, workspaceSetting: workspaceSetting, unauthorized: false, isMenuCollapsed: appearanceSettingsState.isMenuCollapsed, diff --git a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart index 3816dfb87d..c9ca94e0ef 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_bloc.dart @@ -6,7 +6,7 @@ import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -52,16 +52,23 @@ class MenuBloc extends Bloc { (app) => emit(state.copyWith(lastCreatedView: app)), (error) { Log.error(error); - emit(state.copyWith(successOrFailure: right(error))); + emit( + state.copyWith( + successOrFailure: FlowyResult.failure(error), + ), + ); }, ); }, didReceiveApps: (e) async { emit( e.appsOrFail.fold( - (views) => - state.copyWith(views: views, successOrFailure: left(unit)), - (err) => state.copyWith(successOrFailure: right(err)), + (views) => state.copyWith( + views: views, + successOrFailure: FlowyResult.success(null), + ), + (err) => + state.copyWith(successOrFailure: FlowyResult.failure(err)), ), ); }, @@ -92,16 +99,16 @@ class MenuBloc extends Bloc { (views) => state.copyWith(views: views), (error) { Log.error(error); - return state.copyWith(successOrFailure: right(error)); + return state.copyWith(successOrFailure: FlowyResult.failure(error)); }, ), ); } - void _handleAppsOrFail(Either, FlowyError> appsOrFail) { + void _handleAppsOrFail(FlowyResult, FlowyError> appsOrFail) { appsOrFail.fold( - (apps) => add(MenuEvent.didReceiveApps(left(apps))), - (error) => add(MenuEvent.didReceiveApps(right(error))), + (apps) => add(MenuEvent.didReceiveApps(FlowyResult.success(apps))), + (error) => add(MenuEvent.didReceiveApps(FlowyResult.failure(error))), ); } } @@ -113,7 +120,7 @@ class MenuEvent with _$MenuEvent { _CreateApp; const factory MenuEvent.moveApp(int fromIndex, int toIndex) = _MoveApp; const factory MenuEvent.didReceiveApps( - Either, FlowyError> appsOrFail, + FlowyResult, FlowyError> appsOrFail, ) = _ReceiveApps; } @@ -121,12 +128,12 @@ class MenuEvent with _$MenuEvent { class MenuState with _$MenuState { const factory MenuState({ required List views, - required Either successOrFailure, + required FlowyResult successOrFailure, ViewPB? lastCreatedView, }) = _MenuState; factory MenuState.initial() => MenuState( views: [], - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart index 3b41726b09..58071fb68e 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/menu/menu_user_bloc.dart @@ -4,7 +4,7 @@ import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -63,7 +63,9 @@ class MenuUserBloc extends Bloc { result.fold((l) => null, (error) => Log.error(error)); } - void _profileUpdated(Either userProfileOrFailed) { + void _profileUpdated( + FlowyResult userProfileOrFailed, + ) { if (isClosed) { return; } @@ -90,13 +92,13 @@ class MenuUserEvent with _$MenuUserEvent { class MenuUserState with _$MenuUserState { const factory MenuUserState({ required UserProfilePB userProfile, - required Option> workspaces, - required Either successOrFailure, + required List? workspaces, + required FlowyResult successOrFailure, }) = _MenuUserState; factory MenuUserState.initial(UserProfilePB userProfile) => MenuUserState( userProfile: userProfile, - workspaces: none(), - successOrFailure: left(unit), + workspaces: null, + successOrFailure: FlowyResult.success(null), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/recent/recent_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/recent/recent_listener.dart index 763fcc9667..fc70ef0602 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/recent/recent_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/recent/recent_listener.dart @@ -6,11 +6,11 @@ import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter/foundation.dart'; typedef RecentViewsUpdated = void Function( - Either result, + FlowyResult result, ); class RecentViewsListener { @@ -34,7 +34,7 @@ class RecentViewsListener { void _observableCallback( FolderNotification ty, - Either result, + FlowyResult result, ) { if (_recentViewsUpdated == null) { return; @@ -44,11 +44,11 @@ class RecentViewsListener { (payload) { final view = RepeatedViewIdPB.fromBuffer(payload); _recentViewsUpdated?.call( - right(view), + FlowyResult.success(view), ); }, (error) => _recentViewsUpdated?.call( - left(error), + FlowyResult.failure(error), ), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/recent/recent_service.dart b/frontend/appflowy_flutter/lib/workspace/application/recent/recent_service.dart index 0aea848572..9050b378ee 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/recent/recent_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/recent/recent_service.dart @@ -1,10 +1,10 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class RecentService { - Future> updateRecentViews( + Future> updateRecentViews( List viewIds, bool addInRecent, ) async { @@ -13,7 +13,7 @@ class RecentService { ).send(); } - Future> readRecentViews() { + Future> readRecentViews() { return FolderEventReadRecentViews().send(); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/recent/recent_views_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/recent/recent_views_bloc.dart index 32496b1c45..a454952016 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/recent/recent_views_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/recent/recent_views_bloc.dart @@ -3,7 +3,7 @@ import 'package:appflowy/workspace/application/recent/recent_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -54,7 +54,7 @@ class RecentViewsBloc extends Bloc { } void _onRecentViewsUpdated( - Either result, + FlowyResult result, ) { add(const RecentViewsEvent.fetchRecentViews()); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/appearance_cubit.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/appearance_cubit.dart index 756bb80097..b1480d0ffe 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/appearance_cubit.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/appearance/appearance_cubit.dart @@ -83,13 +83,11 @@ class AppearanceSettingsCubit extends Cubit { Future readTextScaleFactor() async { final textScaleFactor = await getIt().getWithFormat( - KVKeys.textScaleFactor, - (value) => double.parse(value), - ); - textScaleFactor.fold( - () => emit(state.copyWith(textScaleFactor: 1.0)), - (value) => emit(state.copyWith(textScaleFactor: value.clamp(0.7, 1.0))), - ); + KVKeys.textScaleFactor, + (value) => double.parse(value), + ) ?? + 1.0; + emit(state.copyWith(textScaleFactor: textScaleFactor.clamp(0.7, 1.0))); } /// Update selected theme in the user's settings and emit an updated state @@ -267,8 +265,8 @@ class AppearanceSettingsCubit extends Cubit { final result = await UserSettingsBackendService() .setDateTimeSettings(_dateTimeSettings); result.fold( - (error) => Log.error(error), (_) => null, + (error) => Log.error(error), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_setting_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_setting_bloc.dart index b94b52fa48..fdb53f4e43 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_setting_bloc.dart @@ -3,7 +3,7 @@ import 'package:appflowy/workspace/application/settings/cloud_setting_listener.d import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -86,16 +86,18 @@ class AppFlowyCloudSettingState with _$AppFlowyCloudSettingState { ); } -Either validateUrl(String url) { +FlowyResult validateUrl(String url) { try { // Use Uri.parse to validate the url. final uri = Uri.parse(url); if (uri.isScheme('HTTP') || uri.isScheme('HTTPS')) { - return right(()); + return FlowyResult.success(null); } else { - return left(LocaleKeys.settings_menu_invalidCloudURLScheme.tr()); + return FlowyResult.failure( + LocaleKeys.settings_menu_invalidCloudURLScheme.tr(), + ); } } catch (e) { - return left(e.toString()); + return FlowyResult.failure(e.toString()); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_urls_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_urls_bloc.dart index 72b91f011c..998e6d632f 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_urls_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/appflowy_cloud_urls_bloc.dart @@ -2,7 +2,7 @@ import 'package:appflowy/env/backend_env.dart'; import 'package:appflowy/env/cloud_env.dart'; import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/startup.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -19,7 +19,7 @@ class AppFlowyCloudURLsBloc emit( state.copyWith( updatedServerUrl: url, - urlError: none(), + urlError: null, showRestartHint: url.isNotEmpty, ), ); @@ -29,9 +29,8 @@ class AppFlowyCloudURLsBloc emit( state.copyWith( updatedServerUrl: "", - urlError: Some( - LocaleKeys.settings_menu_appFlowyCloudUrlCanNotBeEmpty.tr(), - ), + urlError: + LocaleKeys.settings_menu_appFlowyCloudUrlCanNotBeEmpty.tr(), restartApp: false, ), ); @@ -41,14 +40,14 @@ class AppFlowyCloudURLsBloc await useSelfHostedAppFlowyCloudWithURL(url); add(const AppFlowyCloudURLsEvent.didSaveConfig()); }, - (err) => emit(state.copyWith(urlError: Some(err))), + (err) => emit(state.copyWith(urlError: err)), ); } }, didSaveConfig: () { emit( state.copyWith( - urlError: none(), + urlError: null, restartApp: true, ), ); @@ -72,14 +71,14 @@ class AppFlowyCloudURLsState with _$AppFlowyCloudURLsState { const factory AppFlowyCloudURLsState({ required AppFlowyCloudConfiguration config, required String updatedServerUrl, - required Option urlError, + required String? urlError, required bool restartApp, required bool showRestartHint, }) = _AppFlowyCloudURLsState; factory AppFlowyCloudURLsState.initial() => AppFlowyCloudURLsState( config: getIt().appflowyCloudConfig, - urlError: none(), + urlError: null, updatedServerUrl: getIt().appflowyCloudConfig.base_url, showRestartHint: getIt() @@ -90,17 +89,19 @@ class AppFlowyCloudURLsState with _$AppFlowyCloudURLsState { ); } -Either validateUrl(String url) { +FlowyResult validateUrl(String url) { try { // Use Uri.parse to validate the url. final uri = Uri.parse(removeTrailingSlash(url)); if (uri.isScheme('HTTP') || uri.isScheme('HTTPS')) { - return left(uri.toString()); + return FlowyResult.success(uri.toString()); } else { - return right(LocaleKeys.settings_menu_invalidCloudURLScheme.tr()); + return FlowyResult.failure( + LocaleKeys.settings_menu_invalidCloudURLScheme.tr(), + ); } } catch (e) { - return right(e.toString()); + return FlowyResult.failure(e.toString()); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/application_data_storage.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/application_data_storage.dart index 1680678107..99a3b77d58 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/application_data_storage.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/application_data_storage.dart @@ -64,14 +64,14 @@ class ApplicationDataStorage { } final response = await getIt().get(KVKeys.pathLocation); - String path = await response.fold( - () async { - // return the default path if the path is not set - final directory = await appFlowyApplicationDataDirectory(); - return directory.path; - }, - (path) => path, - ); + + String path; + if (response == null) { + final directory = await appFlowyApplicationDataDirectory(); + path = directory.path; + } else { + path = response; + } _cachePath = path; // if the path is not exists means the path is invalid, so we should clear the kv store diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/cloud_setting_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/cloud_setting_listener.dart index f23d5aacf0..b6007847b3 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/cloud_setting_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/cloud_setting_listener.dart @@ -5,7 +5,7 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_backend/rust_stream.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import '../../../core/notification/user_notification.dart'; @@ -14,10 +14,10 @@ class UserCloudConfigListener { UserNotificationParser? _userParser; StreamSubscription? _subscription; - void Function(Either)? _onSettingChanged; + void Function(FlowyResult)? _onSettingChanged; void start({ - void Function(Either)? onSettingChanged, + void Function(FlowyResult)? onSettingChanged, }) { _onSettingChanged = onSettingChanged; _userParser = UserNotificationParser( @@ -37,14 +37,14 @@ class UserCloudConfigListener { void _userNotificationCallback( UserNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case UserNotification.DidUpdateCloudConfig: result.fold( - (payload) => - _onSettingChanged?.call(left(CloudSettingPB.fromBuffer(payload))), - (error) => _onSettingChanged?.call(right(error)), + (payload) => _onSettingChanged + ?.call(FlowyResult.success(CloudSettingPB.fromBuffer(payload))), + (error) => _onSettingChanged?.call(FlowyResult.failure(error)), ); break; default: diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/create_file_settings_cubit.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/create_file_settings_cubit.dart index 143048c030..7ff1ed5fed 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/create_file_settings_cubit.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/create_file_settings_cubit.dart @@ -21,9 +21,6 @@ class CreateFileSettingsCubit extends Cubit { KVKeys.showRenameDialogWhenCreatingNewFile, (value) => bool.parse(value), ); - settingsOrFailure.fold( - () => emit(false), - (settings) => emit(settings), - ); + emit(settingsOrFailure ?? false); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/notifications/notification_settings_cubit.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/notifications/notification_settings_cubit.dart index 06bb7bd61e..aae0a63609 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/notifications/notification_settings_cubit.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/notifications/notification_settings_cubit.dart @@ -47,8 +47,8 @@ class NotificationSettingsCubit extends Cubit { final result = await UserSettingsBackendService() .setNotificationSettings(_notificationSettings); result.fold( - (error) => Log.error(error), (r) => null, + (error) => Log.error(error), ); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/setting_file_importer_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/setting_file_importer_bloc.dart index 2ed81a194e..517b943b35 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/setting_file_importer_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/setting_file_importer_bloc.dart @@ -3,7 +3,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/import_data.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -36,8 +36,9 @@ class SettingFileImportBloc (l) { emit( state.copyWith( - successOrFail: some(left(unit)), - loadingState: LoadingState.finish(left(unit)), + successOrFail: FlowyResult.success(null), + loadingState: + LoadingState.finish(FlowyResult.success(null)), ), ); }, @@ -45,8 +46,8 @@ class SettingFileImportBloc Log.error(err); emit( state.copyWith( - successOrFail: some(right(err)), - loadingState: LoadingState.finish(right(err)), + successOrFail: FlowyResult.failure(err), + loadingState: LoadingState.finish(FlowyResult.failure(err)), ), ); }, @@ -63,7 +64,7 @@ class SettingFileImportEvent with _$SettingFileImportEvent { const factory SettingFileImportEvent.importAppFlowyDataFolder(String path) = _ImportAppFlowyDataFolder; const factory SettingFileImportEvent.finishImport( - Either result, + FlowyResult result, ) = _ImportResult; } @@ -71,11 +72,11 @@ class SettingFileImportEvent with _$SettingFileImportEvent { class SettingFileImportState with _$SettingFileImportState { const factory SettingFileImportState({ required LoadingState loadingState, - required Option> successOrFail, + required FlowyResult? successOrFail, }) = _SettingFileImportState; - factory SettingFileImportState.initial() => SettingFileImportState( - loadingState: const LoadingState.idle(), - successOrFail: none(), + factory SettingFileImportState.initial() => const SettingFileImportState( + loadingState: LoadingState.idle(), + successOrFail: null, ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/settings_dialog_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/settings_dialog_bloc.dart index 47eb6705dd..f1f369725e 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/settings_dialog_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/settings_dialog_bloc.dart @@ -2,7 +2,7 @@ import 'package:appflowy/user/application/user_listener.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -53,7 +53,9 @@ class SettingsDialogBloc ); } - void _profileUpdated(Either userProfileOrFailed) { + void _profileUpdated( + FlowyResult userProfileOrFailed, + ) { userProfileOrFailed.fold( (newUserProfile) => add(SettingsDialogEvent.didReceiveUserProfile(newUserProfile)), @@ -76,14 +78,14 @@ class SettingsDialogEvent with _$SettingsDialogEvent { class SettingsDialogState with _$SettingsDialogState { const factory SettingsDialogState({ required UserProfilePB userProfile, - required Either successOrFailure, + required FlowyResult successOrFailure, required SettingsPage page, }) = _SettingsDialogState; factory SettingsDialogState.initial(UserProfilePB userProfile) => SettingsDialogState( userProfile: userProfile, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), page: SettingsPage.appearance, ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/share/export_service.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/share/export_service.dart index 1d0ad4068b..7cf81b3bfb 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/share/export_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/share/export_service.dart @@ -2,10 +2,11 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/database_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/share_entities.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class BackendExportService { - static Future> exportDatabaseAsCSV( + static Future> + exportDatabaseAsCSV( String viewId, ) async { final payload = DatabaseViewIdPB.create()..value = viewId; diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/share/import_service.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/share/import_service.dart index 9628ea104d..34ea16e52f 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/share/import_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/share/import_service.dart @@ -2,10 +2,10 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/import.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pbenum.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class ImportBackendService { - static Future> importData( + static Future> importData( List data, String name, String parentViewId, diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_setting_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_setting_bloc.dart index 7465f1c437..9308a06a98 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_setting_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_setting_bloc.dart @@ -5,7 +5,7 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -56,7 +56,7 @@ class SupabaseCloudSettingBloc emit( state.copyWith( setting: setting, - loadingState: LoadingState.finish(left(unit)), + loadingState: LoadingState.finish(FlowyResult.success(null)), ), ); }, @@ -96,7 +96,7 @@ class SupabaseCloudSettingState with _$SupabaseCloudSettingState { factory SupabaseCloudSettingState.initial(CloudSettingPB setting) => SupabaseCloudSettingState( - loadingState: LoadingState.finish(left(unit)), + loadingState: LoadingState.finish(FlowyResult.success(null)), setting: setting, config: getIt().supabaseConfig, ); diff --git a/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_urls_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_urls_bloc.dart index b87e0189ab..fdd4cbef21 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_urls_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/settings/supabase_cloud_urls_bloc.dart @@ -4,7 +4,6 @@ import 'package:appflowy/generated/locale_keys.g.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; -import 'package:dartz/dartz.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -23,7 +22,7 @@ class SupabaseCloudURLsBloc state.copyWith( updatedUrl: url, showRestartHint: url.isNotEmpty && state.upatedAnonKey.isNotEmpty, - urlError: none(), + urlError: null, ), ); }, @@ -33,7 +32,7 @@ class SupabaseCloudURLsBloc upatedAnonKey: anonKey, showRestartHint: anonKey.isNotEmpty && state.updatedUrl.isNotEmpty, - anonKeyError: none(), + anonKeyError: null, ), ); }, @@ -41,10 +40,9 @@ class SupabaseCloudURLsBloc if (state.updatedUrl.isEmpty) { emit( state.copyWith( - urlError: Some( - LocaleKeys.settings_menu_cloudSupabaseUrlCanNotBeEmpty.tr(), - ), - anonKeyError: none(), + urlError: + LocaleKeys.settings_menu_cloudSupabaseUrlCanNotBeEmpty.tr(), + anonKeyError: null, restartApp: false, ), ); @@ -54,11 +52,10 @@ class SupabaseCloudURLsBloc if (state.upatedAnonKey.isEmpty) { emit( state.copyWith( - urlError: none(), - anonKeyError: Some( - LocaleKeys.settings_menu_cloudSupabaseAnonKeyCanNotBeEmpty - .tr(), - ), + urlError: null, + anonKeyError: LocaleKeys + .settings_menu_cloudSupabaseAnonKeyCanNotBeEmpty + .tr(), restartApp: false, ), ); @@ -66,7 +63,6 @@ class SupabaseCloudURLsBloc } validateUrl(state.updatedUrl).fold( - (error) => emit(state.copyWith(urlError: Some(error))), (_) async { await useSupabaseCloud( url: state.updatedUrl, @@ -75,13 +71,14 @@ class SupabaseCloudURLsBloc add(const SupabaseCloudURLsEvent.didSaveConfig()); }, + (error) => emit(state.copyWith(urlError: error)), ); }, didSaveConfig: () { emit( state.copyWith( - urlError: none(), - anonKeyError: none(), + urlError: null, + anonKeyError: null, restartApp: true, ), ); @@ -110,8 +107,8 @@ class SupabaseCloudURLsState with _$SupabaseCloudURLsState { required SupabaseConfiguration config, required String updatedUrl, required String upatedAnonKey, - required Option urlError, - required Option anonKeyError, + required String? urlError, + required String? anonKeyError, required bool restartApp, required bool showRestartHint, }) = _SupabaseCloudURLsState; @@ -121,8 +118,8 @@ class SupabaseCloudURLsState with _$SupabaseCloudURLsState { return SupabaseCloudURLsState( updatedUrl: config.url, upatedAnonKey: config.anon_key, - urlError: none(), - anonKeyError: none(), + urlError: null, + anonKeyError: null, restartApp: false, showRestartHint: config.url.isNotEmpty && config.anon_key.isNotEmpty, config: config, diff --git a/frontend/appflowy_flutter/lib/workspace/application/sidebar/folder/folder_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/sidebar/folder/folder_bloc.dart index 19927043a4..51891a0be9 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/sidebar/folder/folder_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/sidebar/folder/folder_bloc.dart @@ -5,6 +5,7 @@ import 'package:appflowy/core/config/kv_keys.dart'; import 'package:appflowy/startup/startup.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; + part 'folder_bloc.freezed.dart'; enum FolderCategoryType { @@ -34,10 +35,10 @@ class FolderBloc extends Bloc { Future _setFolderExpandStatus(bool isExpanded) async { final result = await getIt().get(KVKeys.expandedViews); - final map = result.fold( - () => {}, - (r) => jsonDecode(r), - ); + var map = {}; + if (result != null) { + map = jsonDecode(result); + } if (isExpanded) { // set expand status to true if it's not expanded map[state.type.name] = true; @@ -50,10 +51,11 @@ class FolderBloc extends Bloc { Future _getFolderExpandStatus() async { return getIt().get(KVKeys.expandedViews).then((result) { - return result.fold(() => true, (r) { - final map = jsonDecode(r); - return map[state.type.name] ?? true; - }); + if (result == null) { + return true; + } + final map = jsonDecode(result); + return map[state.type.name] ?? true; }); } } diff --git a/frontend/appflowy_flutter/lib/workspace/application/user/settings_user_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/user/settings_user_bloc.dart index fa0c84237f..0f45b019fd 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/user/settings_user_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/user/settings_user_bloc.dart @@ -3,7 +3,7 @@ import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -101,15 +101,17 @@ class SettingsUserViewBloc extends Bloc { } result.fold( - (err) => Log.error(err), (userProfile) => add( SettingsUserEvent.didReceiveUserProfile(userProfile), ), + (err) => Log.error(err), ); }); } - void _profileUpdated(Either userProfileOrFailed) { + void _profileUpdated( + FlowyResult userProfileOrFailed, + ) { userProfileOrFailed.fold( (newUserProfile) { add(SettingsUserEvent.didReceiveUserProfile(newUserProfile)); @@ -141,12 +143,12 @@ class SettingsUserEvent with _$SettingsUserEvent { class SettingsUserState with _$SettingsUserState { const factory SettingsUserState({ required UserProfilePB userProfile, - required Either successOrFailure, + required FlowyResult successOrFailure, }) = _SettingsUserState; factory SettingsUserState.initial(UserProfilePB userProfile) => SettingsUserState( userProfile: userProfile, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart index b7ef0e3f66..a6df92fa23 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_bloc.dart @@ -9,8 +9,8 @@ import 'package:appflowy/workspace/application/view/view_listener.dart'; import 'package:appflowy/workspace/application/view/view_service.dart'; 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:dartz/dartz.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:protobuf/protobuf.dart'; @@ -45,7 +45,7 @@ class ViewBloc extends Bloc { initial: (e) async { listener.start( onViewUpdated: (result) { - add(ViewEvent.viewDidUpdate(left(result))); + add(ViewEvent.viewDidUpdate(FlowyResult.success(result))); }, onViewChildViewsUpdated: (result) async { final view = await _updateChildViews(result); @@ -56,13 +56,20 @@ class ViewBloc extends Bloc { ); favoriteListener.start( favoritesUpdated: (result, isFavorite) { - result.fold((error) {}, (result) { - final current = result.items - .firstWhereOrNull((v) => v.id == state.view.id); - if (current != null) { - add(ViewEvent.viewDidUpdate(left(current))); - } - }); + result.fold( + (result) { + final current = result.items + .firstWhereOrNull((v) => v.id == state.view.id); + if (current != null) { + add( + ViewEvent.viewDidUpdate( + FlowyResult.success(current), + ), + ); + } + }, + (error) {}, + ); }, ); final isExpanded = await _getViewIsExpanded(view); @@ -95,12 +102,12 @@ class ViewBloc extends Bloc { emit( state.copyWith( view: view_ ?? view, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ), ); }, (error) => emit( - state.copyWith(successOrFailure: right(error)), + state.copyWith(successOrFailure: FlowyResult.failure(error)), ), ); }, @@ -118,11 +125,13 @@ class ViewBloc extends Bloc { (b) => b.name = e.newName, ); return state.copyWith( - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), view: newView, ); }, - (error) => state.copyWith(successOrFailure: right(error)), + (error) => state.copyWith( + successOrFailure: FlowyResult.failure(error), + ), ), ); }, @@ -130,8 +139,11 @@ class ViewBloc extends Bloc { final result = await ViewBackendService.delete(viewId: view.id); emit( result.fold( - (l) => state.copyWith(successOrFailure: left(unit)), - (error) => state.copyWith(successOrFailure: right(error)), + (l) => + state.copyWith(successOrFailure: FlowyResult.success(null)), + (error) => state.copyWith( + successOrFailure: FlowyResult.failure(error), + ), ), ); await RecentService().updateRecentViews([view.id], false); @@ -140,8 +152,11 @@ class ViewBloc extends Bloc { final result = await ViewBackendService.duplicate(view: view); emit( result.fold( - (l) => state.copyWith(successOrFailure: left(unit)), - (error) => state.copyWith(successOrFailure: right(error)), + (l) => + state.copyWith(successOrFailure: FlowyResult.success(null)), + (error) => state.copyWith( + successOrFailure: FlowyResult.failure(error), + ), ), ); }, @@ -153,8 +168,11 @@ class ViewBloc extends Bloc { ); emit( result.fold( - (l) => state.copyWith(successOrFailure: left(unit)), - (error) => state.copyWith(successOrFailure: right(error)), + (l) => + state.copyWith(successOrFailure: FlowyResult.success(null)), + (error) => state.copyWith( + successOrFailure: FlowyResult.failure(error), + ), ), ); }, @@ -172,9 +190,11 @@ class ViewBloc extends Bloc { result.fold( (view) => state.copyWith( lastCreatedView: view, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), + ), + (error) => state.copyWith( + successOrFailure: FlowyResult.failure(error), ), - (error) => state.copyWith(successOrFailure: right(error)), ), ); }, @@ -225,7 +245,7 @@ class ViewBloc extends Bloc { }, (error) => emit( state.copyWith( - successOrFailure: right(error), + successOrFailure: FlowyResult.failure(error), isExpanded: true, isLoading: false, ), @@ -235,10 +255,12 @@ class ViewBloc extends Bloc { Future _setViewIsExpanded(ViewPB view, bool isExpanded) async { final result = await getIt().get(KVKeys.expandedViews); - final map = result.fold( - () => {}, - (r) => jsonDecode(r), - ); + final Map map; + if (result != null) { + map = jsonDecode(result); + } else { + map = {}; + } if (isExpanded) { map[view.id] = true; } else { @@ -249,10 +271,11 @@ class ViewBloc extends Bloc { Future _getViewIsExpanded(ViewPB view) { return getIt().get(KVKeys.expandedViews).then((result) { - return result.fold(() => false, (r) { - final map = jsonDecode(r); - return map[view.id] ?? false; - }); + if (result == null) { + return false; + } + final map = jsonDecode(result); + return map[view.id] ?? false; }); } @@ -337,8 +360,9 @@ class ViewEvent with _$ViewEvent { /// open the view after created @Default(true) bool openAfterCreated, }) = CreateView; - const factory ViewEvent.viewDidUpdate(Either result) = - ViewDidUpdate; + const factory ViewEvent.viewDidUpdate( + FlowyResult result, + ) = ViewDidUpdate; const factory ViewEvent.viewUpdateChildView(ViewPB result) = ViewUpdateChildView; } @@ -349,7 +373,7 @@ class ViewState with _$ViewState { required ViewPB view, required bool isEditing, required bool isExpanded, - required Either successOrFailure, + required FlowyResult successOrFailure, @Default(true) bool isLoading, @Default(null) ViewPB? lastCreatedView, }) = _ViewState; @@ -358,6 +382,6 @@ class ViewState with _$ViewState { view: view, isExpanded: false, isEditing: false, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart index 3e111d72cf..395699f147 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_ext.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/generated/flowy_svgs.g.dart'; import 'package:appflowy/plugins/database/board/presentation/board_page.dart'; import 'package:appflowy/plugins/database/calendar/presentation/calendar_page.dart'; @@ -12,7 +10,8 @@ import 'package:appflowy/workspace/application/view/view_service.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; -import 'package:dartz/dartz.dart' hide id; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flutter/material.dart'; enum FlowyPlugin { editor, @@ -93,13 +92,13 @@ extension ViewExtension on ViewPB { final ancestors = []; if (includeSelf) { final self = await ViewBackendService.getView(id); - ancestors.add(self.getLeftOrNull() ?? this); + ancestors.add(self.fold((s) => s, (e) => this)); } - Either parent = + FlowyResult parent = await ViewBackendService.getView(parentViewId); - while (parent.isLeft()) { + while (parent.isSuccess()) { // parent is not null - final view = parent.getLeftOrNull(); + final view = parent.fold((s) => s, (e) => null); if (view == null || (!includeRoot && view.parentViewId.isEmpty)) { break; } diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart index d082cd84f6..95505b8216 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_listener.dart @@ -1,22 +1,23 @@ import 'dart:async'; import 'dart:typed_data'; + import 'package:appflowy/core/notification/folder_notification.dart'; import 'package:appflowy_backend/log.dart'; -import 'package:dartz/dartz.dart'; -import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-notification/subject.pb.dart'; import 'package:appflowy_backend/rust_stream.dart'; +import 'package:appflowy_result/appflowy_result.dart'; // Delete the view from trash, which means the view was deleted permanently -typedef DeleteViewNotifyValue = Either; +typedef DeleteViewNotifyValue = FlowyResult; // The view get updated typedef UpdateViewNotifiedValue = ViewPB; // Restore the view from trash -typedef RestoreViewNotifiedValue = Either; +typedef RestoreViewNotifiedValue = FlowyResult; // Move the view to trash -typedef MoveToTrashNotifiedValue = Either; +typedef MoveToTrashNotifiedValue = FlowyResult; class ViewListener { ViewListener({required this.viewId}); @@ -63,7 +64,7 @@ class ViewListener { void _handleObservableType( FolderNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case FolderNotification.DidUpdateView: @@ -86,22 +87,23 @@ class ViewListener { break; case FolderNotification.DidDeleteView: result.fold( - (payload) => _deletedNotifier?.call(left(ViewPB.fromBuffer(payload))), - (error) => _deletedNotifier?.call(right(error)), + (payload) => _deletedNotifier + ?.call(FlowyResult.success(ViewPB.fromBuffer(payload))), + (error) => _deletedNotifier?.call(FlowyResult.failure(error)), ); break; case FolderNotification.DidRestoreView: result.fold( - (payload) => - _restoredNotifier?.call(left(ViewPB.fromBuffer(payload))), - (error) => _restoredNotifier?.call(right(error)), + (payload) => _restoredNotifier + ?.call(FlowyResult.success(ViewPB.fromBuffer(payload))), + (error) => _restoredNotifier?.call(FlowyResult.failure(error)), ); break; case FolderNotification.DidMoveViewToTrash: result.fold( (payload) => _moveToTrashNotifier - ?.call(left(DeletedViewPB.fromBuffer(payload))), - (error) => _moveToTrashNotifier?.call(right(error)), + ?.call(FlowyResult.success(DeletedViewPB.fromBuffer(payload))), + (error) => _moveToTrashNotifier?.call(FlowyResult.failure(error)), ); break; default: diff --git a/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart b/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart index 8c31a69a76..893a11d9b1 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/view/view_service.dart @@ -3,10 +3,10 @@ import 'dart:async'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class ViewBackendService { - static Future> createView({ + static Future> createView({ /// The [layoutType] is the type of the view. required ViewLayoutPB layoutType, @@ -64,7 +64,7 @@ class ViewBackendService { /// The orphan view is meant to be a view that is not attached to any parent view. By default, this /// view will not be shown in the view list unless it is attached to a parent view that is shown in /// the view list. - static Future> createOrphanView({ + static Future> createOrphanView({ required String viewId, required ViewLayoutPB layoutType, required String name, @@ -84,7 +84,7 @@ class ViewBackendService { return FolderEventCreateOrphanView(payload).send(); } - static Future> createDatabaseLinkedView({ + static Future> createDatabaseLinkedView({ required String parentViewId, required String databaseId, required ViewLayoutPB layoutType, @@ -101,39 +101,47 @@ class ViewBackendService { } /// Returns a list of views that are the children of the given [viewId]. - static Future, FlowyError>> getChildViews({ + static Future, FlowyError>> getChildViews({ required String viewId, }) { final payload = ViewIdPB.create()..value = viewId; return FolderEventGetView(payload).send().then((result) { return result.fold( - (view) => left(view.childViews), - (error) => right(error), + (view) => FlowyResult.success(view.childViews), + (error) => FlowyResult.failure(error), ); }); } - static Future> delete({required String viewId}) { + static Future> delete({ + required String viewId, + }) { final request = RepeatedViewIdPB.create()..items.add(viewId); return FolderEventDeleteView(request).send(); } - static Future> deleteView({required String viewId}) { + static Future> deleteView({ + required String viewId, + }) { final request = RepeatedViewIdPB.create()..items.add(viewId); return FolderEventDeleteView(request).send(); } - static Future> duplicate({required ViewPB view}) { + static Future> duplicate({ + required ViewPB view, + }) { return FolderEventDuplicateView(view).send(); } - static Future> favorite({required String viewId}) { + static Future> favorite({ + required String viewId, + }) { final request = RepeatedViewIdPB.create()..items.add(viewId); return FolderEventToggleFavorite(request).send(); } - static Future> updateView({ + static Future> updateView({ required String viewId, String? name, bool? isFavorite, @@ -151,7 +159,7 @@ class ViewBackendService { return FolderEventUpdateView(payload).send(); } - static Future> updateViewIcon({ + static Future> updateViewIcon({ required String viewId, required String viewIcon, }) { @@ -166,7 +174,7 @@ class ViewBackendService { } // deprecated - static Future> moveView({ + static Future> moveView({ required String viewId, required int fromIndex, required int toIndex, @@ -183,7 +191,7 @@ class ViewBackendService { /// /// supports nested view /// if the [prevViewId] is null, the view will be moved to the beginning of the list - static Future> moveViewV2({ + static Future> moveViewV2({ required String viewId, required String newParentId, required String? prevViewId, @@ -214,7 +222,7 @@ class ViewBackendService { Future> fetchViews() async { final result = []; return FolderEventReadCurrentWorkspace().send().then((value) async { - final workspace = value.getLeftOrNull(); + final workspace = value.toNullable(); if (workspace != null) { final views = workspace.views; for (final view in views) { @@ -230,7 +238,7 @@ class ViewBackendService { Future> getAllViews(ViewPB view) async { final result = []; final childViews = await getChildViews(viewId: view.id).then( - (value) => value.getLeftOrNull>()?.toList(), + (value) => value.toNullable(), ); if (childViews != null && childViews.isNotEmpty) { result.addAll(childViews); @@ -242,35 +250,25 @@ class ViewBackendService { return result; } - static Future> getView( + static Future> getView( String viewID, ) async { final payload = ViewIdPB.create()..value = viewID; return FolderEventGetView(payload).send(); } - Future> getChildView({ + Future> getChildView({ required String parentViewId, required String childViewId, }) async { final payload = ViewIdPB.create()..value = parentViewId; return FolderEventGetView(payload).send().then((result) { return result.fold( - (app) => left( + (app) => FlowyResult.success( app.childViews.firstWhere((e) => e.id == childViewId), ), - (error) => right(error), + (error) => FlowyResult.failure(error), ); }); } } - -extension AppFlowy on Either { - T? getLeftOrNull() { - if (isLeft()) { - final result = fold((l) => l, (r) => null); - return result; - } - return null; - } -} diff --git a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_bloc.dart b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_bloc.dart index f7a7a2a24f..f74b435ad7 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_bloc.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_bloc.dart @@ -2,7 +2,7 @@ import 'package:appflowy/user/application/user_service.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:freezed_annotation/freezed_annotation.dart'; @@ -25,14 +25,16 @@ class WorkspaceBloc extends Bloc { createWorkspace: (e) async { await _createWorkspace(e.name, e.desc, emit); }, - workspacesReveived: (e) async { + workspacesReceived: (e) async { emit( e.workspacesOrFail.fold( (workspaces) => state.copyWith( workspaces: workspaces, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), + ), + (error) => state.copyWith( + successOrFailure: FlowyResult.failure(error), ), - (error) => state.copyWith(successOrFailure: right(error)), ), ); }, @@ -47,11 +49,11 @@ class WorkspaceBloc extends Bloc { workspacesOrFailed.fold( (workspaces) => state.copyWith( workspaces: workspaces, - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ), (error) { Log.error(error); - return state.copyWith(successOrFailure: right(error)); + return state.copyWith(successOrFailure: FlowyResult.failure(error)); }, ), ); @@ -66,11 +68,11 @@ class WorkspaceBloc extends Bloc { emit( result.fold( (workspace) { - return state.copyWith(successOrFailure: left(unit)); + return state.copyWith(successOrFailure: FlowyResult.success(null)); }, (error) { Log.error(error); - return state.copyWith(successOrFailure: right(error)); + return state.copyWith(successOrFailure: FlowyResult.failure(error)); }, ), ); @@ -82,8 +84,8 @@ class WorkspaceEvent with _$WorkspaceEvent { const factory WorkspaceEvent.initial() = Initial; const factory WorkspaceEvent.createWorkspace(String name, String desc) = CreateWorkspace; - const factory WorkspaceEvent.workspacesReveived( - Either, FlowyError> workspacesOrFail, + const factory WorkspaceEvent.workspacesReceived( + FlowyResult, FlowyError> workspacesOrFail, ) = WorkspacesReceived; } @@ -92,12 +94,12 @@ class WorkspaceState with _$WorkspaceState { const factory WorkspaceState({ required bool isLoading, required List workspaces, - required Either successOrFailure, + required FlowyResult successOrFailure, }) = _WorkspaceState; factory WorkspaceState.initial() => WorkspaceState( isLoading: false, workspaces: List.empty(), - successOrFailure: left(unit), + successOrFailure: FlowyResult.success(null), ); } diff --git a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart index 3168e3ff3a..4c5ba13ec0 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_listener.dart @@ -1,17 +1,18 @@ import 'dart:async'; import 'dart:typed_data'; + import 'package:appflowy/core/notification/folder_notification.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; -import 'package:dartz/dartz.dart'; -import 'package:flowy_infra/notifier.dart'; -import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' - show UserProfilePB; -import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/notification.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' + show UserProfilePB; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flowy_infra/notifier.dart'; -typedef AppListNotifyValue = Either, FlowyError>; -typedef WorkspaceNotifyValue = Either; +typedef AppListNotifyValue = FlowyResult, FlowyError>; +typedef WorkspaceNotifyValue = FlowyResult; class WorkspaceListener { WorkspaceListener({required this.user, required this.workspaceId}); @@ -45,21 +46,22 @@ class WorkspaceListener { void _handleObservableType( FolderNotification ty, - Either result, + FlowyResult result, ) { switch (ty) { case FolderNotification.DidUpdateWorkspace: result.fold( (payload) => _workspaceUpdatedNotifier?.value = - left(WorkspacePB.fromBuffer(payload)), - (error) => _workspaceUpdatedNotifier?.value = right(error), + FlowyResult.success(WorkspacePB.fromBuffer(payload)), + (error) => + _workspaceUpdatedNotifier?.value = FlowyResult.failure(error), ); break; case FolderNotification.DidUpdateWorkspaceViews: result.fold( (payload) => _appsChangedNotifier?.value = - left(RepeatedViewPB.fromBuffer(payload).items), - (error) => _appsChangedNotifier?.value = right(error), + FlowyResult.success(RepeatedViewPB.fromBuffer(payload).items), + (error) => _appsChangedNotifier?.value = FlowyResult.failure(error), ); break; default: diff --git a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart index da6f366ca1..3c29c9a4c1 100644 --- a/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart +++ b/frontend/appflowy_flutter/lib/workspace/application/workspace/workspace_service.dart @@ -1,18 +1,18 @@ import 'dart:async'; -import 'package:dartz/dartz.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart' show CreateViewPayloadPB, MoveViewPayloadPB, ViewLayoutPB, ViewPB; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; +import 'package:appflowy_result/appflowy_result.dart'; class WorkspaceService { WorkspaceService({required this.workspaceId}); final String workspaceId; - Future> createApp({ + Future> createApp({ required String name, String? desc, int? index, @@ -33,21 +33,21 @@ class WorkspaceService { return FolderEventCreateView(payload).send(); } - Future> getWorkspace() { + Future> getWorkspace() { return FolderEventReadCurrentWorkspace().send(); } - Future, FlowyError>> getViews() { + Future, FlowyError>> getViews() { final payload = WorkspaceIdPB.create()..value = workspaceId; return FolderEventReadWorkspaceViews(payload).send().then((result) { return result.fold( - (views) => left(views.items), - (error) => right(error), + (views) => FlowyResult.success(views.items), + (error) => FlowyResult.failure(error), ); }); } - Future> moveApp({ + Future> moveApp({ required String appId, required int fromIndex, required int toIndex, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart index 3335b67c8e..93cc5a81d5 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/desktop_home_screen.dart @@ -4,6 +4,7 @@ import 'package:appflowy/startup/startup.dart'; import 'package:appflowy/startup/tasks/memory_leak_detector.dart'; import 'package:appflowy/user/application/auth/auth_service.dart'; import 'package:appflowy/user/application/reminder/reminder_bloc.dart'; +import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart'; import 'package:appflowy/workspace/application/home/home_bloc.dart'; import 'package:appflowy/workspace/application/home/home_service.dart'; import 'package:appflowy/workspace/application/home/home_setting_bloc.dart'; @@ -13,7 +14,6 @@ import 'package:appflowy/workspace/application/view/view_ext.dart'; import 'package:appflowy/workspace/presentation/home/errors/workspace_failed_screen.dart'; import 'package:appflowy/workspace/presentation/home/hotkeys.dart'; import 'package:appflowy/workspace/presentation/home/menu/sidebar/sidebar.dart'; -import 'package:appflowy/workspace/application/favorite/favorite_bloc.dart'; import 'package:appflowy/workspace/presentation/widgets/edit_panel/panel_animation.dart'; import 'package:appflowy/workspace/presentation/widgets/float_bubble/question_bubble.dart'; import 'package:appflowy_backend/dispatch/dispatch.dart'; @@ -54,8 +54,8 @@ class DesktopHomeScreen extends StatelessWidget { (error) => null, ); final userProfile = snapshots.data?[1].fold( - (error) => null, (userProfilePB) => userProfilePB as UserProfilePB, + (error) => null, ); // In the unlikely case either of the above is null, eg. @@ -197,15 +197,16 @@ class DesktopHomeScreen extends StatelessWidget { buildWhen: (previous, current) => previous.panelContext != current.panelContext, builder: (context, state) { - return state.panelContext.fold( - () => const SizedBox(), - (panelContext) => FocusTraversalGroup( - child: RepaintBoundary( - child: EditPanel( - panelContext: panelContext, - onEndEdit: () => - homeBloc.add(const HomeSettingEvent.dismissEditPanel()), - ), + final panelContext = state.panelContext; + if (panelContext == null) { + return const SizedBox.shrink(); + } + return FocusTraversalGroup( + child: RepaintBoundary( + child: EditPanel( + panelContext: panelContext, + onEndEdit: () => + homeBloc.add(const HomeSettingEvent.dismissEditPanel()), ), ), ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart index b466ca9d2e..1da2ca32fa 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/home_layout.dart @@ -12,7 +12,7 @@ import 'home_sizes.dart'; class HomeLayout { HomeLayout(BuildContext context) { final homeSetting = context.read().state; - showEditPanel = homeSetting.panelContext.isSome(); + showEditPanel = homeSetting.panelContext != null; menuWidth = Sizes.sideBarWidth; menuWidth += homeSetting.resizeOffset; diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/rename_view_dialog.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/rename_view_dialog.dart index 3ec06bbd5c..964229e4cf 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/rename_view_dialog.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/rename_view_dialog.dart @@ -21,7 +21,7 @@ Future createViewAndShowRenameDialogIfNeeded( KVKeys.showRenameDialogWhenCreatingNewFile, (value) => bool.parse(value), ); - final showRenameDialog = value.fold(() => false, (r) => r); + final showRenameDialog = value ?? false; if (context.mounted && showRenameDialog) { await NavigatorTextFieldDialog( title: dialogTitle, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_user.dart b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_user.dart index 0532d8cfab..0572e2703b 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_user.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/home/menu/sidebar/sidebar_user.dart @@ -1,5 +1,3 @@ -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/more/cubit/document_appearance_cubit.dart'; @@ -14,11 +12,12 @@ import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart' show UserProfilePB; -import 'package:easy_localization/easy_localization.dart'; import 'package:appflowy_editor/appflowy_editor.dart' hide Log; +import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/style_widget/text.dart'; import 'package:flowy_infra_ui/widget/flowy_tooltip.dart'; import 'package:flowy_infra_ui/widget/spacing.dart'; +import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:hotkey_manager/hotkey_manager.dart'; @@ -28,10 +27,6 @@ Future openSettingsHotKey(BuildContext context) async { final userProfileOrFailure = await getIt().getUser(); return userProfileOrFailure.fold( - (e) { - Log.error('Failed to get user $e'); - return null; - }, (userProfile) => HotKeyItem( hotKey: HotKey( KeyCode.comma, @@ -49,6 +44,10 @@ Future openSettingsHotKey(BuildContext context) async { } }, ), + (e) { + Log.error('Failed to get user $e'); + return null; + }, ); } diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_view.dart index 0f02100801..facd3a2f0b 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/notifications/widgets/notification_view.dart @@ -1,5 +1,3 @@ -import 'package:flutter/material.dart'; - import 'package:appflowy/plugins/document/application/document_data_pb_extension.dart'; import 'package:appflowy/plugins/document/application/prelude.dart'; import 'package:appflowy/user/application/reminder/reminder_bloc.dart'; @@ -12,7 +10,8 @@ import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/reminder.pb.dart'; import 'package:appflowy_editor/appflowy_editor.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:flutter/material.dart'; /// Displays a Lsit of Notifications, currently used primarily to /// display Reminders. @@ -103,12 +102,12 @@ class NotificationsView extends StatelessWidget { } Future _getNodeFromDocument( - Future> documentFuture, + Future> documentFuture, String blockId, ) async { final document = (await documentFuture).fold( - (l) => null, (document) => document, + (_) => null, ); if (document == null) { diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart index f84fe9f374..30c7da23f2 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_appflowy_cloud.dart @@ -9,7 +9,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart'; -import 'package:dartz/dartz.dart' show Either; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -33,7 +33,7 @@ class AppFlowyCloudViewSetting extends StatelessWidget { @override Widget build(BuildContext context) { - return FutureBuilder>( + return FutureBuilder>( future: UserEventGetCloudConfig().send(), builder: (context, snapshot) { if (snapshot.data != null && @@ -94,7 +94,7 @@ class CustomAppFlowyCloudView extends StatelessWidget { @override Widget build(BuildContext context) { - return FutureBuilder>( + return FutureBuilder>( future: UserEventGetCloudConfig().send(), builder: (context, snapshot) { if (snapshot.data != null && @@ -303,11 +303,7 @@ class CloudURLInputState extends State { borderSide: BorderSide(color: Theme.of(context).colorScheme.primary), ), hintText: widget.hint, - errorText: context - .read() - .state - .urlError - .fold(() => null, (error) => error), + errorText: context.read().state.urlError, ), onChanged: widget.onChanged, ); diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_file_import_appflowy_data_view.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_file_import_appflowy_data_view.dart index a54e461db0..e3faa32a93 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_file_import_appflowy_data_view.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_file_import_appflowy_data_view.dart @@ -33,17 +33,12 @@ class _ImportAppFlowyDataState extends State { create: (context) => SettingFileImportBloc(), child: BlocListener( listener: (context, state) { - state.successOrFail.fold( - () {}, - (either) { - either.fold( - (unit) { - _showToast(LocaleKeys.settings_menu_importSuccess.tr()); - }, - (err) { - _showToast(LocaleKeys.settings_menu_importFailed.tr()); - }, - ); + state.successOrFail?.fold( + (_) { + _showToast(LocaleKeys.settings_menu_importSuccess.tr()); + }, + (_) { + _showToast(LocaleKeys.settings_menu_importFailed.tr()); }, ); }, diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart index 43e5472ef8..dbfaa3f7f6 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_supabase_cloud.dart @@ -8,7 +8,7 @@ import 'package:appflowy_backend/dispatch/dispatch.dart'; import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_setting.pb.dart'; -import 'package:dartz/dartz.dart' show Either; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/size.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; @@ -27,7 +27,7 @@ class SettingSupabaseCloudView extends StatelessWidget { @override Widget build(BuildContext context) { - return FutureBuilder>( + return FutureBuilder>( future: UserEventGetCloudConfig().send(), builder: (context, snapshot) { if (snapshot.data != null && @@ -102,7 +102,7 @@ class SupabaseCloudURLs extends StatelessWidget { .read() .add(SupabaseCloudURLsEvent.updateUrl(text)); }, - error: state.urlError.fold(() => null, (a) => a), + error: state.urlError, ), SupabaseInput( title: LocaleKeys.settings_menu_cloudSupabaseAnonKey.tr(), @@ -113,7 +113,7 @@ class SupabaseCloudURLs extends StatelessWidget { .read() .add(SupabaseCloudURLsEvent.updateAnonKey(text)); }, - error: state.anonKeyError.fold(() => null, (a) => a), + error: state.anonKeyError, ), const VSpace(20), RestartButton( diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_third_party_login.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_third_party_login.dart index 73bf46f285..e9ccc32b0e 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_third_party_login.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/setting_third_party_login.dart @@ -6,7 +6,7 @@ import 'package:appflowy/user/presentation/router.dart'; import 'package:appflowy/user/presentation/screens/sign_in_screen/widgets/widgets.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-user/user_profile.pb.dart'; -import 'package:dartz/dartz.dart'; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart'; import 'package:flowy_infra_ui/style_widget/snap_bar.dart'; @@ -24,10 +24,10 @@ class SettingThirdPartyLogin extends StatelessWidget { create: (context) => getIt(), child: BlocConsumer( listener: (context, state) { - state.successOrFail.fold( - () => null, - (result) => _handleSuccessOrFail(result, context), - ); + final successOrFail = state.successOrFail; + if (successOrFail != null) { + _handleSuccessOrFail(successOrFail, context); + } }, builder: (_, state) { final indicator = state.isSubmitting @@ -68,7 +68,7 @@ class SettingThirdPartyLogin extends StatelessWidget { } Future _handleSuccessOrFail( - Either result, + FlowyResult result, BuildContext context, ) async { result.fold( diff --git a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart index 6055f52182..efd789ed99 100644 --- a/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart +++ b/frontend/appflowy_flutter/lib/workspace/presentation/settings/widgets/settings_file_exporter_widget.dart @@ -10,7 +10,7 @@ import 'package:appflowy_backend/log.dart'; import 'package:appflowy_backend/protobuf/flowy-error/errors.pbserver.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/view.pb.dart'; import 'package:appflowy_backend/protobuf/flowy-folder/workspace.pb.dart'; -import 'package:dartz/dartz.dart' as dartz; +import 'package:appflowy_result/appflowy_result.dart'; import 'package:easy_localization/easy_localization.dart'; import 'package:flowy_infra/file_picker/file_picker_service.dart'; import 'package:flowy_infra_ui/flowy_infra_ui.dart' hide WidgetBuilder; @@ -34,12 +34,12 @@ class _FileExporterWidgetState extends State { @override Widget build(BuildContext context) { - return FutureBuilder>( + return FutureBuilder>( future: FolderEventReadCurrentWorkspace().send(), builder: (context, snapshot) { if (snapshot.hasData && snapshot.connectionState == ConnectionState.done) { - final workspace = snapshot.data?.getLeftOrNull(); + final workspace = snapshot.data?.fold((s) => s, (e) => null); if (workspace != null) { final views = workspace.views; cubit ??= SettingsFileExporterCubit(views: views); @@ -224,17 +224,6 @@ class _ExpandedListState extends State<_ExpandedList> { } } -extension AppFlowy on dartz.Either { - T? getLeftOrNull() { - if (isLeft()) { - final result = fold((l) => l, (r) => null); - return result; - } - - return null; - } -} - class _AppFlowyFileExporter { static Future<(bool result, List failedNames)> exportToPath( String path, @@ -251,9 +240,12 @@ class _AppFlowyFileExporter { final result = await documentExporter.export( DocumentExportType.json, ); - result.fold((l) => Log.error(l), (json) { - content = json; - }); + result.fold( + (json) { + content = json; + }, + (e) => Log.error(e), + ); fileExtension = 'afdocument'; break; default: diff --git a/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart b/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart index 816ff76d02..d32663f470 100644 --- a/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart +++ b/frontend/appflowy_flutter/packages/appflowy_backend/lib/dispatch/dispatch.dart @@ -1,37 +1,37 @@ +import 'dart:async'; +import 'dart:convert' show utf8; import 'dart:ffi'; -import 'package:dartz/dartz.dart'; +import 'dart:typed_data'; + +import 'package:appflowy_backend/ffi.dart' as ffi; import 'package:appflowy_backend/log.dart'; // ignore: unnecessary_import import 'package:appflowy_backend/protobuf/dart-ffi/ffi_response.pb.dart'; -import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; -import 'package:isolates/isolates.dart'; -import 'package:isolates/ports.dart'; -import 'package:ffi/ffi.dart'; -import 'package:flutter/services.dart'; -import 'dart:async'; -import 'dart:typed_data'; -import 'package:appflowy_backend/ffi.dart' as ffi; -import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; import 'package:appflowy_backend/protobuf/dart-ffi/protobuf.dart'; -import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/protobuf.dart'; import 'package:appflowy_backend/protobuf/flowy-document/protobuf.dart'; - +import 'package:appflowy_backend/protobuf/flowy-error/errors.pb.dart'; +import 'package:appflowy_backend/protobuf/flowy-folder/protobuf.dart'; +import 'package:appflowy_backend/protobuf/flowy-user/protobuf.dart'; +import 'package:appflowy_result/appflowy_result.dart'; +import 'package:ffi/ffi.dart'; +import 'package:flutter/services.dart'; +import 'package:isolates/isolates.dart'; +import 'package:isolates/ports.dart'; import 'package:protobuf/protobuf.dart'; -import 'dart:convert' show utf8; + import '../protobuf/flowy-config/entities.pb.dart'; import '../protobuf/flowy-config/event_map.pb.dart'; -import 'error.dart'; - import '../protobuf/flowy-date/entities.pb.dart'; import '../protobuf/flowy-date/event_map.pb.dart'; +import 'error.dart'; +part 'dart_event/flowy-config/dart_event.dart'; +part 'dart_event/flowy-database2/dart_event.dart'; +part 'dart_event/flowy-date/dart_event.dart'; +part 'dart_event/flowy-document/dart_event.dart'; part 'dart_event/flowy-folder/dart_event.dart'; part 'dart_event/flowy-user/dart_event.dart'; -part 'dart_event/flowy-database2/dart_event.dart'; -part 'dart_event/flowy-document/dart_event.dart'; -part 'dart_event/flowy-config/dart_event.dart'; -part 'dart_event/flowy-date/dart_event.dart'; enum FFIException { RequestIsEmpty, @@ -43,7 +43,8 @@ class DispatchException implements Exception { } class Dispatch { - static Future> asyncRequest(FFIRequest request) { + static Future> asyncRequest( + FFIRequest request) { // FFIRequest => Rust SDK final bytesFuture = _sendToRust(request); @@ -57,43 +58,43 @@ class Dispatch { } } -Future> _extractPayload( - Future> responseFuture) { +Future> _extractPayload( + Future> responseFuture) { return responseFuture.then((result) { return result.fold( (response) { switch (response.code) { case FFIStatusCode.Ok: - return left(Uint8List.fromList(response.payload)); + return FlowySuccess(Uint8List.fromList(response.payload)); case FFIStatusCode.Err: - return right(Uint8List.fromList(response.payload)); + return FlowyFailure(Uint8List.fromList(response.payload)); case FFIStatusCode.Internal: final error = utf8.decode(response.payload); Log.error("Dispatch internal error: $error"); - return right(emptyBytes()); + return FlowyFailure(emptyBytes()); default: Log.error("Impossible to here"); - return right(emptyBytes()); + return FlowyFailure(emptyBytes()); } }, (error) { Log.error("Response should not be empty $error"); - return right(emptyBytes()); + return FlowyFailure(emptyBytes()); }, ); }); } -Future> _extractResponse( +Future> _extractResponse( Completer bytesFuture) { return bytesFuture.future.then((bytes) { try { final response = FFIResponse.fromBuffer(bytes); - return left(response); + return FlowySuccess(response); } catch (e, s) { final error = StackTraceError(e, s); Log.error('Deserialize response failed. ${error.toString()}'); - return right(error.asFlowyError()); + return FlowyFailure(error.asFlowyError()); } }); } diff --git a/frontend/appflowy_flutter/packages/appflowy_backend/pubspec.yaml b/frontend/appflowy_flutter/packages/appflowy_backend/pubspec.yaml index 318cd173cc..c014da75df 100644 --- a/frontend/appflowy_flutter/packages/appflowy_backend/pubspec.yaml +++ b/frontend/appflowy_flutter/packages/appflowy_backend/pubspec.yaml @@ -14,11 +14,12 @@ dependencies: ffi: ^2.0.2 isolates: ^3.0.3+8 protobuf: ^3.1.0 - dartz: ^0.10.1 freezed_annotation: logger: ^2.0.0 plugin_platform_interface: ^2.1.3 json_annotation: ^4.7.0 + appflowy_result: + path: ../appflowy_result dev_dependencies: flutter_test: diff --git a/frontend/appflowy_flutter/packages/appflowy_result/.gitignore b/frontend/appflowy_flutter/packages/appflowy_result/.gitignore new file mode 100644 index 0000000000..ac5aa9893e --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/.gitignore @@ -0,0 +1,29 @@ +# Miscellaneous +*.class +*.log +*.pyc +*.swp +.DS_Store +.atom/ +.buildlog/ +.history +.svn/ +migrate_working_dir/ + +# IntelliJ related +*.iml +*.ipr +*.iws +.idea/ + +# The .vscode folder contains launch configuration and tasks you configure in +# VS Code which you may wish to be included in version control, so this line +# is commented out by default. +#.vscode/ + +# Flutter/Dart/Pub related +# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock. +/pubspec.lock +**/doc/api/ +.dart_tool/ +build/ diff --git a/frontend/appflowy_flutter/packages/appflowy_result/.metadata b/frontend/appflowy_flutter/packages/appflowy_result/.metadata new file mode 100644 index 0000000000..ea18fe993d --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/.metadata @@ -0,0 +1,10 @@ +# This file tracks properties of this Flutter project. +# Used by Flutter tool to assess capabilities and perform upgrades etc. +# +# This file should be version controlled and should not be manually edited. + +version: + revision: "bae5e49bc2a867403c43b2aae2de8f8c33b037e4" + channel: "[user-branch]" + +project_type: package diff --git a/frontend/appflowy_flutter/packages/appflowy_result/CHANGELOG.md b/frontend/appflowy_flutter/packages/appflowy_result/CHANGELOG.md new file mode 100644 index 0000000000..41cc7d8192 --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/CHANGELOG.md @@ -0,0 +1,3 @@ +## 0.0.1 + +* TODO: Describe initial release. diff --git a/frontend/appflowy_flutter/packages/appflowy_result/LICENSE b/frontend/appflowy_flutter/packages/appflowy_result/LICENSE new file mode 100644 index 0000000000..ba75c69f7f --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/LICENSE @@ -0,0 +1 @@ +TODO: Add your license here. diff --git a/frontend/appflowy_flutter/packages/appflowy_result/README.md b/frontend/appflowy_flutter/packages/appflowy_result/README.md new file mode 100644 index 0000000000..02fe8ecabc --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/README.md @@ -0,0 +1,39 @@ + + +TODO: Put a short description of the package here that helps potential users +know whether this package might be useful for them. + +## Features + +TODO: List what your package can do. Maybe include images, gifs, or videos. + +## Getting started + +TODO: List prerequisites and provide or point to information on how to +start using the package. + +## Usage + +TODO: Include short and useful examples for package users. Add longer examples +to `/example` folder. + +```dart +const like = 'sample'; +``` + +## Additional information + +TODO: Tell users more about the package: where to find more information, how to +contribute to the package, how to file issues, what response they can expect +from the package authors, and more. diff --git a/frontend/appflowy_flutter/packages/appflowy_result/analysis_options.yaml b/frontend/appflowy_flutter/packages/appflowy_result/analysis_options.yaml new file mode 100644 index 0000000000..a5744c1cfb --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/analysis_options.yaml @@ -0,0 +1,4 @@ +include: package:flutter_lints/flutter.yaml + +# Additional information about this file can be found at +# https://dart.dev/guides/language/analysis-options diff --git a/frontend/appflowy_flutter/packages/appflowy_result/lib/appflowy_result.dart b/frontend/appflowy_flutter/packages/appflowy_result/lib/appflowy_result.dart new file mode 100644 index 0000000000..1f19ffaa41 --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/lib/appflowy_result.dart @@ -0,0 +1,3 @@ +library appflowy_result; + +export 'src/result.dart'; diff --git a/frontend/appflowy_flutter/packages/appflowy_result/lib/src/result.dart b/frontend/appflowy_flutter/packages/appflowy_result/lib/src/result.dart new file mode 100644 index 0000000000..ac056f3b97 --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/lib/src/result.dart @@ -0,0 +1,117 @@ +abstract class FlowyResult { + const FlowyResult(); + + factory FlowyResult.success(S s) => FlowySuccess(s); + + factory FlowyResult.failure(F e) => FlowyFailure(e); + + T fold(T Function(S s) onSuccess, T Function(F e) onFailure); + + FlowyResult map(T Function(S success) fn); + FlowyResult mapError(T Function(F error) fn); + + bool isSuccess(); + bool isFailure(); + + S? toNullable(); +} + +class FlowySuccess implements FlowyResult { + final S _value; + + FlowySuccess(this._value); + + S get value => _value; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is FlowySuccess && + runtimeType == other.runtimeType && + _value == other._value; + + @override + int get hashCode => _value.hashCode; + + @override + String toString() => 'Success(value: $_value)'; + + @override + T fold(T Function(S s) onSuccess, T Function(F e) onFailure) => + onSuccess(_value); + + @override + map(T Function(S success) fn) { + return FlowySuccess(fn(_value)); + } + + @override + FlowyResult mapError(T Function(F error) fn) { + return FlowySuccess(_value); + } + + @override + bool isSuccess() { + return true; + } + + @override + bool isFailure() { + return false; + } + + @override + S? toNullable() { + return _value; + } +} + +class FlowyFailure implements FlowyResult { + final F _error; + + FlowyFailure(this._error); + + F get error => _error; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is FlowyFailure && + runtimeType == other.runtimeType && + _error == other._error; + + @override + int get hashCode => _error.hashCode; + + @override + String toString() => 'Failure(error: $_error)'; + + @override + T fold(T Function(S s) onSuccess, T Function(F e) onFailure) => + onFailure(_error); + + @override + map(T Function(S success) fn) { + return FlowyFailure(_error); + } + + @override + FlowyResult mapError(T Function(F error) fn) { + return FlowyFailure(fn(_error)); + } + + @override + bool isSuccess() { + return false; + } + + @override + bool isFailure() { + return true; + } + + @override + S? toNullable() { + return null; + } +} diff --git a/frontend/appflowy_flutter/packages/appflowy_result/pubspec.yaml b/frontend/appflowy_flutter/packages/appflowy_result/pubspec.yaml new file mode 100644 index 0000000000..241f437d9b --- /dev/null +++ b/frontend/appflowy_flutter/packages/appflowy_result/pubspec.yaml @@ -0,0 +1,54 @@ +name: appflowy_result +description: "A new Flutter package project." +version: 0.0.1 +homepage: + +environment: + sdk: '>=3.3.0 <4.0.0' + flutter: ">=1.17.0" + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^3.0.0 + +# For information on the generic Dart part of this file, see the +# following page: https://dart.dev/tools/pub/pubspec + +# The following section is specific to Flutter packages. +flutter: + + # To add assets to your package, add an assets section, like this: + # assets: + # - images/a_dot_burr.jpeg + # - images/a_dot_ham.jpeg + # + # For details regarding assets in packages, see + # https://flutter.dev/assets-and-images/#from-packages + # + # An image asset can refer to one or more resolution-specific "variants", see + # https://flutter.dev/assets-and-images/#resolution-aware + + # To add custom fonts to your package, add a fonts section here, + # in this "flutter" section. Each entry in this list should have a + # "family" key with the font family name, and a "fonts" key with a + # list giving the asset and other descriptors for the font. For + # example: + # fonts: + # - family: Schyler + # fonts: + # - asset: fonts/Schyler-Regular.ttf + # - asset: fonts/Schyler-Italic.ttf + # style: italic + # - family: Trajan Pro + # fonts: + # - asset: fonts/TrajanPro.ttf + # - asset: fonts/TrajanPro_Bold.ttf + # weight: 700 + # + # For details regarding fonts in packages, see + # https://flutter.dev/custom-fonts/#from-packages diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart index 0345102d8c..97d368eab6 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/lib/src/flowy_overlay/flowy_overlay.dart @@ -292,7 +292,7 @@ class FlowyOverlayState extends State { RenderObject renderObject = anchorContext.findRenderObject()!; assert( renderObject is RenderBox, - 'Unexpected non-RenderBox render object caught.', + 'Unexpecteded non-RenderBox render object caught.', ); final renderBox = renderObject as RenderBox; targetAnchorPosition = renderBox.localToGlobal(Offset.zero); diff --git a/frontend/appflowy_flutter/packages/flowy_infra_ui/pubspec.yaml b/frontend/appflowy_flutter/packages/flowy_infra_ui/pubspec.yaml index 816ac4d160..3d73a51d7b 100644 --- a/frontend/appflowy_flutter/packages/flowy_infra_ui/pubspec.yaml +++ b/frontend/appflowy_flutter/packages/flowy_infra_ui/pubspec.yaml @@ -13,7 +13,6 @@ dependencies: sdk: flutter # Thirdparty packages - dartz: provider: ^6.0.5 styled_widget: ^0.4.1 equatable: ^2.0.5 diff --git a/frontend/appflowy_flutter/pubspec.lock b/frontend/appflowy_flutter/pubspec.lock index 44516648fd..73c3adda34 100644 --- a/frontend/appflowy_flutter/pubspec.lock +++ b/frontend/appflowy_flutter/pubspec.lock @@ -74,6 +74,13 @@ packages: relative: true source: path version: "0.0.1" + appflowy_result: + dependency: "direct main" + description: + path: "packages/appflowy_result" + relative: true + source: path + version: "0.0.1" archive: dependency: "direct main" description: @@ -339,14 +346,6 @@ packages: url: "https://pub.dev" source: hosted version: "2.3.4" - dartz: - dependency: "direct main" - description: - name: dartz - sha256: e6acf34ad2e31b1eb00948692468c30ab48ac8250e0f0df661e29f12dd252168 - url: "https://pub.dev" - source: hosted - version: "0.10.1" dbus: dependency: transitive description: @@ -2187,5 +2186,5 @@ packages: source: hosted version: "2.0.0" sdks: - dart: ">=3.3.0-279.1.beta <4.0.0" + dart: ">=3.3.0 <4.0.0" flutter: ">=3.19.0" diff --git a/frontend/appflowy_flutter/pubspec.yaml b/frontend/appflowy_flutter/pubspec.yaml index 00068fc836..3203aa1391 100644 --- a/frontend/appflowy_flutter/pubspec.yaml +++ b/frontend/appflowy_flutter/pubspec.yaml @@ -44,6 +44,8 @@ dependencies: git: url: https://github.com/AppFlowy-IO/appflowy-board.git ref: 15a3a50 + appflowy_result: + path: packages/appflowy_result appflowy_editor: appflowy_editor_plugins: git: @@ -61,7 +63,6 @@ dependencies: get_it: ^7.6.0 flutter_bloc: ^8.1.3 flutter_math_fork: ^0.7.2 - dartz: ^0.10.1 provider: ^6.0.5 path_provider: ^2.0.15 sized_context: ^1.0.0+4 diff --git a/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart b/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart index 415df571df..e12fe5e23e 100644 --- a/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart +++ b/frontend/appflowy_flutter/test/bloc_test/grid_test/cell/select_option_cell_test.dart @@ -1,8 +1,8 @@ import 'package:appflowy/plugins/database/application/cell/bloc/select_option_editor_bloc.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/field_entities.pbenum.dart'; import 'package:appflowy_backend/protobuf/flowy-database2/select_option_entities.pb.dart'; -import 'package:dartz/dartz.dart'; import 'package:flutter_test/flutter_test.dart'; + import '../util.dart'; void main() { @@ -179,7 +179,7 @@ void main() { assert(bloc.state.selectedOptions.length == 1); expect(bloc.state.selectedOptions[0].name, "A"); - expect(bloc.state.filter, const Some("x")); + expect(bloc.state.filter, "x"); }); test('filter options', () async { @@ -231,8 +231,8 @@ void main() { 3, reason: "Options: ${bloc.state.options}", ); - expect(bloc.state.createOption, const Some("a")); - expect(bloc.state.filter, const Some("a")); + expect(bloc.state.createOption, "a"); + expect(bloc.state.filter, "a"); }); }); } diff --git a/frontend/appflowy_flutter/test/util.dart b/frontend/appflowy_flutter/test/util.dart index eb42a07596..2cf163688d 100644 --- a/frontend/appflowy_flutter/test/util.dart +++ b/frontend/appflowy_flutter/test/util.dart @@ -47,13 +47,13 @@ class AppFlowyUnitTest { email: userEmail, ); result.fold( - (error) { - assert(false, 'Error: $error'); - }, (user) { userProfile = user; userService = UserBackendService(userId: userProfile.id); }, + (error) { + assert(false, 'Error: $error'); + }, ); } diff --git a/frontend/resources/translations/fr-CA.json b/frontend/resources/translations/fr-CA.json index f84eccfb67..9397a95599 100644 --- a/frontend/resources/translations/fr-CA.json +++ b/frontend/resources/translations/fr-CA.json @@ -314,7 +314,7 @@ "importSuccess": "Importation réussie du dossier de données AppFlowy", "importFailed": "L'importation du dossier de données AppFlowy a échoué", "importGuide": "Pour plus de détails, veuillez consulter le document référencé", - "supabaseSetting": "Paramètre Supbase" + "supabaseSetting": "Paramètre Supabase" }, "notifications": { "enableNotifications": { diff --git a/frontend/resources/translations/fr-FR.json b/frontend/resources/translations/fr-FR.json index 91c5e89716..a2d14e4bcf 100644 --- a/frontend/resources/translations/fr-FR.json +++ b/frontend/resources/translations/fr-FR.json @@ -314,7 +314,7 @@ "importSuccess": "Importation réussie du dossier de données AppFlowy", "importFailed": "L'importation du dossier de données AppFlowy a échoué", "importGuide": "Pour plus de détails, veuillez consulter le document référencé", - "supabaseSetting": "Paramètre Supbase" + "supabaseSetting": "Paramètre Supabase" }, "notifications": { "enableNotifications": { diff --git a/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.rs b/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.rs index 82ca535578..ecd7b63927 100644 --- a/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.rs +++ b/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.rs @@ -32,7 +32,7 @@ impl EventTemplate { .tera_context .insert("has_input", &ctx.input_deserializer.is_some()); match ctx.input_deserializer { - None => self.tera_context.insert("input_deserializer", "Unit"), + None => self.tera_context.insert("input_deserializer", "void"), Some(ref input) => self.tera_context.insert("input_deserializer", input), } @@ -45,7 +45,7 @@ impl EventTemplate { self.tera_context.insert("has_output", &has_output); match ctx.output_deserializer { - None => self.tera_context.insert("output_deserializer", "Unit"), + None => self.tera_context.insert("output_deserializer", "void"), Some(ref output) => self.tera_context.insert("output_deserializer", output), } diff --git a/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.tera b/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.tera index 445807ea33..b54b5262b7 100644 --- a/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.tera +++ b/frontend/rust-lib/build-tool/flowy-codegen/src/dart_event/event_template.tera @@ -6,7 +6,7 @@ class {{ event_class }} { {{ event_class }}(); {%- endif %} - Future> send() { + Future> send() { {%- if has_input %} final request = FFIRequest.create() @@ -17,11 +17,11 @@ class {{ event_class }} { .then((bytesResult) => bytesResult.fold( {%- if has_output %} - (okBytes) => left({{ output_deserializer }}.fromBuffer(okBytes)), + (okBytes) => FlowySuccess({{ output_deserializer }}.fromBuffer(okBytes)), {%- else %} - (bytes) => left(unit), + (bytes) => FlowySuccess(null), {%- endif %} - (errBytes) => right({{ error_deserializer }}.fromBuffer(errBytes)), + (errBytes) => FlowyFailure({{ error_deserializer }}.fromBuffer(errBytes)), )); {%- else %} @@ -33,11 +33,11 @@ class {{ event_class }} { return Dispatch.asyncRequest(request).then((bytesResult) => bytesResult.fold( {%- if has_output %} - (okBytes) => left({{ output_deserializer }}.fromBuffer(okBytes)), + (okBytes) => FlowySuccess({{ output_deserializer }}.fromBuffer(okBytes)), {%- else %} - (bytes) => left(unit), + (bytes) => FlowySuccess(null), {%- endif %} - (errBytes) => right({{ error_deserializer }}.fromBuffer(errBytes)), + (errBytes) => FlowyFailure({{ error_deserializer }}.fromBuffer(errBytes)), )); {%- endif %} }