Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(bloc)!: v8.0.0 #2798

Merged
merged 46 commits into from
Nov 18, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
e1fdeaf
feat(bloc)!: v8.0.0
felangel Sep 26, 2021
eba96e8
refactor(bloc)!: remove deprecated listen on BlocBase
felangel Sep 29, 2021
9eaf08c
feat(bloc_test)!: v9.0.0-dev.1 (#2812)
felangel Sep 29, 2021
a4db062
fix(bloc_test): remove pedantic import
felangel Sep 29, 2021
b3a46c1
feat(hydrated_bloc)!: v8.0.0-dev.1 (#2828)
felangel Oct 6, 2021
c356a8a
feat(flutter_bloc)!: v8.0.0-dev.1 (#2829)
felangel Oct 6, 2021
91b5b66
feat(angular_bloc)!: v8.0.0-dev.1 (#2838)
felangel Oct 6, 2021
b3b313e
feat(replay_bloc)!: v0.2.0-dev.1 (#2852)
felangel Oct 9, 2021
e76ce7e
chore(bloc): upgrade to mocktail ^0.2.0
felangel Oct 9, 2021
1bb83a9
chore(angular_bloc): upgrade to mocktail ^0.2.0
felangel Oct 9, 2021
ebc1716
chore(bloc_concurrency): upgrade to mocktail ^0.2.0
felangel Oct 9, 2021
673bb1e
chore(hydrated_bloc): upgrade to mocktail ^0.2.0
felangel Oct 9, 2021
fd83a20
feat(bloc_test)!: upgrade to mocktail v0.2.0
felangel Oct 9, 2021
8d82dda
feat(bloc)!: restrict scope of emit in bloc and cubit (#2868)
felangel Oct 13, 2021
04abb52
chore(bloc): v8.0.0-dev.3 (#2869)
felangel Oct 13, 2021
447dd0d
feat(bloc_test)!: v9.0.0-dev.3 (#2870)
felangel Oct 13, 2021
bd0a46c
feat(flutter_bloc)!: v8.0.0-dev.2 (#2871)
felangel Oct 14, 2021
bb84839
feat(replay_bloc)!: v0.2.0-dev.2 (#2879)
felangel Oct 14, 2021
d53087f
chore(replay_bloc): remove unnecessary newline in library
felangel Oct 14, 2021
5952c95
feat(bloc_concurrency): v0.2.0-dev.1 (#2880)
felangel Oct 15, 2021
a548156
feat(hydrated_bloc)!: v8.0.0-dev.2 (#2881)
felangel Oct 15, 2021
c6f43ef
feat(angular_bloc)!: v8.0.0-dev.2 (#2882)
felangel Oct 15, 2021
638934e
refactor(bloc): add missing parameter names to inline functions (#2898)
felangel Oct 23, 2021
534efab
fix(angular_bloc): restrict test_api version due to chrome timeouts
felangel Oct 23, 2021
bd34d30
feat(bloc)!: improve error handling/reporting (#2899)
felangel Oct 26, 2021
490e9dc
revert(angular_bloc): test_api restriction
felangel Oct 26, 2021
c1d5115
chore(deps): upgrade dev dependencies (#2894)
LeonardoRosaa Oct 30, 2021
9b97253
chore(bloc): v8.0.0-dev.4 (#2909)
felangel Oct 30, 2021
a5917e5
chore(bloc_test): v9.0.0-dev.4 (#2910)
felangel Oct 30, 2021
92f1678
chore(hydrated_bloc): v8.0.0-dev.3 (#2911)
felangel Oct 30, 2021
afd235c
feat(bloc)!: add throws StateError when bloc is closed (#2912)
felangel Oct 30, 2021
eb09e0f
feat(bloc)!: emit throws StateError when bloc is closed (#2913)
felangel Oct 31, 2021
0062af1
refactor(bloc): remove unnecessary cascade from bloc_on_test.dart
felangel Nov 3, 2021
f54ace4
feat(bloc)!: BlocOverrides API (#2932)
felangel Nov 14, 2021
674bb64
chore(bloc): v8.0.0-dev.5 (#2940)
felangel Nov 14, 2021
1e64f8d
chore(angular_bloc): v8.0.0-dev.3 (#2941)
felangel Nov 14, 2021
e9a2003
chore(bloc_test): v9.0.0-dev.5 (#2942)
felangel Nov 14, 2021
3f667e6
chore(bloc_concurrency): v0.2.0-dev.2 (#2943)
felangel Nov 14, 2021
04f5725
chore(replay_bloc): v0.2.0-dev.3 (#2944)
felangel Nov 14, 2021
d26a24c
chore(flutter_bloc): v8.0.0-dev.3 (#2945)
felangel Nov 14, 2021
aee97eb
chore(hydrated_bloc): v8.0.0-dev.4 (#2946)
felangel Nov 14, 2021
6a9901e
feat(hydrated_bloc)!: HydratedBlocOverrides API (#2947)
felangel Nov 15, 2021
33b1f5c
chore(hydrated_bloc): v8.0.0-dev.5 (#2948)
felangel Nov 15, 2021
14b074a
docs: migration guide
felangel Nov 17, 2021
b32a046
Merge branch 'master' into feat/v8.0.0
felangel Nov 18, 2021
c1cf518
docs: add miquido sponsor
felangel Nov 18, 2021
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
2 changes: 1 addition & 1 deletion .github/workflows/hydrated_bloc.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ jobs:
run: flutter analyze lib test example

- name: Run tests
run: flutter test -j 1 --no-pub --coverage --test-randomize-ordering-seed random
run: flutter test --no-pub --coverage --test-randomize-ordering-seed random

- name: Check Code Coverage
uses: VeryGoodOpenSource/[email protected]
Expand Down
5 changes: 4 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,10 @@ Our top sponsors are shown below! [[Become a Sponsor](https://github.com/sponsor
</td>
<td align="center">
<a href="https://getstream.io/chat/flutter/tutorial/?utm_source=https://github.com/felangel/bloc&utm_medium=github&utm_content=developer&utm_term=flutter" target="_blank"><img width="250px" src="https://stream-blog.s3.amazonaws.com/blog/wp-content/uploads/fc148f0fc75d02841d017bb36e14e388/Stream-logo-with-background-.png"/></a><br/><span><a href="https://getstream.io/chat/flutter/tutorial/?utm_source=https://github.com/felangel/bloc&utm_medium=github&utm_content=developer&utm_term=flutter" target="_blank">Try the Flutter Chat Tutorial &nbsp💬</a></span>
</td>
</td>
<td align="center">
<a href="https://www.miquido.com/flutter-development-company/?utm_source=github&utm_medium=sponsorship&utm_campaign=bloc-silver-tier&utm_term=flutter-development-company&utm_content=miquido-logo"><img src="https://raw.githubusercontent.com/felangel/bloc/master/docs/assets/miquido_logo.png" width="225"/></a>
</td>
</tr>
</tbody>
</table>
Expand Down
25 changes: 12 additions & 13 deletions docs/_coverpage.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,16 @@
<a href="#/gettingstarted">Get Started</a>
</p>

<p align="center" style="margin-top: 2em; margin-bottom: 0"><b>Sponsored with 💖 by</b></p>
<p align="center" style="margin-top: 2em; margin-bottom: 1em"><b>Sponsored with 💖 by</b></p>

<table align="center">
<tbody>
<tr>
<td align="center" style="padding-right: 0.5em">
<a href="https://verygood.ventures"><img src="https://raw.githubusercontent.com/felangel/bloc/master/docs/assets/vgv_logo_transparent.png" width="80"/></a>
</td>
<td align="center" style="padding-left: 0.5em">
<a href="https://getstream.io/chat/flutter/tutorial/?utm_source=https://github.com/felangel/bloc&utm_medium=github&utm_content=developer&utm_term=flutter" target="_blank"><img width="120" src="https://stream-blog-v2.imgix.net/blog/wp-content/uploads/bae8c920a484d1c49dbd148306aa1335/stream-bloc-flutter.png?auto=compress&fit=clip&w=120"/></a><br/><span><a href="https://getstream.io/chat/flutter/tutorial/?utm_source=https://github.com/felangel/bloc&utm_medium=github&utm_content=developer&utm_term=flutter" target="_blank">Try the Flutter Chat Tutorial &nbsp💬</a></span>
</td>
</tr>
</tbody>
</table>
<div id="cover-sponsors-grid">
<div>
<a href="https://verygood.ventures"><img src="https://raw.githubusercontent.com/felangel/bloc/master/docs/assets/vgv_logo_transparent.png" width="65"/></a>
</div>
<div>
<a href="https://getstream.io/chat/flutter/tutorial/?utm_source=https://github.com/felangel/bloc&utm_medium=github&utm_content=developer&utm_term=flutter" target="_blank"><img width="120" src="https://stream-blog-v2.imgix.net/blog/wp-content/uploads/bae8c920a484d1c49dbd148306aa1335/stream-bloc-flutter.png?auto=compress&fit=clip&w=120"/></a><br/><span><a href="https://getstream.io/chat/flutter/tutorial/?utm_source=https://github.com/felangel/bloc&utm_medium=github&utm_content=developer&utm_term=flutter" target="_blank">Try the Flutter Chat Tutorial &nbsp💬</a></span>
</div>
<div>
<a href="https://www.miquido.com/flutter-development-company/?utm_source=github&utm_medium=sponsorship&utm_campaign=bloc-silver-tier&utm_term=flutter-development-company&utm_content=miquido-logo"><img src="https://raw.githubusercontent.com/felangel/bloc/master/docs/assets/miquido_logo_transparent.png" width="225"/></a>
</div>
</div>
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
```dart
void main() {
Bloc.observer = SimpleBlocObserver();
CounterCubit()
..increment()
..close();
BlocOverrides.runZoned(
() {
CounterCubit()
..increment()
..close();
},
blocObserver: SimpleBlocObserver(),
);
}
```
```
Original file line number Diff line number Diff line change
@@ -1,8 +1,12 @@
```dart
void main() {
Bloc.observer = SimpleBlocObserver();
CounterBloc()
..add(Increment())
..close();
BlocOverrides.runZoned(
() {
CounterBloc()
..add(Increment())
..close();
},
blocObserver: SimpleBlocObserver(),
);
}
```
```
12 changes: 12 additions & 0 deletions docs/assets/style.css
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,15 @@ section.cover blockquote > .buttons > a:hover {
#TOPBANNER p {
padding: 1.25rem 0;
}

#cover-sponsors-grid {
display: grid;
grid-auto-rows: 1fr;
grid-template-columns: 1fr 1fr 1fr;
gap: 0px 1em;
max-width: 600px;
justify-content: center;
align-items: center;
margin: 0 auto;
font-size: 0.8em;
}
237 changes: 237 additions & 0 deletions docs/migration.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,243 @@

?> 💡 **Tip**: Please refer to the [release log](https://github.com/felangel/bloc/releases) for more information regarding what changed in each release.

## v8.0.0

### package:bloc

#### ❗✨ Introduce new `BlocOverrides` API

!> In bloc v8.0.0, `Bloc.observer` and `Bloc.transformer` were removed in favor of the `BlocOverrides` API.

##### Rationale

The previous API used to override the default `BlocObserver` and `EventTransformer` relied on a global singleton for both the `BlocObserver` and `EventTransformer`.

As a result, it was not possible to:

- Have multiple `BlocObserver` or `EventTransformer` implementations scoped to different parts of the application
- Have `BlocObserver` or `EventTransformer` overrides be scoped to a package
- If a package were to depend on `package:bloc` and registered its own `BlocObserver`, any consumer of the package would either have to overwrite the package's `BlocObserver` or report to the package's `BlocObserver`.

It was also more difficult to test because of the shared global state across tests.

Bloc v8.0.0 introduces a `BlocOverrides` class which allows developers to override `BlocObserver` and/or `EventTransformer` for a specific `Zone` rather than relying on a global mutable singleton.

**v7.x.x**

```dart
void main() {
Bloc.observer = CustomBlocObserver();
Bloc.transformer = customEventTransformer();

// ...
}
```

**v8.0.0**

```dart
void main() {
BlocOverrides.runZoned(
() {
// ...
},
blocObserver: CustomBlocObserver(),
eventTransformer: customEventTransformer(),
);
}
```

`Bloc` instances will use the `BlocObserver` and/or `EventTransformer` for the current `Zone` via `BlocOverrides.current`. If there are no `BlocOverrides` for the zone, they will use the existing internal defaults (no change in behavior/functionality).

This allows allow each `Zone` to function independently with its own `BlocOverrides`.

```dart
BlocOverrides.runZoned(
() {
// BlocObserverA and eventTransformerA
final overrides = BlocOverrides.current;

// Blocs in this zone report to BlocObserverA
// and use eventTransformerA as the default transformer.
// ...

// Later...
BlocOverrides.runZoned(
() {
// BlocObserverB and eventTransformerB
final overrides = BlocOverrides.current;

// Blocs in this zone report to BlocObserverB
// and use eventTransformerB as the default transformer.
// ...
},
blocObserver: BlocObserverB(),
eventTransformer: eventTransformerB(),
);
},
blocObserver: BlocObserverA(),
eventTransformer: eventTransformerA(),
);
```

#### ❗✨ Improve Error Handling and Reporting

!> In bloc v8.0.0, `BlocUnhandledErrorException` is removed. In addition, any uncaught exceptions are always reported to `onError` and rethrown (regardless of debug or release mode). The `addError` API reports errors to `onError`, but does not treat reported errors as uncaught exceptions.

##### Rationale

The goal of these changes is:

- make internal unhandled exceptions extremely obvious while still preserving bloc functionality
- support `addError` without disrupting control flow

Previously, error handling and reporting varied depending on whether the application was running in debug or release mode. In addition, errors reported via `addError` were treated as uncaught exceptions in debug mode which led to a poor developer experience when using the `addError` API (specifically when writing unit tests).

In v8.0.0, `addError` can be safely used to report errors and `blocTest` can be used to verify that errors are reported. All errors are still reported to `onError`, however, only uncaught exceptions are rethrown (regardless of debug or release mode).

#### ❗🧹 Make `BlocObserver` abstract

!> In bloc v8.0.0, `BlocObserver` was converted into an `abstract` class which means an instance of `BlocObserver` cannot be instantiated.

##### Rationale

`BlocObserver` was intended to be an interface. Since the default API implementation are no-ops, `BlocObserver` is now an `abstract` class to clearly communicate that the class is meant to be extended and not directly instantiated.

**v7.x.x**

```dart
void main() {
// It was possible to create an instance of the base class.
final observer = BlocObserver();
}
```

**v8.0.0**

```dart
class MyBlocObserver extends BlocObserver {...}

void main() {
// Cannot instantiate the base class.
final observer = BlocObserver(); // ERROR

// Extend `BlocObserver` instead.
final observer = MyBlocObserver(); // OK
}
```

#### ❗✨ `add` throws `StateError` if Bloc is closed

!> In bloc v8.0.0, calling `add` on a closed bloc will result in a `StateError`.

##### Rationale

Previously, it was possible to call `add` on a closed bloc and the internal error would get swallowed, making it difficult to debug why the added event was not being processed. In order to make this scenario more visible, in v8.0.0, calling `add` on a closed bloc will throw a `StateError` which will be reported as an uncaught exception and propagated to `onError`.

#### ❗✨ `emit` throws `StateError` if Bloc is closed

!> In bloc v8.0.0, calling `emit` within a closed bloc will result in a `StateError`.

##### Rationale

Previously, it was possible to call `emit` within a closed bloc and no state change would occur but there would also be no indication of what went wrong, making it difficult to debug. In order to make this scenario more visible, in v8.0.0, calling `emit` within a closed bloc will throw a `StateError` which will be reported as an uncaught exception and propagated to `onError`.

#### ❗🧹 Remove Deprecated APIs

!> In bloc v8.0.0, all previously deprecated APIs were removed.

##### Summary

- `mapEventToState` removed in favor of `on<Event>`
- `transformEvents` removed in favor of `EventTransformer` API
- `TransitionFunction` typedef removed in favor of `EventTransformer` API
- `listen` removed in favor of `stream.listen`

### package:bloc_test

#### ✨ `MockBloc` and `MockCubit` no longer require `registerFallbackValue`

!> In bloc_test v9.0.0, developers no longer need to explicitly call `registerFallbackValue` when using `MockBloc` or `MockCubit`.

##### Summary

`registerFallbackValue` is only needed when using the `any()` matcher from `package:mocktail` for a custom type. Previously, `registerFallbackValue` was needed for every `Event` and `State` when using `MockBloc` or `MockCubit`.

**v8.x.x**

```dart
class FakeMyEvent extends Fake implements MyEvent {}
class FakeMyState extends Fake implements MyState {}
class MyMockBloc extends MockBloc<MyEvent, MyState> implements MyBloc {}

void main() {
setUpAll(() {
registerFallbackValue(FakeMyEvent());
registerFallbackValue(FakeMyState());
});

// Tests...
}
```

**v9.0.0**

```dart
class MyMockBloc extends MockBloc<MyEvent, MyState> implements MyBloc {}

void main() {
// Tests...
}
```

### package:hydrated_bloc

#### ❗✨ Introduce new `HydratedBlocOverrides` API

!> In hydrated_bloc v8.0.0, `HydratedBloc.storage` was removed in favor of the `HydratedBlocOverrides` API.

##### Rationale

Previously, a global singleton was used to override the `Storage` implementation.

As a result, it was not possible to have multiple `Storage` implementations scoped to different parts of the application. It was also more difficult to test because of the shared global state across tests.

`HydratedBloc` v8.0.0 introduces a `HydratedBlocOverrides` class which allows developers to override `Storage` for a specific `Zone` rather than relying on a global mutable singleton.

**v7.x.x**

```dart
void main() async {
HydratedBloc.storage = await HydratedStorage.build(
storageDirectory: await getApplicationSupportDirectory(),
);

// ...
}
```

**v8.0.0**

```dart
void main() {
final storage = await HydratedStorage.build(
storageDirectory: await getApplicationSupportDirectory(),
);

HydratedBlocOverrides.runZoned(
() {
// ...
},
storage: storage,
);
}
```

`HydratedBloc` instances will use the `Storage` for the current `Zone` via `HydratedBlocOverrides.current`.

This allows allow each `Zone` to function independently with its own `BlocOverrides`.

## v7.2.0

### package:bloc
Expand Down
6 changes: 4 additions & 2 deletions examples/angular_counter/web/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class SimpleBlocObserver extends BlocObserver {
}

void main() {
Bloc.observer = SimpleBlocObserver();
runApp(ng.AppComponentNgFactory);
BlocOverrides.runZoned(
() => runApp(ng.AppComponentNgFactory),
blocObserver: SimpleBlocObserver(),
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,6 @@ import 'package:mocktail/mocktail.dart';
class MockTickerBloc extends MockBloc<TickerEvent, TickerState>
implements TickerBloc {}

class FakeTickerEvent extends Fake implements TickerEvent {}

class FakeTickerState extends Fake implements TickerState {}

extension on WidgetTester {
Future<void> pumpTickerPage(TickerBloc tickerBloc) {
return pumpWidget(
Expand All @@ -28,11 +24,6 @@ extension on WidgetTester {
void main() {
late TickerBloc tickerBloc;

setUpAll(() {
registerFallbackValue(FakeTickerEvent());
registerFallbackValue(FakeTickerState());
});

setUp(() {
tickerBloc = MockTickerBloc();
});
Expand Down
8 changes: 5 additions & 3 deletions examples/flutter_complex_list/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import 'package:bloc/bloc.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_complex_list/app.dart';
import 'package:flutter_complex_list/repository.dart';
import 'package:flutter_complex_list/simple_bloc_observer.dart';

void main() {
Bloc.observer = SimpleBlocObserver();
runApp(App(repository: Repository()));
BlocOverrides.runZoned(
() => runApp(App(repository: Repository())),
blocObserver: SimpleBlocObserver(),
);
}
Loading