diff --git a/packages/storybook_flutter/example/lib/main.dart b/packages/storybook_flutter/example/lib/main.dart index c383828..c56eccc 100644 --- a/packages/storybook_flutter/example/lib/main.dart +++ b/packages/storybook_flutter/example/lib/main.dart @@ -109,6 +109,15 @@ class MyApp extends StatelessWidget { name: 'Story/Nested/Multiple/Fourth', builder: (context) => const Center(child: Text('Fourth')), ), + Story( + name: 'Story/Logging', + builder: (context) => Center( + child: ElevatedButton( + onPressed: () => context.logger.log('This is a test message'), + child: const Text('Log something'), + ), + ), + ), Story( name: 'Story without a category', builder: (context) => const Center(child: Text('Simple text')), diff --git a/packages/storybook_flutter/lib/src/plugins/logging.dart b/packages/storybook_flutter/lib/src/plugins/logging.dart new file mode 100644 index 0000000..2998b8e --- /dev/null +++ b/packages/storybook_flutter/lib/src/plugins/logging.dart @@ -0,0 +1,92 @@ +import 'package:flutter/material.dart'; +import 'package:provider/provider.dart'; +import 'package:storybook_flutter/src/plugins/plugin.dart'; + +/// Plugin that allows logging from stories and callbacks. +/// Shows the recorded logs inside a panel. +/// +/// With this plugin, one can also test actions inside the story and +/// then see the logs appear in the panel. +class LoggingPlugin extends Plugin { + const LoggingPlugin() + : super( + icon: _buildIcon, + wrapperBuilder: _buildWrapper, + onPressed: _onPressed, + ); +} + +abstract interface class Logger { + void log(String message); +} + +class LoggingNotifier extends ChangeNotifier implements Logger { + final _logs = []; + var _panelVisible = false; + + List get logs => List.unmodifiable(_logs); + + bool get panelVisible => _panelVisible; + + set panelVisible(bool value) { + _panelVisible = value; + notifyListeners(); + } + + @override + void log(String message) { + _logs.insert(0, '${DateTime.now().toIso8601String()} - $message'); + notifyListeners(); + } +} + +extension Logging on BuildContext { + Logger get logger => read(); +} + +Widget? _buildIcon(BuildContext context) => const Icon( + Icons.format_quote, + semanticLabel: 'Log output', + ); + +Widget _buildWrapper(BuildContext context, Widget? child) => + ChangeNotifierProvider( + create: (context) => LoggingNotifier(), + child: Column( + children: [ + Expanded(flex: 3, child: child ?? const SizedBox.shrink()), + Consumer( + builder: (context, notifier, child) => notifier.panelVisible + ? Flexible( + flex: 1, + child: Container( + color: Colors.white, + padding: const EdgeInsets.symmetric( + vertical: 8, + horizontal: 16, + ), + child: ListView.builder( + itemCount: notifier.logs.length, + itemBuilder: (context, index) => Text( + notifier.logs[index], + style: const TextStyle( + fontSize: 14, + color: Colors.black, + height: 1.4, + fontFamily: 'Courier', + fontFamilyFallback: ['monospace'], + ), + ), + ), + ), + ) + : const SizedBox.shrink(), + ), + ], + ), + ); + +void _onPressed(BuildContext context) { + final notifier = context.read(); + notifier.panelVisible = !notifier.panelVisible; +} diff --git a/packages/storybook_flutter/lib/src/storybook.dart b/packages/storybook_flutter/lib/src/storybook.dart index a5ba408..aa147a7 100644 --- a/packages/storybook_flutter/lib/src/storybook.dart +++ b/packages/storybook_flutter/lib/src/storybook.dart @@ -3,6 +3,7 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:nested/nested.dart'; import 'package:provider/provider.dart'; +import 'package:storybook_flutter/src/plugins/logging.dart'; import 'package:storybook_flutter/src/plugins/plugin.dart'; import 'package:storybook_flutter/src/plugins/plugin_panel.dart'; import 'package:storybook_flutter/src/story.dart'; @@ -36,6 +37,7 @@ class Storybook extends StatefulWidget { LayoutPlugin(initialLayout), const ContentsPlugin(), const KnobsPlugin(), + const LoggingPlugin(), ...plugins ?? _defaultPlugins, ]), stories = UnmodifiableListView(stories); diff --git a/packages/storybook_flutter/lib/storybook_flutter.dart b/packages/storybook_flutter/lib/storybook_flutter.dart index 4d4b12d..13a142a 100644 --- a/packages/storybook_flutter/lib/storybook_flutter.dart +++ b/packages/storybook_flutter/lib/storybook_flutter.dart @@ -5,6 +5,7 @@ export 'src/knobs/knobs.dart'; export 'src/knobs/select_knob.dart'; export 'src/knobs/slider_knob.dart'; export 'src/knobs/string_knob.dart'; +export 'src/plugins/logging.dart'; export 'src/plugins/plugin.dart'; export 'src/plugins/plugin_panel.dart'; export 'src/story.dart'; diff --git a/packages/storybook_flutter/test/goldens/simple_story_layout.png b/packages/storybook_flutter/test/goldens/simple_story_layout.png index 3635db2..dbf44f9 100644 Binary files a/packages/storybook_flutter/test/goldens/simple_story_layout.png and b/packages/storybook_flutter/test/goldens/simple_story_layout.png differ diff --git a/packages/storybook_flutter/test/goldens/story_layout.png b/packages/storybook_flutter/test/goldens/story_layout.png index 8497300..de3e99b 100644 Binary files a/packages/storybook_flutter/test/goldens/story_layout.png and b/packages/storybook_flutter/test/goldens/story_layout.png differ