diff --git a/packages/neon/neon/lib/src/bloc/result.dart b/packages/neon/neon/lib/src/bloc/result.dart index 96593a3a..9840ef82 100644 --- a/packages/neon/neon/lib/src/bloc/result.dart +++ b/packages/neon/neon/lib/src/bloc/result.dart @@ -2,28 +2,43 @@ import 'package:meta/meta.dart'; @immutable class Result { - const Result( + Result( this.data, this.error, { required this.isLoading, required this.isCached, - }); + }) : assert( + T != Never, + 'Result() called without specifying the data type. Call Result() instead', + ); - const Result.loading() + Result.loading() : data = null, error = null, isLoading = true, - isCached = false; + isCached = false, + assert( + T != Never, + 'Result.loading() called without specifying the data type. Call Result.loading() instead', + ); - const Result.success(this.data) + Result.success(this.data) : error = null, isLoading = false, - isCached = false; + isCached = false, + assert( + T != Never, + 'Result.success() called without specifying the data type. Call Result.success() instead', + ); - const Result.error(this.error) + Result.error(this.error) : data = null, isLoading = false, - isCached = false; + isCached = false, + assert( + T != Never, + 'Result.error() called without specifying the data type. Call Result.error() instead', + ); final T? data; final Object? error; @@ -55,6 +70,7 @@ class Result { bool get hasError => error != null; bool get hasData => data != null; + bool get hasUncachedData => hasData && !isCached; T get requireData { diff --git a/packages/neon/neon/lib/src/blocs/login_check_account.dart b/packages/neon/neon/lib/src/blocs/login_check_account.dart index 5762e709..1d1b7bf0 100644 --- a/packages/neon/neon/lib/src/blocs/login_check_account.dart +++ b/packages/neon/neon/lib/src/blocs/login_check_account.dart @@ -45,7 +45,7 @@ class LoginCheckAccountBloc extends InteractiveBloc @override Future refresh() async { - state.add(const Result.loading()); + state.add(Result.loading()); try { final client = NextcloudClient( diff --git a/packages/neon/neon/lib/src/blocs/login_check_server_status.dart b/packages/neon/neon/lib/src/blocs/login_check_server_status.dart index 5cde597d..73a42f57 100644 --- a/packages/neon/neon/lib/src/blocs/login_check_server_status.dart +++ b/packages/neon/neon/lib/src/blocs/login_check_server_status.dart @@ -38,7 +38,7 @@ class LoginCheckServerStatusBloc extends InteractiveBloc @override Future refresh() async { - state.add(const Result.loading()); + state.add(Result.loading()); try { final client = NextcloudClient( diff --git a/packages/neon/neon/lib/src/blocs/login_flow.dart b/packages/neon/neon/lib/src/blocs/login_flow.dart index 6c7f0a2c..2f640bdd 100644 --- a/packages/neon/neon/lib/src/blocs/login_flow.dart +++ b/packages/neon/neon/lib/src/blocs/login_flow.dart @@ -51,7 +51,7 @@ class LoginFlowBloc extends InteractiveBloc implements LoginFlowBlocEvents, Logi @override Future refresh() async { try { - init.add(const Result.loading()); + init.add(Result.loading()); final initResponse = await _client.core.clientFlowLoginV2.init(); init.add(Result.success(initResponse.body)); diff --git a/packages/neon/neon/lib/src/blocs/unified_search.dart b/packages/neon/neon/lib/src/blocs/unified_search.dart index 94305ab6..e99933ab 100644 --- a/packages/neon/neon/lib/src/blocs/unified_search.dart +++ b/packages/neon/neon/lib/src/blocs/unified_search.dart @@ -48,7 +48,7 @@ class UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBlocEven @override BehaviorSubject>?>> results = - BehaviorSubject.seeded(const Result.success(null)); + BehaviorSubject.seeded(Result.success(null)); @override void dispose() { @@ -76,13 +76,13 @@ class UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBlocEven @override void disable() { enabled.add(false); - results.add(const Result.success(null)); + results.add(Result.success(null)); _term = ''; } Future _search() async { if (_term.isEmpty) { - results.add(const Result.success(null)); + results.add(Result.success(null)); return; } @@ -107,12 +107,12 @@ class UnifiedSearchBloc extends InteractiveBloc implements UnifiedSearchBlocEven final Iterable providers, ) sync* { for (final provider in providers) { - yield MapEntry(provider, const Result.loading()); + yield MapEntry(provider, Result.loading()); } } Future _searchProvider(final CoreUnifiedSearchProvider provider) async { - _updateResults(provider, const Result.loading()); + _updateResults(provider, Result.loading()); try { final response = await _account.client.core.unifiedSearch.search( providerId: provider.id, diff --git a/packages/neon/neon/lib/src/blocs/user_statuses.dart b/packages/neon/neon/lib/src/blocs/user_statuses.dart index 24a24c29..eee802de 100644 --- a/packages/neon/neon/lib/src/blocs/user_statuses.dart +++ b/packages/neon/neon/lib/src/blocs/user_statuses.dart @@ -58,7 +58,7 @@ class UserStatusesBloc extends InteractiveBloc implements UserStatusesBlocEvents } try { - _updateStatus(username, const Result.loading()); + _updateStatus(username, Result.loading()); UserStatusPublicInterface? data; @@ -90,7 +90,7 @@ class UserStatusesBloc extends InteractiveBloc implements UserStatusesBlocEvents _updateStatus(username, Result.success(data)); } catch (e, s) { if (e is DynamiteApiException && e.statusCode == 404) { - _updateStatus(username, const Result.success(null)); + _updateStatus(username, Result.success(null)); return; } debugPrint(e.toString()); diff --git a/packages/neon/neon/lib/src/utils/request_manager.dart b/packages/neon/neon/lib/src/utils/request_manager.dart index 8c1dee02..5222f823 100644 --- a/packages/neon/neon/lib/src/utils/request_manager.dart +++ b/packages/neon/neon/lib/src/utils/request_manager.dart @@ -102,7 +102,7 @@ class RequestManager { final int retries = 0, ]) async { // emit loading state with the current value if present - final value = subject.valueOrNull?.asLoading() ?? const Result.loading(); + final value = subject.valueOrNull?.asLoading() ?? Result.loading(); subject.add(value); final key = '$clientID-$k'; diff --git a/packages/neon/neon/test/result_test.dart b/packages/neon/neon/test/result_test.dart index bd4171a7..d109f5c4 100644 --- a/packages/neon/neon/test/result_test.dart +++ b/packages/neon/neon/test/result_test.dart @@ -8,13 +8,13 @@ void main() { test('Equality', () { const data = 'someData'; - const a = Result( + final a = Result( data, null, isLoading: true, isCached: false, ); - const b = Result( + final b = Result( data, null, isLoading: true, @@ -31,8 +31,8 @@ void main() { test('Transform to loading', () { const data = 'someData'; - const a = Result.success(data); - const b = Result( + final a = Result.success(data); + final b = Result( data, null, isLoading: true, @@ -46,9 +46,9 @@ void main() { test('data check', () { const data = 'someData'; - const a = Result.loading(); - const b = Result.success(data); - const c = Result( + final a = Result.loading(); + final b = Result.success(data); + final c = Result( data, null, isLoading: false, @@ -68,7 +68,7 @@ void main() { test('error check', () { const error = 'someError'; - const a = Result.error(error); + final a = Result.error(error); expect(a.hasError, true); }); @@ -76,11 +76,25 @@ void main() { test('transform', () { const data = 1; - const a = Result.success(data); + final a = Result.success(data); String transformer(final int data) => data.toString(); expect(a.transform(transformer), equals(Result.success(data.toString()))); }); + + test('copyWith', () { + expect(Result('String', 'error', isLoading: false, isCached: false).copyWith(data: '').data, ''); + expect(Result('String', 'error', isLoading: false, isCached: false).copyWith(data: '').data, ''); + + expect(Result.loading().copyWith(data: '').isLoading, true); + expect(Result.loading().copyWith(data: '').isLoading, true); + + expect(Result.success('String').copyWith(data: '').data, ''); + expect(Result.success('String').copyWith(data: '').data, ''); + + expect(Result.error('error').copyWith(data: '').error, 'error'); + expect(Result.error('error').copyWith(data: '').error, 'error'); + }); }); }