bloc_ai 1.1.3
bloc_ai: ^1.1.3 copied to clipboard
BlocAI: a Flutter package for strict Bloc clean architecture.
example/lib/main.dart
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:bloc_ai/bloc_ai.dart';
void main() {
runApp(const CounterExampleApp());
}
class CounterExampleApp extends BaseApp<CounterBloc> {
const CounterExampleApp({super.key});
@override
BaseTheme get appTheme => const CounterTheme();
@override
String get title => 'BlocAI example';
@override
List<SingleChildWidget> get repositoryProviders =>
<SingleChildWidget>[
RepositoryProvider<CounterRepository>(
create: (_) => InMemoryCounterRepository(),
),
];
@override
CounterBloc createBloc(BuildContext context) {
final repository = RepositoryProvider.of<CounterRepository>(context);
return CounterBloc(repository);
}
@override
List<BasePage<CounterBloc>> buildPages(
BuildContext context,
BaseState state,
CounterBloc bloc,
) {
return <BasePage<CounterBloc>>[const CounterPage()];
}
}
final class CounterTheme extends BaseTheme {
const CounterTheme();
@override
ThemeData buildLightTheme() {
return ThemeData(
colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
);
}
@override
ThemeMode get themeMode => ThemeMode.light;
}
final class CounterPage extends BasePage<CounterBloc> {
const CounterPage({super.key});
@override
PreferredSizeWidget? buildAppBar(BuildContext context, CounterBloc bloc) {
return AppBar(title: const Text('BlocAI example'));
}
@override
Widget buildBody(BuildContext context, BaseState state, CounterBloc bloc) {
final count = switch (state) {
SuccessState<int> value => value.data,
_ => 0,
};
return Center(
child: Column(
mainAxisSize: MainAxisSize.min,
children: <Widget>[
Text('Count: $count'),
const SizedBox(height: 12),
FilledButton(
onPressed: bloc.onIncrementTapped,
child: const Text('Increment'),
),
],
),
);
}
}
final class CounterEntity implements BaseEntity {
const CounterEntity(this.value);
final int value;
@override
String get id => 'counter';
@override
List<Object?> get props => <Object?>[id, value];
}
abstract interface class CounterRepository extends BaseRepository<CounterEntity> {}
final class InMemoryCounterRepository implements CounterRepository {
int _value = 0;
@override
Future<Result<void>> delete(String id) async {
_value = 0;
return const Success<void>(null);
}
@override
Future<Result<List<CounterEntity>>> getAll() async {
return Success<List<CounterEntity>>(<CounterEntity>[CounterEntity(_value)]);
}
@override
Future<Result<CounterEntity>> getById(String id) async {
return Success<CounterEntity>(CounterEntity(_value));
}
@override
Future<Result<CounterEntity>> save(CounterEntity entity) async {
_value = entity.value;
return Success<CounterEntity>(entity);
}
}
final class CounterBloc extends BaseBloc {
CounterBloc(this._repository) : super(const SuccessState<int>(0));
final CounterRepository _repository;
Future<void> onIncrementTapped() async => guard(() async {
final current = switch (state) {
SuccessState<int> value => value.data,
_ => 0,
};
final result = await _repository.save(CounterEntity(current + 1));
result.when(
success: (entity) => emit(SuccessState<int>(entity.value)),
failure: (failure) => emit(ErrorState(message: failure.message)),
);
});
}