Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions lib/core/network/failure.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
sealed class Failure {
const Failure();
}

final class SomeFailure extends Failure {
final String error;

const SomeFailure(this.error);

@override
String toString() => error;
}
29 changes: 29 additions & 0 deletions lib/core/network/result.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
import 'package:bloc_example/core/network/failure.dart';

sealed class Result<T> {
const Result();

factory Result.ok(T value) = Ok<T>;

factory Result.err(Failure failure) = Err<T>;

R fold<R>({
required R Function(Failure) onErr,
required R Function(T) onOk,
}) => switch (this) {
Err<T>(:final failure) => onErr(failure),
Ok<T>(:final value) => onOk(value),
};
}

final class Ok<T> extends Result<T> {
final T value;

const Ok(this.value);
}

final class Err<T> extends Result<T> {
final Failure failure;

const Err(this.failure);
}
151 changes: 151 additions & 0 deletions lib/features/users/bloc/users_bloc.dart
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import 'package:bloc_concurrency/bloc_concurrency.dart';
import 'package:bloc_example/core/bloc/transformers/measure_time.dart';
import 'package:bloc_example/core/network/failure.dart';
import 'package:bloc_example/core/network/result.dart';
import 'package:bloc_example/features/users/bloc/users_bloc_event.dart';
import 'package:bloc_example/features/users/bloc/users_bloc_state.dart';
import 'package:bloc_example/features/users/model/user.dart';
Expand Down Expand Up @@ -27,6 +29,7 @@ class UsersBloc extends HydratedBloc<UsersBlocEvent, UsersBlocState> {
}
}

// --- RECORDS ---
Future<void> _onFetch(
UsersBlocEventFetch event,
Emitter<UsersBlocState> emit,
Expand All @@ -35,6 +38,7 @@ class UsersBloc extends HydratedBloc<UsersBlocEvent, UsersBlocState> {
limit: 30,
page: 0,
);

if (usersRes.$2 == null) {
final users = usersRes.$1!;

Expand All @@ -50,6 +54,61 @@ class UsersBloc extends HydratedBloc<UsersBlocEvent, UsersBlocState> {
}
}

// --- EITHER (dartz) ---
// Future<void> _onFetch(
// UsersBlocEventFetch event,
// Emitter<UsersBlocState> emit,
// ) async {
// final usersRes = await usersRepository.fetchUsers(
// limit: 30,
// page: 0,
// );

// usersRes.fold(
// (error) => emit(
// UsersBlocStateError(
// error.toString(),
// ),
// ),
// (users) {
// emit(
// UsersBlocStateLoaded(
// users: users,
// canLoadMore: users.length == 30,
// page: 1,
// ),
// );
// },
// );
// }

// --- SEALED CLASSES ---
// Future<void> _onFetch(
// UsersBlocEventFetch event,
// Emitter<UsersBlocState> emit,
// ) async {
// final usersRes = await usersRepository.fetchUsers(
// limit: 30,
// page: 0,
// );

// usersRes.fold(
// onErr: (failure) => emit(
// UsersBlocStateError(
// failure.toString(),
// ),
// ),
// onOk: (users) => emit(
// UsersBlocStateLoaded(
// users: users,
// canLoadMore: users.length == 30,
// page: 1,
// ),
// ),
// );
// }

// --- RECORDS ---
Future<void> _onFetchMore(
UsersBlocEventFetchMore event,
Emitter<UsersBlocState> emit,
Expand All @@ -70,6 +129,7 @@ class UsersBloc extends HydratedBloc<UsersBlocEvent, UsersBlocState> {
limit: 30,
page: page,
);

if (usersRes.$2 == null) {
final users = usersRes.$1!;

Expand All @@ -88,6 +148,97 @@ class UsersBloc extends HydratedBloc<UsersBlocEvent, UsersBlocState> {
}
}

// --- EITHER (dartz) ---
// Future<void> _onFetchMore(
// UsersBlocEventFetchMore event,
// Emitter<UsersBlocState> emit,
// ) async {
// if (state is! UsersBlocStateLoaded) {
// return;
// }

// final currState = state as UsersBlocStateLoaded;

// if (!currState.canLoadMore) {
// return;
// }

// final page = currState.page;

// final usersRes = await usersRepository.fetchUsers(
// limit: 30,
// page: page,
// );

// usersRes.fold(
// (error) => emit(
// UsersBlocStateError(
// error.toString(),
// ),
// ),
// (users) {
// emit(
// UsersBlocStateLoaded(
// users: [
// ...currState.users,
// ...users,
// ],
// canLoadMore: users.length == 30,
// page: page + 1,
// ),
// );
// },
// );
// }

// --- SEALED CLASSES ---
// Future<void> _onFetchMore(
// UsersBlocEventFetchMore event,
// Emitter<UsersBlocState> emit,
// ) async {
// if (state is! UsersBlocStateLoaded) {
// return;
// }

// final currState = state as UsersBlocStateLoaded;

// if (!currState.canLoadMore) {
// return;
// }

// final page = currState.page;

// final usersRes = await usersRepository.fetchUsers(
// limit: 30,
// page: page,
// );

// usersRes.fold(
// onOk: (users) {
// emit(
// UsersBlocStateLoaded(
// users: [
// ...currState.users,
// ...users,
// ],
// canLoadMore: users.length == 30,
// page: page + 1,
// ),
// );
// },
// onErr: (failure) {
// switch (failure) {
// case SomeFailure(:final error):
// emit(
// UsersBlocStateError(
// error,
// ),
// );
// }
// },
// );
// }

Future<void> _onRefresh(
UsersBlocEventRefresh event,
Emitter<UsersBlocState> emit,
Expand Down
20 changes: 20 additions & 0 deletions lib/features/users/repository/users_repository.dart
Original file line number Diff line number Diff line change
@@ -1,8 +1,28 @@
import 'package:bloc_example/core/network/failure.dart';
import 'package:bloc_example/core/network/result.dart';
import 'package:bloc_example/features/users/model/user.dart';
import 'package:dartz/dartz.dart';

// --- RECORDS ---
abstract class UsersRepository {
Future<(List<User>?, String?)> fetchUsers({
int limit,
int page,
});
}

// --- EITHER (dartz) ---
// abstract class UsersRepository {
// Future<Either<Failure, List<User>>> fetchUsers({
// int limit,
// int page,
// });
// }

// --- SEALED CLASSES ---
// abstract class UsersRepository {
// Future<Result<List<User>>> fetchUsers({
// int limit,
// int page,
// });
// }
80 changes: 80 additions & 0 deletions lib/features/users/repository/users_repository_impl.dart
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
import 'dart:io';

import 'package:bloc_example/core/network/failure.dart';
import 'package:bloc_example/core/network/result.dart';
import 'package:bloc_example/features/users/model/user.dart';
import 'package:bloc_example/features/users/repository/users_repository.dart';
import 'package:dartz/dartz.dart';
import 'package:dio/dio.dart';

// --- RECORDS ---
class UsersRepositoryImpl extends UsersRepository {
final Dio dio;

Expand Down Expand Up @@ -35,3 +39,79 @@ class UsersRepositoryImpl extends UsersRepository {
}
}
}

// --- EITHER (dartz) ---
// class UsersRepositoryImpl extends UsersRepository {
// final Dio dio;

// UsersRepositoryImpl(this.dio);

// @override
// Future<Either<Failure, List<User>>> fetchUsers({
// int limit = 30,
// int page = 0,
// }) async {
// try {
// final res = await dio.get('?page=$page&results=$limit');
// if (res.statusCode == HttpStatus.ok) {
// final rawUsers = res.data['results'] as List<dynamic>;
// final users = rawUsers.map((rawUser) => User.fromJson(rawUser)).toList();

// return Right(users);
// }

// return Left(
// SomeFailure(
// '''Network error:
// - status code: ${res.statusCode}
// - data: ${res.data}
// ''',
// ),
// );
// } catch (e) {
// return Left(
// SomeFailure(
// 'Network error: $e',
// ),
// );
// }
// }
// }

// --- SEALED CLASSES ---
// class UsersRepositoryImpl extends UsersRepository {
// final Dio dio;

// UsersRepositoryImpl(this.dio);

// @override
// Future<Result<List<User>>> fetchUsers({
// int limit = 30,
// int page = 0,
// }) async {
// try {
// final res = await dio.get('?page=$page&results=$limit');
// if (res.statusCode == HttpStatus.ok) {
// final rawUsers = res.data['results'] as List<dynamic>;
// final users = rawUsers.map((rawUser) => User.fromJson(rawUser)).toList();

// return Result.ok(users);
// }

// return Result.err(
// SomeFailure(
// '''Network error:
// - status code: ${res.statusCode}
// - data: ${res.data}
// ''',
// ),
// );
// } catch (e) {
// return Result.err(
// SomeFailure(
// 'Network error: $e',
// ),
// );
// }
// }
// }
8 changes: 8 additions & 0 deletions pubspec.lock
Original file line number Diff line number Diff line change
Expand Up @@ -209,6 +209,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "3.0.1"
dartz:
dependency: "direct main"
description:
name: dartz
sha256: e6acf34ad2e31b1eb00948692468c30ab48ac8250e0f0df661e29f12dd252168
url: "https://pub.dev"
source: hosted
version: "0.10.1"
diff_match_patch:
dependency: transitive
description:
Expand Down
1 change: 1 addition & 0 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ dependencies:
rxdart: 0.28.0

collection:
dartz:

dev_dependencies:
flutter_test:
Expand Down
Loading