{"id":19214335,"url":"https://github.com/treeinfra/modifier","last_synced_at":"2026-05-14T08:43:33.205Z","repository":{"id":246211441,"uuid":"820475319","full_name":"treeinfra/modifier","owner":"treeinfra","description":"Syntax sugar optimizations to avoid nesting hell in Flutter.","archived":false,"fork":false,"pushed_at":"2024-06-30T16:03:42.000Z","size":65,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-01-04T18:12:13.743Z","etag":null,"topics":["cascade","chain-style-programming","flutter","nesting","nesting-hell","syntax-optimization","syntax-sugar","widget"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/modifier","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/treeinfra.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}},"created_at":"2024-06-26T14:38:31.000Z","updated_at":"2024-12-25T08:30:52.000Z","dependencies_parsed_at":"2024-06-26T15:50:47.187Z","dependency_job_id":"c1df613a-be5b-4e4a-b476-ad50136b7707","html_url":"https://github.com/treeinfra/modifier","commit_stats":null,"previous_names":["treeinfra/modifier"],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treeinfra%2Fmodifier","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treeinfra%2Fmodifier/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treeinfra%2Fmodifier/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/treeinfra%2Fmodifier/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/treeinfra","download_url":"https://codeload.github.com/treeinfra/modifier/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240287644,"owners_count":19777517,"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","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":["cascade","chain-style-programming","flutter","nesting","nesting-hell","syntax-optimization","syntax-sugar","widget"],"created_at":"2024-11-09T14:09:39.139Z","updated_at":"2025-11-14T08:03:22.511Z","avatar_url":"https://github.com/treeinfra.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Modifier\n\nSyntax sugar optimizations to avoid nesting hell in Flutter.\n\n## Examples:\n\nHere is a **Before** code and an **After** code.\nBoth their source codes are listed inside the child repositories\nin [the `example` folder](./example),\nwhere you can read the source code\nand run them to see whether they have the same result.\n\n[Before](./example/before/lib/main.dart) (115 lines):\n\n```dart\nimport 'package:flutter/widgets.dart';\n\nvoid main() {\n  runApp(const App());\n}\n\nclass App extends StatelessWidget {\n  const App({super.key});\n\n  @override\n  Widget build(BuildContext context) {\n    final media = MediaQueryData.fromView(View.of(context));\n    return MediaQuery(\n      data: media,\n      child: Directionality(\n        textDirection: TextDirection.ltr,\n        child: MessageHandler(\n          message: 'message',\n          child: Builder(builder: (context) {\n            final message = MessageHandler.of(context);\n            return Center(\n              child: Column(\n                mainAxisSize: MainAxisSize.min,\n                children: [\n                  Padding(\n                    padding: const EdgeInsets.only(bottom: 50),\n                    child: Text(message),\n                  ),\n                  GestureDetector(\n                    onTap: () {\n                      MessageHandler.update(context, (message) =\u003e '$message.');\n                    },\n                    child: const Text('Click me to append a dot'),\n                  ),\n                ],\n              ),\n            );\n          }),\n        ),\n      ),\n    );\n  }\n}\n\nclass MessageHandler extends StatefulWidget {\n  const MessageHandler({\n    super.key,\n    required this.message,\n    required this.child,\n  });\n\n  final String message;\n  final Widget child;\n\n  static String? maybeOf(BuildContext context) =\u003e\n      context.dependOnInheritedWidgetOfExactType\u003c_InheritedMessage\u003e()?.message;\n\n  static String of(BuildContext context) {\n    final message = maybeOf(context);\n    assert(message != null, 'cannot find $MessageHandler in context');\n    return message!;\n  }\n\n  static void update(\n      BuildContext context,\n      String Function(String raw) updater,\n      ) {\n    final handler =\n    context.dependOnInheritedWidgetOfExactType\u003c_InheritedMessage\u003e();\n    if (handler != null) handler.update(updater(handler.message));\n  }\n\n  @override\n  State\u003cMessageHandler\u003e createState() =\u003e _MessageHandlerState();\n}\n\nclass _MessageHandlerState extends State\u003cMessageHandler\u003e {\n  late String _message = widget.message;\n\n  void update(String message) {\n    if (_message != message) {\n      setState(() {\n        _message = message;\n      });\n    }\n  }\n\n  @override\n  void didUpdateWidget(covariant MessageHandler oldWidget) {\n    super.didUpdateWidget(oldWidget);\n    update(widget.message);\n  }\n\n  @override\n  Widget build(BuildContext context) =\u003e _InheritedMessage(\n    message: _message,\n    update: update,\n    child: widget.child,\n  );\n}\n\nclass _InheritedMessage extends InheritedWidget {\n  const _InheritedMessage({\n    required this.message,\n    required this.update,\n    required super.child,\n  });\n\n  final String message;\n  final void Function(String message) update;\n\n  @override\n  bool updateShouldNotify(covariant _InheritedMessage oldWidget) =\u003e\n      message != oldWidget.message;\n}\n```\n\n[After](./example/after/lib/main.dart) (22 lines):\n\n```dart\nimport 'package:flutter/widgets.dart';\nimport 'package:modifier/modifier.dart';\n\nvoid main() {\n  runApp(const App());\n}\n\nclass App extends StatelessWidget {\n  const App({super.key});\n\n  @override\n  Widget build(BuildContext context) =\u003e builder((context) =\u003e [\n    context.findAndTrust\u003cString\u003e().asText.padding(bottom: 50),\n    'Click me to append a dot'\n        .asText\n        .on(tap: () =\u003e context.update\u003cString\u003e((message) =\u003e '$message.'))\n  ].asColumn)\n      .center\n      .handle('message')\n      .ensureDirection(context)\n      .ensureMedia(context);\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftreeinfra%2Fmodifier","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftreeinfra%2Fmodifier","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftreeinfra%2Fmodifier/lists"}