{"id":19639950,"url":"https://github.com/frideosapps/frideos_flutter","last_synced_at":"2025-09-05T03:44:07.276Z","repository":{"id":56830818,"uuid":"166552143","full_name":"frideosapps/frideos_flutter","owner":"frideosapps","description":"An all-in-one Fllutter package for state management, reactive objects, animations, effects, timed widgets etc.","archived":false,"fork":false,"pushed_at":"2023-11-22T09:51:32.000Z","size":987,"stargazers_count":189,"open_issues_count":6,"forks_count":22,"subscribers_count":12,"default_branch":"master","last_synced_at":"2025-05-20T06:04:55.162Z","etag":null,"topics":["bloc","bloc-pattern","dart","dart-library","dart2","flutter","flutter-apps","flutter-examples","flutter-library","flutter-package","flutter-widget","frideos","library","reactive-programming","rxdart","sharedpreferences","sharedpreferences-helper","state-management","streams","widgets-timing"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/frideos","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/frideosapps.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null}},"created_at":"2019-01-19T13:53:19.000Z","updated_at":"2025-02-15T20:44:48.000Z","dependencies_parsed_at":"2024-03-09T04:31:21.238Z","dependency_job_id":"f6f188d2-9597-4bd2-b288-5866f640e1f1","html_url":"https://github.com/frideosapps/frideos_flutter","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/frideosapps/frideos_flutter","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frideosapps%2Ffrideos_flutter","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frideosapps%2Ffrideos_flutter/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frideosapps%2Ffrideos_flutter/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frideosapps%2Ffrideos_flutter/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/frideosapps","download_url":"https://codeload.github.com/frideosapps/frideos_flutter/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/frideosapps%2Ffrideos_flutter/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268617373,"owners_count":24279230,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-08-03T02:00:12.545Z","response_time":2577,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["bloc","bloc-pattern","dart","dart-library","dart2","flutter","flutter-apps","flutter-examples","flutter-library","flutter-package","flutter-widget","frideos","library","reactive-programming","rxdart","sharedpreferences","sharedpreferences-helper","state-management","streams","widgets-timing"],"created_at":"2024-11-11T14:04:00.843Z","updated_at":"2025-08-03T21:34:21.325Z","avatar_url":"https://github.com/frideosapps.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Frideos [![pub package](https://img.shields.io/pub/v/frideos.svg)](https://pub.dartlang.org/packages/frideos)\n\nAn all-in-one package for state management, streams and BLoC pattern, animations and timed widgets, effects.\n\n## Contents\n\n### [1. State management](#state-management)\n**Getting started**\n- StreamedValue\n- AppStateModel\n- AppStateProvider\n- ValueBuilder\n- StreamedWidget\n\n  \n#### Specialized StreamedObjects\n- StreamedList\n- StreamedMap\n- HistoryObject\n- MemoryValue\n- StreamedTransformed\n\n##### Other\n- FuturedWidget\n- ReceiverWidget\n- StreamedSender, ListSender, and MapSender\n\n\n### [2. Animations and timing](#animations)\n- AnimationTween\n- AnimationCreate\n- AnimationCurved\n- CompositeItem\n- AnimationComposite\n- CompositeCreate\n- ScenesObject\n- ScenesCreate\n- StagedObject\n- StagedWidget\n- WavesWidget\n- ScrollingText\n\n### [3. Effects](#effects)\n- LinearTransition\n- CurvedTransition\n- FadeInWidget\n- FadeOutWidget\n- BlurWidget\n- BlurInWidget\n- BlurOutWidget\n- AnimatedBlurWidget\n\n\n## Articles and examples\n\n- [A book trailer with Flutter web](https://itnext.io/me-flutter-web-and-the-making-of-an-experimental-book-trailer-8f1625173759)\n\n- [Quiz game](https://github.com/frideosapps/trivia_example): a simple trivia game built with Flutter and this package. You can read an article about this example here: https://medium.com/flutter-community/flutter-how-to-build-a-quiz-game-596d0f369575\n\n- [Todo App](https://github.com/brianegan/flutter_architecture_samples/tree/master/frideos_library): an implementation of the Todo App of the [Flutter Architecture Samples](https://github.com/brianegan/flutter_architecture_samples) repository using this package.\n\n- [Frideos examples](https://github.com/frideosapps/frideos_examples): an example app to show how to use some features of this library. \n  - Streamed objects\n  - Streamed collections\n  - TimerObject: a simple stopwatch\n  - StagedObject\n  - StagedWidget\n  - AnimatedObject\n  - Multiple selection and tunnel pattern (to share data between two blocs)\n  - LinearTransition\n  - CurvedTransition\n  - Blur (fixed, in, out, animated)\n  - WavesWidget\n  - Sliders\n  - Products catalog\n  \n- [Dynamic fields validation](https://github.com/frideosapps/dynamic_fields_validation): a Flutter example on how to validate dynamically created fields with the BLoC pattern and this package.\n\n- [Theme changer](https://github.com/frideosapps/theme_changer): a simple starter app with a drawer, app state management, dynamic theme changer and persistent theme using the sharedpreferences.\n\n- [Counter](https://github.com/frideosapps/counter): a simple app using the BLoC pattern showing a counter implemented with this library.\n\n- [Blood pressure](https://github.com/frideosapps/bloodpressure): an example of a medical app built with Flutter for the classification of the arterial blood pressure.\n\n- [Pair game](https://github.com/frideosapps/pair_game): a simple pair game (multiple selections, animations, tunnel pattern).\n  \n## Dependencies\n\n- [RxDart](https://pub.dartlang.org/packages/rxdart)\n\n   \n    \n# State management\n\n### Getting started\n\nThe core of the package consists of classes that implement the StramedObject interface:\n\n```dart\n///\n/// Interface for all the StreamedObjects\n///\nabstract class StreamedObject\u003cT\u003e {\n  /// Getter for the stream exposed by the classes that implement\n  /// the StreamedObject interface.\n  Stream\u003cT\u003e get outStream;\n\n  /// Getter for the last value emitted by the stream\n  T get value;\n}\n```\n\n- HistoryObject\n- MemoryValue\n- StreamedList\n- StreamedMap\n- StreamedTransformed\n- StreamedValue\n\nThese objects are then used (e.g. in classes extending the AppStateModel interface) in combination with the **ValueBuilder** widget (or StreamedWidget/StreamBuilder), to make the UI reactive to their changes.\n\n### StreamedValue\n\nThe **StreamedValue** is the simplest class that implements this interface.\nEvery time a new value is set, this is compared to the latest one and if it is different, it is sent to stream. Used in tandem with `ValueBuilder` (or StreamedWidget/StreamBuilder) it automatically triggers the rebuild of the widgets returned by its builder.\n\nSo for example, instead of:\n\n```dart\ncounter += 1;\nstream.sink.add(counter);\n```\n\nIt becomes just:\n\n```dart\ncounter.value += 1;\n```\n\nIt can be used even with `StreamedWidget` and `StreamBuilder` by using its stream getter `outStream`.\n\nN.B. when the type is not a basic type (e.g int, double, String etc.) and the value of a property of the object is changed, it is necessary to call the `refresh` method to update the stream.\n\n#### Example\n\n```dart\n// In the BLoC\nfinal count = StreamedValue\u003cint\u003e(initialData: 0);\n\nincrementCounter() {\n  count.value += 2.0;\n}\n\n// View\nValueBuilder\u003cint\u003e(\n  streamed: bloc.count, // no need of the outStream getter with ValueBuilder\n  builder: (context, snapshot) =\u003e\n    Text('Value: ${snapshot.data}'),\n  noDataChild: Text('NO DATA'),\n),\nRaisedButton(\n    color: buttonColor,\n    child: Text('+'),\n    onPressed: () {\n      bloc.incrementCounter();\n    },\n),\n\n// As an alternative:\n//\n// StreamedWidget\u003cint\u003e(    \n//    stream: bloc.count.outStream,\n//    builder: (context, snapshot) =\u003e Text('Value: ${snapshot.data}'),\n//    noDataChild: Text('NO DATA'),\n//),\n```\n\nIf on debugMode, on each update the `timesUpdated` increases showing how many times the value has been updated.\n\nN.B. For collections use `StreamedList` and `StreamedMap` instead.\n\n\n### AppStateModel and AppStateProvider\n\nThese reactive objects can be used in classes extending the AppStateModel interface, and provided to the widgets tree using the AppStateProvider widget.\n\nFrom the \"theme changer\" example:\n\n#### 1. Create a model for the app state:\n\n```dart\nclass AppState extends AppStateModel {\n  List\u003cMyTheme\u003e themes;\n  StreamedValue\u003cMyTheme\u003e currentTheme;\n\n  AppState() {\n    print('-------APP STATE INIT--------');\n\n    themes = List\u003cMyTheme\u003e();\n\n    themes.addAll([\n      MyTheme(\n        name: 'Default',\n        brightness: Brightness.light,\n        backgroundColor: Colors.blue[50],\n        scaffoldBackgroundColor: Colors.blue[50],\n        primaryColor: Colors.blue,\n        primaryColorBrightness: Brightness.dark,\n        accentColor: Colors.blue[300],\n      ),\n      MyTheme(\n        name: 'Teal',\n        brightness: Brightness.light,\n        backgroundColor: Colors.teal[50],\n        scaffoldBackgroundColor: Colors.teal[50],\n        primaryColor: Colors.teal[600],\n        primaryColorBrightness: Brightness.dark,\n        accentColor: Colors.teal[300],\n      ),\n      MyTheme(\n        name: 'Orange',\n        brightness: Brightness.light,\n        backgroundColor: Colors.orange[50],\n        scaffoldBackgroundColor: Colors.orange[50],\n        primaryColor: Colors.orange[600],\n        primaryColorBrightness: Brightness.dark,\n        accentColor: Colors.orange[300],\n      ),\n    ]);\n\n    currentTheme = StreamedValue();\n  }\n\n  void setTheme(MyTheme theme) =\u003e currentTheme.value = theme;    \n  \n\n  @override\n  void init() =\u003e currentTheme.value = themes[0];    \n \n\n  @override\n  dispose() {\n    print('---------APP STATE DISPOSE-----------');\n    currentTheme.dispose();\n  }\n}\n```\n\n#### 2. Wrap the MaterialApp in the AppStateProvider:\n\n```dart\nvoid main() =\u003e runApp(App());\n\nclass App extends StatefulWidget {\n  @override\n  _AppState createState() =\u003e _AppState();\n}\n\nclass _AppState extends State\u003cApp\u003e {\n  AppState appState;\n\n  @override\n  void initState() {\n    super.initState();\n    appState = AppState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return AppStateProvider\u003cAppState\u003e(\n      appState: appState,\n      child: MaterialPage(),\n    );\n  }\n}\n```\n\n#### 3. Consume the data:\n\n```dart\nclass MaterialPage extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    var theme = AppStateProvider.of\u003cAppState\u003e(context).currentTheme;\n\n    return ValueBuilder\u003cMyTheme\u003e(\n        streamed: theme,\n        builder: (context, snapshot) {\n          return MaterialApp(\n              title: \"Theme and drawer starter app\",\n              theme: _buildThemeData(snapshot.data),\n              home: HomePage(),\n            );\n        },\n    );\n  }\n\n  _buildThemeData(MyTheme appTheme) {\n    return ThemeData(\n      brightness: appTheme.brightness,\n      backgroundColor: appTheme.backgroundColor,\n      scaffoldBackgroundColor: appTheme.scaffoldBackgroundColor,\n      primaryColor: appTheme.primaryColor,\n      primaryColorBrightness: appTheme.primaryColorBrightness,\n      accentColor: appTheme.accentColor,\n    );\n  }\n}\n```\n\n#### 4. Change the data (using a stream):\n\n```dart\nclass SettingsPage extends StatelessWidget {\n  @override\n  Widget build(BuildContext context) {\n    var appState = AppStateProvider.of\u003cAppState\u003e(context);\n\n    _buildThemesList() {\n      return appState.themes.map((MyTheme appTheme) {\n        return DropdownMenuItem\u003cMyTheme\u003e(\n          value: appTheme,\n          child: Text(appTheme.name, style: TextStyle(fontSize: 14.0)),\n        );\n      }).toList();\n    }\n\n    return Scaffold(\n      appBar: AppBar(\n        centerTitle: true,\n        title: Text(\n          \"Settings\",\n        ),\n      ),\n      body: Container(\n        padding: EdgeInsets.all(8.0),\n        child: Column(\n          children: \u003cWidget\u003e[\n            Column(\n              mainAxisAlignment: MainAxisAlignment.start,\n              children: \u003cWidget\u003e[\n                Padding(\n                  padding: const EdgeInsets.all(8.0),\n                  child: Text(\n                    'Choose a theme:',\n                    style: TextStyle(fontWeight: FontWeight.w500),\n                  ),\n                ),\n                ValueBuilder\u003cMyTheme\u003e(\n                  streamed: appState.currentTheme,\n                  builder: (context, snapshot) {\n                    return DropdownButton\u003cMyTheme\u003e(\n                      hint: Text(\"Status\"),\n                      value: snapshot.data,\n                      items: _buildThemesList(),\n                      onChanged: appState.setTheme,\n                    );\n                  },\n                ),\n              ],\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n}\n```\n\n### ValueBuilder\n\nValueBuilder extends the [StreamBuilder] widget providing some callbacks to handle the state of the stream and returning a [Container] if `noDataChild` is not provided, in order to avoid checking `snapshot.hasData`.\n\nN.B. To use when there is no need to receive a _null value_.\n\nIt takes as a `streamed` parameter an object implementing the [StreamedObject] interface and triggers the rebuild of the widget whenever the stream emits a new event.\n\n#### Usage\n\n```dart\nValueBuilder\u003cString\u003e(\n  streamed: streamedValue,\n  builder: (context, snasphot) =\u003e Text(snasphot.data),\n  initialData: // Data to provide for the initial snapshot\n  noDataChild: // Widget to show when the stream has no data\n  onNoData: () =\u003e // or Callback\n  errorChild: // Widget to show on error\n  onError: (error) =\u003e // or Callback\n)\n```\n\nIf no [noDataChild] widget or [onNoData] callback is provided then a [Container] is returned.\n\nIf no [errorChild] widget or no [onError] callback is provided then a [Container] is returned.\n\nN.B. The callbacks are executed only if their respective child is not provided.\n\n### StreamedWidget\n\nStreamedWidget extends the [StreamBuilder] widget providing\nsome callbacks to handle the state of the stream and returning a\n[Container] if `noDataChild` is not provided, in order to avoid\nchecking `snapshot.hasData`.\n\nN.B. To use when there is no need to receive a _null value_.\n\nIt takes as a `stream` parameter a [Stream] and triggers the rebuild of the widget whenever the stream emits a new event.\n\nIf no [noDataChild] widget or [onNoData] callback is provided then a [Container] is returned.\n\nIf no [errorChild] widget or no [onError] callback is provided then a [Container] is returned.\n\n#### Usage\n\n```dart\nStreamedWidget\u003cString\u003e(\n  stream: stream,\n  builder: (context, snasphot) =\u003e Text(snasphot.data),\n  noDataChild: // Widget to show when the stream has no data\n  onNoData: () =\u003e // or Callback\n  errorChild: // Widget to show on error\n  onError: (error) =\u003e // or Callback\n)\n```\n\nIn case of an object implementing the StreamedObject interface (eg. StreamedValue, StreameList etc.):\n\n```dart\nStreamedWidget\u003cString\u003e(\n  stream: streamedObject.outStream, // outStream getter\n  builder: (context, snasphot) =\u003e Text(snasphot.data),\n  noDataChild: // Widget to show when the stream has no data\n  onNoData: () =\u003e // or Callback\n  errorChild: // Widget to show on error\n  onError: (error) =\u003e // or Callback\n)\n```\n\nN.B. The callbacks are executed only if their respective child is not provided.\n\n\n## Specialized StreamedObjects\n\n### StreamedList\n\nThis class has been created to work with lists. It works like `StreamedValue`.\n\nTo modify the list (e.g. adding items) and update the stream automatically\nuse these methods:\n\n- `AddAll`\n- `addElement`\n- `clear`\n- `removeAt`\n- `removeElement`\n- `replace`\n- `replaceAt`\n\nFor other direct actions on the list, to update the stream call\nthe `refresh` method instead.\n\n#### Usage\n\ne.g. adding an item:\n\n```dart\n streamedList.addElement(item);\n```\n\nit is the same as:\n\n```dart\n  streamedList.value.add(item);\n  streamedList.refresh();\n```\n\nFrom the StreamedList example:\n\n```dart\n  final streamedList = StreamedList\u003cString\u003e();\n\n\n  // Add to the streamed list the string from the textfield\n  addText() {\n    streamedList.addElement(streamedText.value);\n\n    // Or, as an alternative:\n    // streamedList.value.add(streamedText.value);\n    // streamedList.refresh(); // To refresh the stream with the new value\n  }\n```\n\n### StreamedMap\n\nThis class has been created to work with maps, it works like `StreamedList`.\n\nTo modify the list (e.g. adding items) and update the stream automatically\nuse these methods:\n\n- `addKey`\n- `removeKey`\n- `clear`\n\nFor other direct actions on the map, to update the stream call\nthe `refresh` method instead.\n\n#### Usage\n\ne.g. adding a key/value pair:\n\n```dart\n  streamedMap.addKey(1, 'first');\n```\n\nit is the same as:\n\n```dart\n   streamedMap.value[1] = 'first';\n   streamedList.refresh();\n```\n\nFrom the streamed map example:\n\n```dart\n  final streamedMap = StreamedMap\u003cint, String\u003e();\n\n\n  // Add to the streamed map the key/value pair put by the user\n  addText() {\n    var key = int.parse(streamedKey.value);\n    var value = streamedText.value;\n\n    streamedMap.addKey(key, value);\n\n    // Or, as an alternative:\n    //streamedMap.value[key] = value;\n    //streamedMap.refresh();\n  }\n```\n\n### MemoryValue\n\nThe `MemoryValue` has a property to preserve the previous value. The setter checks for the new value, if it is different from the one already stored, this one is given `oldValue` before storing and streaming the new one.\n\n#### Usage\n\n```dart\nfinal countMemory = MemoryValue\u003cint\u003e();\n\ncountMemory.value // current value\ncouneMemory.oldValue // previous value\n```\n\n### HistoryObject\n\nExtends the `MemoryValue` class, adding a `StreamedList`. Useful when it is need to store a value in a list.\n\n```dart\nfinal countHistory = HistoryObject\u003cint\u003e();\n\nincrementCounterHistory() {\n  countHistory.value++;\n}\n\nsaveToHistory() {\n  countHistory.saveValue();\n}\n```\n\n### StreamedTransformed\n\nA particular class the implement the `StreamedObject` interface, to use when there is the need of a `StreamTransformer` (e.g. stream transformation, validation of input\nfields, etc.).\n\n#### Usage\n\nFrom the StreamedMap example:\n\n```dart\n// In the BLoC class\nfinal streamedKey = StreamedTransformed\u003cString, int\u003e();\n\n\n\n// In the constructor of the BLoC class\nstreamedKey.setTransformer(validateKey);\n\n\n\n// Validation (e.g. in the BLoC or in a mixin class)\nfinal validateKey =\n      StreamTransformer\u003cString, int\u003e.fromHandlers(handleData: (key, sink) {\n    var k = int.tryParse(key);\n    if (k != null) {\n      sink.add(k);\n    } else {\n      sink.addError('The key must be an integer.');\n    }\n  });\n\n\n// In the view:\nStreamBuilder\u003cint\u003e(\n            stream: bloc.streamedKey.outTransformed,\n            builder: (context, snapshot) {\n              return Column(\n                children: \u003cWidget\u003e[\n                  Padding(\n                    padding: const EdgeInsets.symmetric(\n                      vertical: 12.0,\n                      horizontal: 20.0,\n                    ),\n                    child: TextField(\n                      style: TextStyle(\n                        fontSize: 18.0,\n                        color: Colors.black,\n                      ),\n                      decoration: InputDecoration(\n                        labelText: 'Key:',\n                        hintText: 'Insert an integer...',\n                        errorText: snapshot.error,\n                      ),\n                      // To avoid the user could insert text use the TextInputType.number\n                      // Here is commented to show the error msg.\n                      //keyboardType: TextInputType.number,\n                      onChanged: bloc.streamedKey.inStream,\n                    ),\n                  ),\n                ],\n              );\n            }),\n```\n\n\n## Other\n\n### FuturedWidget\n\nFuturedWidget is a wrapper for the [FutureBuilder] widget. It provides some callbacks to handle the state of the future and returning a [Container] if `onWaitingChild` is not provided, in order to avoid checking `snapshot.hasData`.\n\n#### Usage\n\n```dart\nFuturedWidget\u003cString\u003e(\n  future: future,\n  builder: (context, snasphot) =\u003e Text(snasphot.data),\n  initialData: // Data to provide if the snapshot is null or still not completed\n  waitingChild: // Widget to show on waiting\n  onWaiting: () =\u003e // or Callback\n  errorChild: // Widget to show on error\n  onError: (error) =\u003e // or Callback\n)\n```\n\nIf no [onWaitingChild] widget or [onWaiting] callback is provided then a [Container] is returned.\n\nIf no [errorChild] widget or no [onError] callback is provided then a [Container] is returned.\n\nN.B. The callbacks are executed only if their respective child is not provided.\n\n\n\n### ReceiverWidget\n\nUsed with a StreamedValue when the type is a widget to directly stream a widget to the view. Under the hood a StreamedWidget handles the stream and shows the widget.\n\n#### Usage\n\n```dart\nReceiverWidget(stream: streamedValue.outStream),\n```\n\n### StreamedSender\n\nUsed to make a one-way tunnel beetween two blocs (from blocA to a StremedValue on blocB).\n\n#### Usage\n\n1. #### Define an object that implements the `StreamedObject` interface in the blocB (e.g. a `StreamedValue`):\n\n```dart\nfinal receiverStr = StreamedValue\u003cString\u003e();\n```\n\n2. #### Define a `StreamedSender` in the blocA:\n\n```dart\nfinal tunnelSenderStr = StreamedSender\u003cString\u003e();\n```\n\n3. #### Set the receiver in the sender on the class the holds the instances of the blocs:\n\n```dart\nblocA.tunnelSenderStr.setReceiver(blocB.receiverStr);\n```\n\n4. #### To send data from blocA to blocB then:\n\n```dart\ntunnelSenderStr.send(\"Text from blocA to blocB\");\n```\n\n### ListSender and MapSender\n\nLike the StreamedSender, but used with collections.\n\n#### Usage\n\n1. #### Define a `StreamedList` or `StreamedMap` object in the blocB\n\n```dart\nfinal receiverList = StreamedList\u003cint\u003e();\nfinal receiverMap = StreamedMap\u003cint, String\u003e();\n```\n\n2. #### Define a `ListSender`/`MapSender` in the blocA\n\n```dart\nfinal tunnelList = ListSender\u003cint\u003e();\nfinal tunnelMap = MapSender\u003cint, String\u003e();\n```\n\n3. #### Set the receiver in the sender on the class the holds the instances of the blocs\n\n```dart\nblocA.tunnelList.setReceiver(blocB.receiverList);\nblocA.tunnelMap.setReceiver(blocB.receiverMap);\n```\n\n4. #### To send data from blocA to blocB then:\n\n```dart\ntunnelList.send(list);\ntunnelMap.send(map);\n```\n\n\n# Animations\n\n### AnimationTween\n\n```dart\nanim = AnimationTween\u003cdouble\u003e(\n        duration: Duration(milliseconds: 120000),\n        setState: setState,\n        tickerProvider: this,\n        begin: 360.0,\n        end: 1.0,\n        onAnimating: _onAnimating,\n);\n\nopacityAnim = AnimationTween\u003cdouble\u003e(\n  begin: 0.5,\n  end: 1.0,\n  controller: anim.baseController,\n);\n\ngrowAnim = AnimationTween\u003cdouble\u003e(\n  begin: 1.0,\n  end: 30.0,\n  controller: anim.baseController,\n);\n\n// Play animation\nanim.forward();\n\n\n// Called on each frame\nvoid _onAnimating(AnimationStatus status) {   \n  if (status == AnimationStatus.completed) {\n    anim.reverse();\n  }\n  if (status == AnimationStatus.dismissed) {\n    anim.forward();\n  }\n}\n\n\n// Example\nOpacity(\n  opacity: opacityAnim.value,\n  child: Container(\n    alignment: Alignment.center,\n    height: 100 + growAnim.value,\n    width: 100 + growAnim.value,\n    decoration: BoxDecoration(\n      color: Colors.blue,\n        boxShadow: [\n          BoxShadow(blurRadius: anim.value),\n        ],        \n  ),\n),\n```\n\n### AnimationCreate\n\n```dart\n AnimationCreate\u003cdouble\u003e(\n        begin: 0.1,\n        end: 1.0,\n        curve: Curves.easeIn,\n        duration: 1000,\n        repeat: true,\n        reverse: true,\n        builder: (context, anim) {          \n          return Opacity(\n                opacity: anim.value,\n                child: Text(\n                  'Loading...',\n                  style: TextStyle(\n                    color: Colors.white,\n                    fontSize: 26.0,\n                  ),\n                ),\n              );\n```\n\n\n### AnimationCurved\n\n```dart\n circleAnim = AnimationCurved\u003cdouble\u003e(\n        duration: Duration(milliseconds: 7000),\n        setState: setState,\n        tickerProvider: this,\n        begin: 360.0,\n        end: 1.0,\n        curve: Curves.bounceInOut,\n        onAnimating: _onAnimating,\n);\n\ncircleAnim.forward();\n```\n\n### CompositeItem and AnimationComposite\n\n```dart\n    compAnim = AnimationComposite(\n        duration: Duration(milliseconds: 1750),\n        setState: setState,\n        tickerProvider: this,\n        composite: {\n          'background': CompositeItem\u003cColor\u003e(\n              begin: Colors.amber, end: Colors.blue, curve: Curves.elasticIn),\n          'grow': CompositeItem\u003cdouble\u003e(begin: 1.0, end: 40.0),\n          'rotate': CompositeItem\u003cdouble\u003e(\n              begin: math.pi / 4, end: math.pi, curve: Curves.easeIn),\n          'color': CompositeItem\u003cColor\u003e(\n              begin: Colors.green, end: Colors.orange, curve: Curves.elasticIn),\n          'shadow': CompositeItem\u003cdouble\u003e(begin: 5.0, end: 30.0),\n          'rounded': CompositeItem\u003cdouble\u003e(\n            begin: 0.0,\n            end: 150.0,\n            curve: Curves.easeIn,\n          )\n        });\n\n    movAnim = AnimationComposite(\n        duration: Duration(milliseconds: 1750),\n        setState: setState,\n        tickerProvider: this,\n        composite: {\n          'upper': CompositeItem\u003cOffset\u003e(\n              begin: Offset(-60.0, -30.0),\n              end: Offset(80.0, 15.0),\n              curve: Curves.easeIn),\n          'lower': CompositeItem\u003cOffset\u003e(\n              begin: Offset(-80.0, 0.0),\n              end: Offset(70.0, -25.0),\n              curve: Curves.easeInCirc),\n        });\n\n\n\n// Example\nTransform.translate(\n  offset: movAnim.value('lower'),\n  child: Transform.rotate(\n    angle: compAnim.value('rotate'),\n    child: Container(\n      alignment: Alignment.center,\n      height: 100 + compAnim.value('grow'),\n      width: 100 + compAnim.value('grow'),\n      decoration: BoxDecoration(\n        color: compAnim.value('color'),\n        boxShadow: [\n          BoxShadow(blurRadius: compAnim.value('shadow')),\n          ],\n        borderRadius: BorderRadius.circular(\n          compAnim.value('rounded'),\n          ),\n       ),\n    ),\n  ),\n),\n```\n\n### CompositeCreate\n\n```dart\n\nenum AnimationType {\n  fadeIn,  \n  scale,  \n  fadeOut,  \n}\n\n\n @override\n  Widget build(BuildContext context) {\n    return CompositeCreate(\n      duration: duration,\n      repeat: false,\n      compositeMap: {\n        AnimationType.fadeIn: CompositeItem\u003cdouble\u003e(\n          begin: 0.2,\n          end: 1.0,\n          curve: const Interval(\n            0.0,\n            0.2,\n            curve: Curves.linear,\n          ),\n        ),\n        AnimationType.scale: CompositeItem\u003cdouble\u003e(\n          begin: reverse ? 0.8 : 1.0,\n          end: reverse ? 1.0 : 0.8,\n          curve: const Interval(\n            0.2,\n            0.6,\n            curve: Curves.linear,\n          ),\n        ),\n        AnimationType.fadeOut: CompositeItem\u003cdouble\u003e(\n          begin: 1.0,\n          end: 0.0,\n          curve: Interval(\n            0.7,\n            0.8,\n            curve: Curves.linear,\n          ),\n        ),\n      },\n      onCompleted: onCompleted,\n      builder: (context, comp) {\n        return Transform.scale(\n          scale: comp.value(AnimationType.scale),\n          child: Opacity(\n                  opacity: comp.value(AnimationType.fadeIn),\n                  child: Opacity(\n                    opacity: comp.value(AnimationType.fadeOut),\n                    child: Text(\n                      'Text',\n```\n\n\n\n\n\n\n### ScenesObject\nA complex class to hadle the rendering of scenes over the time.\nIt takes a collection of \"Scenes\" and triggers the visualization of\nthe widgets at a given time (relative o absolute timing).\nFor example to make a demostration on how to use an application,\nshowing the widgets and pages along with explanations.\n\nEvery scene is handled by using the Scene class:\n\n```dart\n class Scene {\n   Widget widget;\n   int time; // milliseconds\n   Function onShow = () {};\n   Scene({this.widget, this.time, this.onShow});\n }\n ```\n\n ##### N.B. The onShow callback is used to trigger an action when the scene shows\n\n #### Usage\n From the ScenesObject example:\n\n #### 1 - Declare a list of scenes\n\n ```dart\n final ScenesObject scenesObject = ScenesObject();\n ```\n \n #### 2 - Add some scenes\n \n ```dart\n scenes.addAll([\n   Scene(\n     time: 4000,\n     widget: SingleScene(text: 'Scene 1', color: Colors.blueGrey),\n     onShow: () =\u003e print('Showing scene 1'),\n   ),\n   Scene(\n     time: 4000,\n     widget: SingleScene(text: 'Scene 2', color: Colors.orange),\n     onShow: () =\u003e print('Showing scene 1'),\n   )\n ]);\n \n \n // The singleScene widget:\n \n class SingleScene extends StatelessWidget {\n   const SingleScene({Key key, this.text, this.color}) : super(key: key);\n \n   final String text;\n   final Color color;\n \n   @override\n   Widget build(BuildContext context) {\n     return Container(\n       alignment: Alignment.center,\n       color: color,\n       child: Text(text),\n     );\n   }\n }\n ```\n #### 3 - Setup the ScenesObject and play the scenes\n\n ```dart\n scenesObject\n   ..setScenesList(scenes)\n   ..setCallback(() =\u003e print('Called on start'))\n   ..setOnEndCallback(scenesObject.startScenes); // Replay the scenes at the end\n \n // For e.g. on tap on a button:\n scenesObject.startScenes();\n ```\n\n### ScenesCreate\n\n This widget uses a [ScenesObject] for the timing of the widgets\n visualization.\n\n It takes as a parameter a List\u003cScene\u003e and plays every [Scene].\n\n By default to change the stage is used the relative time, so the time\n parameter of the [Scene] indicates how much time the stage will lasts.\n Instead, to specify the absolute time, set to true the [absoluteTiming]\n flag, in this case the time parameter indicates the absolute time when\n to show the scene.\n\n The [onStart] is used to call a function when the ScenesObject begins\n to play the stages.\n\n The [onEnd] callback is called at the end of the last stage when the timeing\n is relative (the [absoluteTiming] flag is set to false).\n\n #### Usage\n From the ScenesObject example:\n \n ```dart\nScenesCreate(\n  scenes: [\n    Scene(\n        widget: SingleScene(\n          color: Colors.white,\n          text: 'Scene 1',\n        ),\n        time: 3500,\n        onShow: () {\n          print('Showing scene 1');\n        }),\n    Scene(\n        widget: SingleScene(\n          color: Colors.blue,\n          text: 'Scene 2',\n        ),\n        time: 3500,\n        onShow: () {\n          print('Showing scene 2');\n        }),\n    Scene(\n        widget: SingleScene(\n          color: Colors.brown,\n          text: 'Scene 3',\n        ),\n        time: 3500,\n        onShow: () {\n          print('Showing scene 3');\n        }),\n  ],\n  onStart: () =\u003e print('Start playing scenes!'),\n  onEnd: () =\u003e print('End playing scenes!'),\n),\n\n\n// The singleScene widget:\n\nclass SingleScene extends StatelessWidget {\n  const SingleScene({Key key, this.text, this.color}) : super(key: key);\n\n  final String text;\n  final Color color;\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(\n      alignment: Alignment.center,\n      color: color,\n      child: Text(text),\n    );\n  }\n}\n```\n\n\n### StagedObject\n\nA complex class to hadle the rendering of widgets over the time. It takes a collection of \"Stages\" and triggers the visualization of the widgets at a given time (relative o absolute timing). For example to make a demostration on how to use an application, showing the widgets and pages along with explanations.\n\n![StagedObject](https://i.imgur.com/9XLb7JD.gif)\n\nEvery stage is handled by using the Stage class:\n\n```dart\nclass Stage {\n  Widget widget;\n  int time; // milliseconds\n  Function onShow = () {};\n  Stage({this.widget, this.time, this.onShow});\n}\n```\n\n##### N.B. The onShow callback is used to trigger an action when the stage shows\n\n#### Usage\n\nFrom the StagedObject example:\n\n1. #### Declare a map \u003cint, Stage\u003e\n   Here the map is in the view and is set in the BLoC class by the setStagesMap.\n\n```dart\nMap\u003cint, Stage\u003e get stagesMap =\u003e \u003cint, Stage\u003e{\n  0: Stage(\n      widget: Container(\n        width: 200.0,\n        height: 200.0,\n        color: Colors.indigo[200],\n        alignment: Alignment.center,\n        key: Key('0'),\n        child: ScrollingText(\n          text:\n            'This stage will last 8 seconds. By the onShow call back it is possibile to assign an action when the widget shows.',\n          scrollingDuration: 2000,\n          style: TextStyle(\n            color: Colors.blue,\n            fontSize: 18.0,\n            fontWeight: FontWeight.w500)),\n        ),\n      time: 8000,\n      onShow: () {}),\n  1: Stage(\n      widget: Container(\n        width: 200.0,\n        height: 200.0,\n        color: Colors.indigo[200],\n        alignment: Alignment.center,\n        key: Key('00'),\n        child: ScrollingText(\n              text: 'The next widgets will cross      fade.',\n              scrollingDuration: 2000,\n            ),\n          ),\n      time: 8000,\n      onShow: () {}),\n\n}\n```\n\n2. #### In the BLoC\n\n```dart\n  final text = StreamedValue\u003cString\u003e();\n  final staged = StagedObject();\n\n\n  // The map can be set through the constructor of the StagedObject\n  // or by the setStagesMap method like in this case.\n  setMap(Map\u003cint, Stage\u003e stagesMap) {\n    staged.setStagesMap(stagesMap);\n  }\n\n\n  // This method is then called from a button in the view\n  start() {\n    if (staged.getMapLength() \u003e 0) {\n      staged.setCallback(sendNextStageText);\n      staged.startStages();\n    }\n  }\n\n  // By this method we get the next stage to show it\n  // in a little box below the current stage\n  sendNextStageText() {\n    var nextStage = staged.getNextStage();\n    if (nextStage != null) {\n      text.value = \"Next stage:\";\n      widget.value = nextStage.widget;\n      stage.value = StageBridge(\n          staged.getStageIndex(), staged.getCurrentStage(), nextStage);\n    } else {\n      text.value = \"This is the last stage\";\n      widget.value = Container();\n    }\n  }\n\n```\n\n3. #### In the view:\n\n```dart\n  // Setting the map in the build method\n  StagedObjectBloc bloc = BlocProvider.of(context);\n  bloc.setMap(stagesMap);\n\n\n  // To show the current widget on the view using the ReceiverWidget.\n  // As an alternative it can be used the StreamedWidget/StreamBuilder.\n  ReceiverWidget(\n    stream: bloc.staged.widgetStream,\n  ),\n```\n\n### StagedWidget\n\n![StagedWidget](https://i.imgur.com/nCsbJCy.gif)\n\n#### Usage\n\n1. #### Declare a map \u003cint, Stage\u003e\n   Here the map is in the view and is set in the BLoC class by the setStagesMap.\n\n```dart\nMap\u003cint, Stage\u003e get stagesMap =\u003e \u003cint, Stage\u003e{\n  0: Stage(\n      widget: Container(\n        width: 200.0,\n        height: 200.0,\n        color: Colors.indigo[200],\n        alignment: Alignment.center,\n        key: Key('0'),\n        child: ScrollingText(\n          text:\n            'This stage will last 8 seconds. By the onShow call back it is possibile to assign an action when the widget shows.',\n          scrollingDuration: 2000,\n          style: TextStyle(\n            color: Colors.blue,\n            fontSize: 18.0,\n            fontWeight: FontWeight.w500)),\n        ),\n      time: 8000,\n      onShow: () {}),\n  1: Stage(\n      widget: Container(\n        width: 200.0,\n        height: 200.0,\n        color: Colors.indigo[200],\n        alignment: Alignment.center,\n        key: Key('00'),\n        child: ScrollingText(\n              text: 'The next widgets will cross      fade.',\n              scrollingDuration: 2000,\n            ),\n          ),\n      time: 8000,\n      onShow: () {}),\n\n}\n```\n\n2. #### In the view:\n\n```dart\nStagedWidget(\n  stagesMap: stagesMap,\n  onStart: // function to call,\n  onEnd: () {\n    // Function to call at the end of the last stage\n    // (only if relative timing):\n    // e.g. Navigator.pop(context);\n  }),\n```\n\n### WavesWidget\n\n#### Usage\n\n```dart\nWavesWidget(\n  width: 128.0,\n  height: 128.0,\n  color: Colors.red,\n  child: Container(\n    color: Colors.red[400],\n ),\n```\n\n### ScrollingText\n\n#### Usage\n\n```dart\nScrollingText(\n text: 'Text scrolling (during 8 seconds).',\n scrollingDuration: 2000, // in milliseconds\n style: TextStyle(color: Colors.blue,\n    fontSize: 18.0, fontWeight: FontWeight.w500),\n),\n```\n\n# Effects\n\n### LinearTransition\n\nLinear cross fading transition between two widgets, it can be used with the `StagedObject`.\n\n![LinearTransition](https://i.imgur.com/viGPpCu.gif)\n\n#### Usage\n\n```dart\nLinearTransition(\n  firstWidget: Container(height: 100.0, width: 100.0,\n        color: Colors.blue),\n  secondWidget: Container(height: 100.0, width: 100.0,\n        color: Colors.lime),\n  transitionDuration: 4000,\n),\n```\n\n### CurvedTransition\n\nCross fading transition between two widgets. This uses the Flutter way to make an animation.\n\n![CurvedTransition](https://i.imgur.com/kxWOKMU.gif)\n\n#### Usage\n\n```dart\nCurvedTransition(\n  firstWidget: Container(height: 100.0, width: 100.0,\n     color: Colors.blue),\n  secondWidget: Container(height: 100.0, width: 100.0,\n     color: Colors.lime),\n  transitionDuration: 4000,\n  curve: Curves.bounceInOut,\n),\n```\n\n### FadeInWidget\n\n#### Usage\n\n```dart\nFadeInWidget(\n  duration: 7000,\n  child: ScrollingText(\n      text: 'Fade in text',\n      scrollingDuration: 2000,\n      style: TextStyle(\n        color: Colors.blue,\n        fontSize: 94.0,\n        fontWeight: FontWeight.w500,\n      ),\n    ),\n),\n```\n\n### FadeOutWidget\n\n#### Usage\n\n```dart\nFadeOutWidget(\n  duration: 7000,\n  child: ScrollingText(\n      text: 'Fade out text',\n      scrollingDuration: 2000,\n      style: TextStyle(\n        color: Colors.blue,\n        fontSize: 94.0,\n        fontWeight: FontWeight.w500,\n      ),\n    ),\n),\n```\n\n### BlurWidget\n\n![Blur](https://i.imgur.com/Q8CJboZ.png)\n\n#### Usage\n\n```dart\nBlurWidget(\n  sigmaX: 2.0,\n  sigmaY: 3.0,\n  child: Text('Fixed blur')\n)\n```\n\n### BlurInWidget\n\n#### Usage\n\n```dart\nBlurInWidget(\n  initialSigmaX: 2.0,\n  initialSigmaY: 12.0,\n  duration: 5000,\n  refreshTime: 20,\n  child: Text('Blur out'),\n)\n```\n\n### BlurOutWidget\n\n#### Usage\n\n```dart\nBlurOutWidget(\n  finalSigmaX: 2.0,\n  finalSigmaY: 12.0,\n  duration: 5000,\n  refreshTime: 20,\n  child: Text('Blur out'),\n)\n```\n\n### AnimatedBlurWidget\n\n#### Usage\n\n```dart\nAnimatedBlurWidget(\n  initialSigmaX: 2.0,\n  initialSigmaY: 3.0,\n  finalSigmaX: 2.0,\n  finalSigmaY: 3.0,\n  duration: 5000,\n  reverseAnimation: true,\n  loop: true,\n  refreshTime: 20,\n  child: Text('Fixed blur')\n)\n```","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrideosapps%2Ffrideos_flutter","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffrideosapps%2Ffrideos_flutter","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffrideosapps%2Ffrideos_flutter/lists"}