{"id":23396160,"url":"https://github.com/mahmoud-saeed-mahmoud/loading_state_handler","last_synced_at":"2026-03-10T10:02:38.420Z","repository":{"id":259723025,"uuid":"879295009","full_name":"Mahmoud-Saeed-Mahmoud/loading_state_handler","owner":"Mahmoud-Saeed-Mahmoud","description":"The StateHandlerWidget manages different UI states—loading, error, empty, and normal—allowing you to customize the displayed widgets for each state.","archived":false,"fork":false,"pushed_at":"2025-05-29T16:19:42.000Z","size":821,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-10-12T10:07:24.610Z","etag":null,"topics":["dart","data","error","flutter","flutter-package","flutter-widget","loading","state"],"latest_commit_sha":null,"homepage":"https://mahmoud-saeed-mahmoud.github.io/loading_state_handler/","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Mahmoud-Saeed-Mahmoud.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,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2024-10-27T14:34:15.000Z","updated_at":"2025-05-29T16:18:58.000Z","dependencies_parsed_at":"2024-12-30T18:22:07.015Z","dependency_job_id":"ec3f43d1-c7e3-4a5a-9f0a-a9617f1bf6a4","html_url":"https://github.com/Mahmoud-Saeed-Mahmoud/loading_state_handler","commit_stats":null,"previous_names":["mahmoud-saeed-mahmoud/loading_state_handler"],"tags_count":15,"template":false,"template_full_name":null,"purl":"pkg:github/Mahmoud-Saeed-Mahmoud/loading_state_handler","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mahmoud-Saeed-Mahmoud%2Floading_state_handler","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mahmoud-Saeed-Mahmoud%2Floading_state_handler/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mahmoud-Saeed-Mahmoud%2Floading_state_handler/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mahmoud-Saeed-Mahmoud%2Floading_state_handler/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Mahmoud-Saeed-Mahmoud","download_url":"https://codeload.github.com/Mahmoud-Saeed-Mahmoud/loading_state_handler/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Mahmoud-Saeed-Mahmoud%2Floading_state_handler/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":30329697,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-03-10T05:25:20.737Z","status":"ssl_error","status_checked_at":"2026-03-10T05:25:17.430Z","response_time":106,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["dart","data","error","flutter","flutter-package","flutter-widget","loading","state"],"created_at":"2024-12-22T07:30:12.895Z","updated_at":"2026-03-10T10:02:38.357Z","avatar_url":"https://github.com/Mahmoud-Saeed-Mahmoud.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# LoadingStateHandlerWidget\n\n[![Dart](https://img.shields.io/badge/Dart-0175C2?logo=dart\u0026logoColor=white)](https://dart.dev) [![Flutter](https://img.shields.io/badge/Dart-0175C2?logo=flutter\u0026logoColor=white)](https://dart.dev) [![Pub Version](https://img.shields.io/pub/v/loading_state_handler)](https://pub.dev/packages/loading_state_handler) [![Pub Likes](https://img.shields.io/pub/likes/loading_state_handler)](https://img.shields.io/pub/likes/loading_state_handler) [![Pub Publisher](https://img.shields.io/pub/publisher/loading_state_handler)](https://img.shields.io/pub/publisher/loading_state_handler) ![Pub Points](https://img.shields.io/pub/points/loading_state_handler) ![Pub Monthly Downloads](https://img.shields.io/pub/dm/loading_state_handler) [![License](https://img.shields.io/badge/license-MIT-blue.svg)](/LICENSE)\n\nA powerful Flutter widget for managing UI states with built-in retry functionality. This widget handles loading, error, empty, and normal states elegantly while providing a customizable retry mechanism with cooldown support.\n\n## Features\n\n- 🔄 Smart state management (loading, error, empty, normal, data)\n- ⏲️ Built-in retry mechanism with configurable cooldown\n- 🎨 Fully customizable widgets for each state\n- 🌐 Global default configurations\n- ⚡ Optimized performance with const constructor\n- 🎯 Type-safe callbacks and builders\n\n## Installation\n\nRun the following command to add the package to your project:\n\n```bash\nflutter pub add loading_state_handler\n```\n\nor add the package to your `pubspec.yaml` file:\n\n```yml\ndependencies:\n  loading_state_handler: ^2.1.0\n```\n\n## Quick Start\n\n```dart\n// Set global defaults (optional)\nLoadingStateHandlerWidget.setDefaults(\n    defaultRetryCooldown: const Duration(seconds: 5),\n    defaultErrorBuilder:\n        (context, errorMessage, retryWidget, retryCooldown, onRetry) =\u003e Center(\n      child: Column(\n        spacing: 20,\n        mainAxisAlignment: MainAxisAlignment.center,\n        children: [\n          Text(errorMessage ?? 'An error occurred'),\n          retryWidget,\n        ],\n      ),\n    ),\n  );\n\n// Use in your widget\nLoadingStateHandlerWidget(\n        currentState: currentState,\n        onLoading: (defaultOnLoading, context, message) {\n          /// Uncomment to use the default loading callback\n          // defaultOnLoading?.call(context, message);\n          ScaffoldMessenger.of(context).showSnackBar(\n            SnackBar(\n              content: Text(message ?? 'Custom Loading...'),\n            ),\n          );\n        },\n        onData: (defaultOnData, context, message) {\n          defaultOnData?.call(context, message);\n          ScaffoldMessenger.of(context).showSnackBar(\n            SnackBar(\n              content: Text(message ?? 'Custom Got Data...'),\n            ),\n          );\n        },\n        errorMessage: errorMessage,\n        child: const Center(child: Text('Data Loaded Successfully!')),\n      );\n```\n\n## Advanced Usage\n\n### Retry Mechanism\n\nThe widget includes a sophisticated retry mechanism with cooldown:\n\n```dart\nLoadingStateHandlerWidget(\n        // State control properties\n        currentState: _currentState,\n\n        // Custom messages for different states\n        errorMessage: _errorMessage,\n        emptyMessage: 'No data available',\n        loadingMessage: 'Fetching data...',\n\n        // Retry configuration\n        enableRetry: true, // Enable the retry mechanism\n        retryCooldown:\n            const Duration(seconds: 3), // Custom cooldown per instance\n        onRetry: () {\n          // Callback executed when the retry button is pressed\n          // This will be disabled during the cooldown period\n          _fetchData();\n        },\n\n        // Content to display when in normal state (not loading/error/empty)\n        child: Center(\n          child: Column(\n            mainAxisAlignment: MainAxisAlignment.center,\n            children: [\n              const Text(\n                'Data loaded successfully!',\n                style: TextStyle(fontSize: 18),\n              ),\n              const SizedBox(height: 20),\n              ElevatedButton(\n                onPressed: _fetchData,\n                child: const Text('Refresh Data'),\n              ),\n            ],\n          ),\n        ),\n      );\n```\n\n### Global Configuration\n\nSet default behaviors for all instances:\n\n```dart\nLoadingStateHandlerWidget.setDefaults(\n    defaultOnData: (context, message) {\n      ScaffoldMessenger.of(context).showSnackBar(\n        SnackBar(\n          content: Text(message ?? 'Default Got Data...'),\n        ),\n      );\n    },\n\n    defaultOnLoading: (context, message) {\n      ScaffoldMessenger.of(context).showSnackBar(\n        SnackBar(\n          content: Text(message ?? 'Default Loading...'),\n        ),\n      );\n    },\n\n    defaultLoadingBuilder: (context, loadingMessage) =\u003e\n        const Center(child: CircularProgressIndicator()),\n\n    defaultErrorBuilder:\n        (context, errorMessage, retryWidget, retryCooldown, onRetry) =\u003e Center(\n      child: Text(\n        'Custom Error: $errorMessage',\n        style: const TextStyle(color: Colors.red),\n      ),\n    ),\n\n    defaultEmptyBuilder: (context, emptyMessage) =\u003e const Center(\n      child: Text('No Data Available'),\n    ),\n  );\n```\n\n### State-Specific Callbacks\n\nHandle different states with custom callbacks:\n\n```dart\nLoadingStateHandlerWidget(\n  loading: isLoading,\n  error: hasError,\n  empty: isEmpty,\n  onLoading: (defaultCallback, context, message) {\n    ScaffoldMessenger.of(context).showSnackBar(\n      SnackBar(\n        content: Text(message ?? 'Custom Loading...'),\n      ),\n    );\n  },\n  onError: (defaultCallback, context, message) {\n    ScaffoldMessenger.of(context).showSnackBar(\n      SnackBar(\n        content: Text(message ?? 'Custom Error...'),\n      ),\n    );\n  },\n  onEmpty: (defaultCallback, context, message) {\n    ScaffoldMessenger.of(context).showSnackBar(\n      SnackBar(\n        content: Text(message ?? 'Custom Empty...'),\n      ),\n    );\n  },\n  child: ContentWidget(),\n);\n```\n\n### Disable State Changes\n\nControl widget behavior granularly:\n\n```dart\nLoadingStateHandlerWidget(\n  disableWidgetChanges: false,\n  disableErrorWidgetChanges: true,\n  disableEmptyWidgetChanges: false,\n  // ... other properties\n);\n```\n\n### State Change Callback\n\nTrack state transitions with the `onStateChange` callback:\n\n```dart\nLoadingStateHandlerWidget(\n  currentState: currentState,\n  onStateChange: (oldState, newState) {\n    print('State changed from $oldState to $newState');\n    // You can use this to log state transitions or trigger additional actions\n  },\n  child: YourContentWidget(),\n);\n```\n\n### Custom Child Builder\n\nCustomize the child widget based on the current state:\n\n```dart\nLoadingStateHandlerWidget(\n  currentState: currentState,\n  childBuilder: (context, currentState, child) {\n    // Add a colored border based on the current state\n    return Container(\n      decoration: BoxDecoration(\n        border: Border.all(\n          color: _getStateColor(currentState),\n          width: 2.0,\n        ),\n        borderRadius: BorderRadius.circular(8.0),\n      ),\n      padding: const EdgeInsets.all(16.0),\n      child: child, // The original child widget\n    );\n  },\n  child: YourContentWidget(),\n);\n\n// Helper method to get color based on state\nColor _getStateColor(CurrentStateEnum state) {\n  switch (state) {\n    case CurrentStateEnum.normal: return Colors.grey;\n    case CurrentStateEnum.loading: return Colors.blue;\n    case CurrentStateEnum.data: return Colors.green;\n    case CurrentStateEnum.empty: return Colors.amber;\n    case CurrentStateEnum.error: return Colors.red;\n    default: return Colors.grey;\n  }\n}\n```\n\n## Properties\n\n| Property                    | Type                             | Description                                                |\n| --------------------------- | -------------------------------- | ---------------------------------------------------------- |\n| `controller`                | `LoadingStateHandlerController?` | Controller instance used to manage the state of the widget |\n| `currentState`              | `CurrentStateEnum`               | Current state of the widget                                |\n| `onStateChange`             | `OnStateChange?`                 | Callback when state changes, provides old and new states   |\n| `childBuilder`              | `ChildBuilder?`                  | Builder for customizing the child widget based on state    |\n| `errorTitle`                | `String?`                        | Custom error title                                         |\n| `retryButtonStyle`          | `ButtonStyle?`                   | Custom retry button style                                  |\n| `retryButtonTextStyle`      | `TextStyle?`                     | Custom retry button text style                             |\n| `retryMessageStyle`         | `TextStyle?`                     | Custom retry message style                                 |\n| `retryButtonText`           | `String?`                        | Custom retry button text                                   |\n| `retryMessage`              | `String?`                        | Custom retry message                                       |\n| `loadingWidget`             | `Widget?`                        | Custom loading widget                                      |\n| `errorWidget`               | `Widget?`                        | Custom error widget                                        |\n| `emptyWidget`               | `Widget?`                        | Custom empty widget                                        |\n| `disableWidgetChanges`      | `bool`                           | Disables state changes in the widget                       |\n| `disableErrorWidgetChanges` | `bool`                           | Disables state changes in the error widget                 |\n| `disableEmptyWidgetChanges` | `bool`                           | Disables state changes in the empty widget                 |\n| `enableRetry`               | `bool`                           | Enables retry functionality                                |\n| `retryCooldown`             | `Duration`                       | Cooldown period between retries                            |\n| `onRetry`                   | `VoidCallback`                   | Callback when retry is triggered                           |\n| `errorMessage`              | `String?`                        | Custom error message                                       |\n| `loadingMessage`            | `String?`                        | Custom loading message                                     |\n| `emptyMessage`              | `String?`                        | Custom empty state message                                 |\n\n## Example\n\nCheck out the [example](example/lib/main.dart), [retry example](example/lib/retry_example.dart), and [controller example](example/lib/loading_state_handler_with_controller_example.dart) for a complete demonstration of all features.\n\n## Contributing\n\nContributions are welcome! Please feel free to submit a Pull Request.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmahmoud-saeed-mahmoud%2Floading_state_handler","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmahmoud-saeed-mahmoud%2Floading_state_handler","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmahmoud-saeed-mahmoud%2Floading_state_handler/lists"}