one_context 0.4.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 86

Pub Version PRs Welcome

logo

One Context to rule them all

OneContext provides a simple way to deal with Dialogs, Overlays, Navigations, Theme* and MediaQuery* with no need of BuildContext. #

If you are Flutter developer, you donโ€™t have to learn something new. This package use the same identificators and names from framework. Itโ€™s not a specialized* implementation, so you have the power to create and do not get blocked because of that.

If you are Flutter package developer, OneContext can be very useful too! You can create a custom dialogs package with no need BuildContext, and release a version, that do not depends of the context, to the comunity.

one_context_demo

BuildContext always is needed (in some cases we need to choose carefully the specific one to make things work as expected), but, to global things, like dialogs, it can be reached by OneContext package. ๐ŸŽฏ

๐ŸŽฎ Let's start #

There are 2 ways to get OneContext singleton instance, OneContext() or OnceContext.intance. e.g.

    OneContext().pushNamed('/detail_page');
    OneContext.instance.pushNamed('/detail_page');

There are controllers to use navigation, overlays and dialogs. e.g.

    OneContext().navigator.pushNamed(...);
    OneContext().dialog.showDialog(...);
    OneContext().overlay.addOverlay(...);

Or, you can use the shortcuts ;)

    OneContext().pushNamed(...);
    OneContext().showDialog(...);
    OneContext().addOverlay(...);
    
    // and can access info from:
    // OneContext().mediaQuery ...
    // OneContext().textTheme ...
    // OneContext().theme ...

OneContext is:

  • Fast (O(1))
  • Easy to learn/use
  • It use same native function names from Flutter, to keep it simple and intuitive ;)

๐Ÿ’ฌ How to show Dialogs with no need of the BuildContext? #

// example snackBar
OneContext().showSnackBar(
    builder: (_) => SnackBar(content: Text('My awesome snackBar!'))
);
// example dialog
OneContext().showDialog(
    // barrierDismissible: false,
    builder: (_) => AlertDialog( 
        title: new Text("The Title"),
        content: new Text("The Body"),
    )
);
// example bottomSheet
OneContext().showBottomSheet(
    builder: (context) => Container(
    alignment: Alignment.topCenter,
    height: 200,
    child: IconButton(
        icon: Icon(Icons.arrow_drop_down),
        iconSize: 50,
        color: Colors.white,
        onPressed: () => Navigator.of(context).pop('sucess')), // or OneContext().popDialog('sucess');
    ),
);
// example modalBottomSheet
OneContext().showModalBottomSheet<String>(
    builder: (context) => Container(
        child: Column(
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
            ListTile(
                leading: Icon(Icons.music_note),
                title: Text('Music'),
                onTap: () => OneContext().popDialog('Music'); //Navigator.of(context).pop('Music')),
            ListTile(
                leading: Icon(Icons.videocam),
                title: Text('Video'),
                onTap: () => Navigator.of(context).pop('Video'),
            ),
            SizedBox(height: 45)
            ],
        ),
    )
);

โ›ต How to navigate? (All methods from Navigator Class are available) #

// go to second page using named route
OneContext().pushNamed('/second');
// go to second page using MaterialPageRoute
OneContext().push(MaterialPageRoute(builder: (_) => SecondPage()));
// go back from second page
OneContext().pop();
// Retrieve data from route when it's pops
String result = await OneContext().push<String>(MaterialPageRoute(builder: (_) => SecondPage()));
print(result);

๐Ÿฐ How to show Overlays? #

// show the default progress indicator
OneContext().showProgressIndicator();
// hide the default progress indicator
OneContext().hideProgressIndicator();
// show the default progress indicator with some colors
OneContext().showProgressIndicator(
    backgroundColor: Colors.blue.withOpacity(.3),
    circularProgressIndicatorColor: Colors.white
);

// Later
OneContext().hideProgressIndicator();
// Show a custom progress indicator
OneContext().showProgressIndicator(
    builder: (_) => MyAwesomeProgressIndicator();
);

// Later
OneContext().hideProgressIndicator();
// Show a custom widget in overlay stack

String myCustomAndAwesomeOverlayId = UniqueKey().toString();

OneContext().addOverlay(
    overlayId: myCustomAndAwesomeOverlayId,
    builder: (_) => MyCustomAndAwesomeOverlay()
);

// Later
OneContext().removeOverlay(myCustomAndAwesomeOverlayId);

๐ŸŽจ Changing Dark and Light theme mode #

Breaking change: OneHotReload becomes OneNotificationBuilder

OneNotification<OneThemeChangerEvent>(
  stopBubbling: true, // avoid bubbling to ancestors
  builder: (_, __) {
    return MaterialApp(
      builder: OneContext().builder,
      themeMode: OneThemeController.initThemeMode(ThemeMode.light),
      theme: OneThemeController.initThemeData(ThemeData(brightness: Brightness.light)),
      darkTheme: OneThemeController.initDarkThemeData(ThemeData(brightness: Brightness.dark)),
      ...
    );
);

// Later...
OneContext().oneTheme.toggleMode();

// Or change only the dark theme
OneContext().oneTheme.changeDarkThemeData(
  ThemeData(
    primarySwatch: Colors.amber,
    brightness: Brightness.dark
 )
);

๐Ÿšง Reload, Restart and Reboot the app (Need bubbling events or data?) #

The concept of using Notifications:

First define the data type in type generics, after that, you can rebuild multiple ancestors widgets that listen the same data type. This is used for the package in this example, to change ThemeMode and Locale and even Restart the app entirely.

OneNotification<List<Locale>>(
      onVisited: (context, localeList) {
        print('widget visited!');
      },
      stopBubbling: true, // avoid the data bubbling to ancestors widgets
      initialData: _localeEnglish, // [data] is null during boot of the application, but you can set initialData
      rebuildOnNull: true, // Allow other entities reload this widget without messing up currenty data (Data is cached on first event)
      builder: (context, localeList) {
        return MaterialApp(
          supportedLocales: localeList,
        );
      },
    );

Need to dispatch more specialized data/event?


// My Specialized Event
class MySpecializedEvent {
  final String text;
  MySpecializedEvent(this.text);
}

// Widget
OneNotification<MySpecializedEvent>(
  builder: (context, event) {
    return Text(event.text);
  },
)

// Later, in children, call `OneNotifier.notify` to get ancestors notified
OneNotifier.notify(
  context,
  NotificationPayload(
    data: MySpecializedEvent('Nice!');
  )
);

Reload and Restart the app

// Place that widget on most top
OneNotification(
  builder: (_, __) => child
);

// Later... in children

// Dont lose state
OneNotification.softReloadRoot(context);

// Lose state
OneNotification.hardReloadRoot(context);

Reboot and load different apps

// Set the main() function
void main() => OnePlatform.app = () => MyApp();

// Later... Call reboot without recreating root app
OnePlatform.reboot();

// Later... Call reboot recreating the entire application
OnePlatform.reboot(
  builder: () => MyApp()
);

// You even can load an entire different app
OnePlatform.reboot(
  builder: () => MyApp2()
);

โš™ Theme and MediaQuery #

print('Platform: ' + OneContext().theme.platform); // TargetPlatform.iOS
print('Orientation: ' + OneContext().mediaQuery.orientation); // Orientation.portrait

โš  Important: Configure MaterialApp. e.g. #

/// important: Use [OneContext().builder] in `MaterialApp` builder, in order to show dialogs and overlays.
/// important: Use [OneContext().key] in `MaterialApp` navigatorKey, in order to navigate.
return MaterialApp(
    builder: OneContext().builder,
    navigatorKey: OneContext().key,
    ...
);

In initState (Can not show dialog if markNeedsBuild, so schedule to next frame) #

@override
  void initState() {
    super.initState();

    WidgetsBinding.instance.addPostFrameCallback(
      (duration) => OneContext().showDialog(
        builder: (_) => AlertDialog(
          title: new Text("On Page Load"),
          content: new Text("Hello World!"),
        ),
      ),
    );

๐Ÿšฆ Warnings #

* OneContex().theme and OneContex().mediaQuery are global instances of the root of the widget tree. Use it with care! It can reproduce unexpected behavior if you don't understand it.

* OneContext().context is like a root context, so, it should not be used directly, as it can reproduce unexpected behaviors, unless you have a understanding how it works. It shouldn't work well with InheritedWidget for example.

* This package only uses specialized implementation in Overlays, to make things easy and ensure a quick start.

๐Ÿ‘จโ€๐Ÿ’ป๐Ÿ‘จโ€๐Ÿ’ป Contributing #

Contributions of any kind are welcome! I'll be glad to analyse and accept them! ๐Ÿ‘พ

If you have any question about the project:

Email-me: fastencoding@gmail.com

Connect with me at LinkedIn.

[0.4.0] - May 29, 2020 #

  • Breaking changes on OneHotReload (check README to upgrade)
  • OneHotReload becomes OneNotification, providing a top most generic feature.

[0.3.0] - May 25, 2020 #

  • Add OneHotReload to reload widget tree (useful for theme, locale, etc...)
  • Add dark and light theme mode changer (Auto save)
  • Add themeData and darkThemeData changer
  • Add reload, restart and reboot app
  • Add boot another app with setUp feature

[0.2.3] - May 6, 2020 #

  • fix generics

[0.2.2] - May 6, 2020 #

  • Linter fixes

[0.2.1] - May 5, 2020 #

  • Add MediaQuery
  • Add Theme
  • Add TextTheme

[0.1.1] - Update description #

[0.1.0] - Initial release #

  • add showDialog
  • add showModalBottomSheet
  • add showBottomSheet
  • add showSnackBar
  • add dismissSnackBar
  • add showOverlay
  • add addOverlay
  • add showProgressIndicator
  • add all Flutter Navigator methods (push, pushNamed, ...) - Flutter 1.12.13+hotfix.9 โ€ข channel stable โ€ข Dart 2.7.2

example/lib/main.dart

import 'dart:math';
import 'package:flutter/services.dart';
import 'package:one_context/one_context.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

bool debugShowCheckedModeBanner = false;
const localeEnglish = [Locale('en', '')];

void main() => OnePlatform.app = () => MyApp();

class MyApp extends StatelessWidget {
  MyApp() {
    print('MyApp loaded!');
    debugShowCheckedModeBanner = true;

    // Reseting light theme
    if (OneContext.hasContext)
      OneContext().oneTheme.changeThemeData(
          ThemeData(primarySwatch: Colors.green, brightness: Brightness.light));
  }

  @override
  Widget build(BuildContext context) {
    /// important: Use [OneContext().builder] in MaterialApp builder, in order to show dialogs, overlays and change the app theme.
    /// important: Use [OneContext().key] in MaterialApp navigatorKey, in order to navigate.

    return OneNotification<List<Locale>>(
      onVisited: (_, __) {
        print('Root widget visited!');
      },
      // This widget rebuild the Material app to update theme, supportedLocales, etc...
      stopBubbling: true, // avoid the data bubbling to ancestors widgets
      initialData:
          localeEnglish, // [data] is null during boot of the application, but you can set initialData ;)
      rebuildOnNull:
          true, // Allow other entities reload this widget without messing up currenty data (Data is cached on first event)

      builder: (context, dataLocale) {
        if (dataLocale != null && dataLocale != localeEnglish)
          print('Set Locale: $dataLocale');

        return OneNotification<OneThemeChangerEvent>(
            onVisited: (_, __) {
              print('Theme Changer widget visited!');
            },
            stopBubbling: true,
            builder: (context, data) {
              return MaterialApp(
                debugShowCheckedModeBanner: debugShowCheckedModeBanner,

                // Configure reactive theme mode and theme data (needs OneNotification above in the widget tree)
                themeMode: OneThemeController.initThemeMode(ThemeMode.light),
                theme: OneThemeController.initThemeData(ThemeData(
                    primarySwatch: Colors.green, brightness: Brightness.light)),
                darkTheme: OneThemeController.initDarkThemeData(
                    ThemeData(brightness: Brightness.dark)),

                // Configure [OneContext] to dialogs, overlays, snackbars, and ThemeMode
                builder: OneContext().builder,
                // builder: (context, widget) => OneContext().builder(context, widget, mediaQueryData: MediaQuery.of(context).copyWith(textScaleFactor: 1.0)),

                // Set navigator key in order to navigate
                navigatorKey: OneContext().key,

                // [data] comes through events
                supportedLocales: dataLocale ?? [const Locale('en', '')],

                title: 'OneContext Demo',
                home: MyHomePage(
                  title: 'OneContext Demo',
                ),
                routes: {'/second': (context) => SecondPage()},
              );
            });
      },
    );
  }
}

class MyApp2 extends StatelessWidget {
  MyApp2() {
    print('MyApp2 loaded!');
    OneContext().key = GlobalKey<NavigatorState>();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
        theme: ThemeData(primarySwatch: Colors.pink),
        title: 'OneContext Demo',
        home: MyHomePage2(title: 'BOOT A NEW APPLICATION'),
        routes: {'/second': (context) => SecondPage()},
        builder: OneContext().builder,
        navigatorKey: OneContext().key);
  }
}

class MyHomePage2 extends StatefulWidget {
  MyHomePage2({Key key, this.title}) : super(key: key);
  final String title;
  @override
  _MyHomePage2State createState() => _MyHomePage2State();
}

class _MyHomePage2State extends State<MyHomePage2> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Container(
        color: Colors.pink,
        alignment: Alignment.center,
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            RaisedButton(
                child: Text('COME BACK TO THE OLD APP'),
                onPressed: () {
                  OnePlatform.reboot(
                    setUp: () {
                      OneContext().key = GlobalKey<NavigatorState>();
                    },
                    builder: () => MyApp(),
                  );
                }),
            RaisedButton(
                child: Text('Navigate to Second Page'),
                onPressed: () {
                  OneContext().pushNamed('/second');
                })
          ],
        ),
      ),
    );
  }
}

class MyHomePage extends StatefulWidget {
  final String reloadAppButtonLabel;
  MyHomePage({Key key, this.title, this.reloadAppButtonLabel})
      : super(key: key);
  final String title;
  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage>
    with SingleTickerProviderStateMixin {
  Map<String, Offset> randomOffset = Map<String, Offset>();
  AnimationController _controller;
  Animation<Offset> _offsetAnimation;

  @override
  void initState() {
    super.initState();

    _controller = AnimationController(
      duration: const Duration(milliseconds: 1000),
      vsync: this,
    );

    _offsetAnimation = Tween<Offset>(
      begin: Offset(0, -1),
      end: const Offset(0, 0),
    ).animate(CurvedAnimation(
      parent: _controller,
      curve: Curves.easeInOutCubic,
    ));
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: SingleChildScrollView(
        child: Container(
          alignment: Alignment.center,
          padding: EdgeInsets.all(16),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            mainAxisAlignment: MainAxisAlignment.center,
            mainAxisSize: MainAxisSize.min,
            children: <Widget>[
              SizedBox(height: 20),
              RaisedButton(
                child: Text(
                    'Soft Reload (ShowModeBanner = $debugShowCheckedModeBanner)'),
                onPressed: () {
                  debugShowCheckedModeBanner = !debugShowCheckedModeBanner;
                  OneNotification.softReloadRoot(
                      context); // It will visit ancestors till the root OneNotificationBuilder widget)
                },
              ),
              RaisedButton(
                child: Text('Hard Reload'),
                onPressed: () {
                  OneNotification.hardReloadRoot(context);
                },
              ),
              RaisedButton(
                child: Text('Soft Reeboot the app'),
                onPressed: () {
                  OnePlatform.reboot(setUp: () => print('Reboot the app!'));
                },
              ),
              RaisedButton(
                child: Text('Setup and Hard Reeboot'),
                onPressed: () {
                  OnePlatform.reboot(
                      builder: () => MyApp(),
                      setUp: () {
                        print(
                            '\n\nSetting debugShowCheckedModeBanner = true, so the debug banner should appear on the app right now.'
                            '\n\n That is useful for load environment variables and project configuration before boot the app!'
                            '\n And if you just need run some stuffs and reload the app without change it.');
                        debugShowCheckedModeBanner = true;
                      });
                },
              ),
              RaisedButton(
                child: Text('Load another app'),
                onPressed: () {
                  OnePlatform.reboot(
                      setUp: () {
                        OneContext().key = GlobalKey<NavigatorState>();
                      },
                      builder: () => MyApp2());
                },
              ),
              RaisedButton(
                child: Text('Change ThemeData Light'),
                onPressed: () {
                  OneContext().oneTheme.changeThemeData(ThemeData(
                      primarySwatch: Colors.purple,
                      brightness: Brightness.light));
                },
              ),
              RaisedButton(
                child: Text('Change ThemeData Dark'),
                onPressed: () {
                  OneContext().oneTheme.changeDarkThemeData(ThemeData(
                      primarySwatch: Colors.amber,
                      brightness: Brightness.dark));
                },
              ),
              RaisedButton(
                child: Text('Toggle ThemeMode (Dark/Light)'),
                onPressed: () {
                  OneContext().oneTheme.toggleMode();
                },
              ),
              RaisedButton(
                child: Text('Change to english locale support'),
                onPressed: () {
                  OneNotification.notify<List<Locale>>(context,
                      payload: NotificationPayload(data: [
                        Locale('en', ''), // English
                      ]));
                },
              ),
              RaisedButton(
                child: Text('Show SnackBar'),
                onPressed: () {
                  showTipsOnScreen('OneContext().showSnackBar()');
                  OneContext()
                      .dismissSnackBar(); // Dismiss snackbar before show another ;)
                  OneContext().showSnackBar(
                      builder: (context) => SnackBar(
                            content: Text(
                              'My awesome snackBar!',
                              textAlign: TextAlign.center,
                              style: Theme.of(context)
                                  .textTheme
                                  .title
                                  .copyWith(color: Colors.white),
                            ),
                            action: SnackBarAction(
                                label: 'DISMISS', onPressed: () {}),
                          ));
                },
              ),
              RaisedButton(
                child: Text('Show Dialog'),
                onPressed: () async {
                  showTipsOnScreen('OneContext().showDialog<String>()');

                  var result = await OneContext().showDialog<String>(
                      // Don't need context to show alertDialog
                      builder: (context) => AlertDialog(
                            title: new Text("The Title"),
                            content: new Text("The Body"),
                            actions: <Widget>[
                              new FlatButton(
                                  child: new Text("OK"),
                                  onPressed: () =>
                                      OneContext().popDialog('ok')),
                              new FlatButton(
                                  child: new Text("CANCEL"),
                                  onPressed: () =>
                                      OneContext().popDialog('cancel')),
                            ],
                          ));
                  print(result);
                },
              ),
              RaisedButton(
                child: Text('Show modalBottomSheet'),
                onPressed: () async {
                  showTipsOnScreen(
                      'OneContext().showModalBottomSheet<String>()');
                  var result = await OneContext().showModalBottomSheet<String>(
                      builder: (context) => Container(
                            child: Column(
                              mainAxisSize: MainAxisSize.min,
                              children: <Widget>[
                                ListTile(
                                    leading: Icon(Icons.music_note),
                                    title: Text('Music'),
                                    onTap: () =>
                                        OneContext().popDialog('Music')),
                                ListTile(
                                    leading: Icon(Icons.videocam),
                                    title: Text('Video'),
                                    onTap: () =>
                                        OneContext().popDialog('Video')),
                                SizedBox(height: 45)
                              ],
                            ),
                          ));
                  print(result);
                },
              ),
              RaisedButton(
                child: Text('Show bottomSheet'),
                onPressed: () {
                  showTipsOnScreen('OneContext().showBottomSheet()');
                  OneContext().showBottomSheet(
                    builder: (context) => Container(
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.all(Radius.circular(10)),
                        color: Colors.red,
                      ),
                      margin: EdgeInsets.all(16),
                      alignment: Alignment.topCenter,
                      height: 200,
                      child: IconButton(
                          icon: Icon(Icons.arrow_drop_down),
                          iconSize: 50,
                          color: Colors.white,
                          onPressed: () => OneContext().popDialog()),
                    ),
                  );
                },
              ),
              RaisedButton(
                  child: Text('Show and block till input'),
                  onPressed: () async {
                    showTipsOnScreen('OneContext().showDialog<int>()');
                    switch (await OneContext().showDialog<int>(
                        barrierDismissible: false,
                        builder: (BuildContext context) {
                          return SimpleDialog(
                            shape: RoundedRectangleBorder(
                                borderRadius:
                                    BorderRadius.all(Radius.circular(10))),
                            title: const Text('Select assignment'),
                            children: <Widget>[
                              SimpleDialogOption(
                                onPressed: () {
                                  OneContext().popDialog(1);
                                },
                                child: const Text('Number 1'),
                              ),
                              SimpleDialogOption(
                                onPressed: () {
                                  OneContext().popDialog(2);
                                },
                                child: const Text('Number 2'),
                              ),
                            ],
                          );
                        })) {
                      case 1:
                        print('number one');
                        break;
                      case 2:
                        print('number two');
                        break;
                    }
                  }),
              RaisedButton(
                child: Text('Show default progress indicator'),
                onPressed: () {
                  showTipsOnScreen('OneContext().showProgressIndicator()');

                  OneContext().showProgressIndicator();
                  Future.delayed(Duration(seconds: 2),
                      () => OneContext().hideProgressIndicator());
                },
              ),
              RaisedButton(
                child: Text('Show progress indicator colored'),
                onPressed: () {
                  showTipsOnScreen(
                      'OneContext().showProgressIndicator(backgroundColor, circularProgressIndicatorColor)');
                  OneContext().showProgressIndicator(
                      backgroundColor: Colors.blue.withOpacity(.3),
                      circularProgressIndicatorColor: Colors.red);
                  Future.delayed(Duration(seconds: 2),
                      () => OneContext().hideProgressIndicator());
                },
              ),
              RaisedButton(
                child: Text('Show custom progress indicator'),
                onPressed: () {
                  showTipsOnScreen(
                      'OneContext().showProgressIndicator(backgroundColor, circularProgressIndicatorColor)');
                  OneContext().showProgressIndicator(
                    builder: (_) => Container(
                        color: Colors.black38,
                        alignment: Alignment.center,
                        child: SizedBox(
                          height: 80,
                          width: 80,
                          child: Card(
                            color: Colors.white,
                            elevation: 0,
                            // shape: RoundedRectangleBorder(),
                            child: Center(child: CircularProgressIndicator()),
                          ),
                        )),
                  );
                  Future.delayed(Duration(seconds: 2),
                      () => OneContext().hideProgressIndicator());
                },
              ),
              RaisedButton(
                child: Text('Show custom animated indicator'),
                onPressed: () {
                  showTipsOnScreen(
                      'OneContext().showProgressIndicator(builder)');
                  OneContext().showProgressIndicator(
                      builder: (_) => SlideTransition(
                            position: _offsetAnimation,
                            child: Container(
                              padding: EdgeInsets.only(top: 120),
                              alignment: Alignment.topCenter,
                              child: Container(
                                  alignment: Alignment.center,
                                  height: 60,
                                  width: 60,
                                  decoration: BoxDecoration(
                                    color: Colors.yellow,
                                    borderRadius: BorderRadius.circular(30),
                                  ),
                                  child: CircularProgressIndicator()),
                            ),
                          ),
                      backgroundColor: Colors.transparent);
                  _controller.reset();
                  _controller.forward();
                  Future.delayed(Duration(seconds: 3), () {
                    _controller.reverse().whenComplete(
                        () => OneContext().hideProgressIndicator());
                  });
                },
              ),
              RaisedButton(
                child: Text('Add a generic overlay'),
                onPressed: () {
                  showTipsOnScreen('OneContext().addOverlay(builder)');
                  String overId = UniqueKey().toString();
                  double getY() => Random()
                      .nextInt(
                          (MediaQuery.of(context).size.height - 50).toInt())
                      .toDouble();
                  double getX() => Random()
                      .nextInt((MediaQuery.of(context).size.width - 50).toInt())
                      .toDouble();
                  randomOffset.putIfAbsent(
                      overId, () => Offset(getX(), getY()));
                  Widget w = RaisedButton(
                      child: Text(
                        'CLOSE OR DRAG',
                        style: TextStyle(color: Colors.white),
                      ),
                      color: Colors.blue,
                      onPressed: () {
                        OneContext().removeOverlay(overId);
                      });
                  OneContext().addOverlay(
                      builder: (_) => Positioned(
                          top: randomOffset[overId].dy,
                          left: randomOffset[overId].dx,
                          child: Draggable(
                            onDragEnd: (DraggableDetails detail) =>
                                randomOffset[overId] = detail.offset,
                            childWhenDragging: Container(),
                            child: w,
                            feedback: w,
                          )),
                      overlayId: overId);
                },
              ),
              RaisedButton(
                child: Text('Push a second page (push)'),
                onPressed: () async {
                  showTipsOnScreen('OneContext().push()');
                  String result = await OneContext().push<String>(
                      MaterialPageRoute(builder: (_) => SecondPage()));
                  print('$result from OneContext().push()');
                },
              ),
              RaisedButton(
                child: Text('Push a second page (pushNamed)'),
                onPressed: () async {
                  showTipsOnScreen('OneContext().pushNamed()');
                  Object result = await OneContext().pushNamed('/second');
                  print('$result from OneContext().pushNamed()');
                },
              ),
              RaisedButton(
                child: Text('Show MediaQuery info'),
                onPressed: () async {
                  MediaQueryData mediaQuery = OneContext().mediaQuery;
                  String info =
                      'orientation: ${mediaQuery.orientation.toString()}\n'
                      'devicePixelRatio: ${mediaQuery.devicePixelRatio}\n'
                      'platformBrightness: ${mediaQuery.platformBrightness.toString()}\n'
                      'width: ${mediaQuery.size.width}\n'
                      'height: ${mediaQuery.size.height}\n'
                      'textScaleFactor: ${mediaQuery.textScaleFactor}';
                  print(info);
                  showTipsOnScreen(info, size: 200, seconds: 5);
                },
              ),
              RaisedButton(
                child: Text('Show Theme info'),
                onPressed: () async {
                  ThemeData theme = OneContext().theme;
                  String info = 'platform: ${theme.platform}\n'
                      'primaryColor: ${theme.primaryColor}\n'
                      'accentColor: ${theme.accentColor}\n'
                      'title.color: ${theme.textTheme.title.color}';
                  print(info);
                  showTipsOnScreen(info, size: 200, seconds: 5);
                },
              ),
              SizedBox(height: 24),
            ],
          ),
        ),
      ),
    );
  }
}

class SecondPage extends StatelessWidget {
  @override
  Widget build(BuildContext context) => Scaffold(
      appBar: AppBar(),
      body: Center(
          child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: <Widget>[
          Text('Second Page'),
          RaisedButton(
            child: Text('Go Back - pop("success")'),
            onPressed: () {
              // showTipsOnScreen('OneContext().pop("success")');
              OneContext().pop('success');
            },
          ),
        ],
      )));
}

// Dont need context, so features can be create in any place ;)
void showTipsOnScreen(String text, {double size, int seconds}) {
  String id = UniqueKey().toString();
  OneContext().addOverlay(
    overlayId: id,
    builder: (_) => Align(
      alignment: Alignment.topCenter,
      child: Container(
          alignment: Alignment.bottomCenter,
          padding: EdgeInsets.symmetric(
              horizontal: kFloatingActionButtonMargin, vertical: 8),
          child: FlatButton(
            onPressed: null,
            child: Text(
              text,
              style: TextStyle(color: Colors.white, fontSize: 16),
            ),
          ),
          color: Colors.red,
          height: size ?? 100,
          width: double.infinity),
    ),
  );
  Future.delayed(
      Duration(seconds: seconds ?? 2), () => OneContext().removeOverlay(id));
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  one_context: ^0.4.0

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:one_context/one_context.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
71
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
86
Learn more about scoring.

We analyzed this package on Jul 14, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.15
  • Flutter: 1.17.5

Analysis suggestions

Package does not support Flutter platform Android

Because:

  • package:one_context/one_context.dart that imports:
  • package:one_context/src/controllers/one_theme_controller.dart that imports:
  • package:shared_preferences/shared_preferences.dart that imports:
  • package:shared_preferences_linux/shared_preferences_linux.dart that declares support for platforms: Linux

Package does not support Flutter platform Web

Because:

  • package:one_context/one_context.dart that imports:
  • package:one_context/src/controllers/one_theme_controller.dart that imports:
  • package:shared_preferences/shared_preferences.dart that imports:
  • package:shared_preferences_linux/shared_preferences_linux.dart that declares support for platforms: Linux

Package does not support Flutter platform Windows

Because:

  • package:one_context/one_context.dart that imports:
  • package:one_context/src/controllers/one_theme_controller.dart that imports:
  • package:shared_preferences/shared_preferences.dart that declares support for platforms: Android, iOS, Linux, macOS, Web

Package does not support Flutter platform iOS

Because:

  • package:one_context/one_context.dart that imports:
  • package:one_context/src/controllers/one_theme_controller.dart that imports:
  • package:shared_preferences/shared_preferences.dart that imports:
  • package:shared_preferences_linux/shared_preferences_linux.dart that declares support for platforms: Linux

Package does not support Flutter platform macOS

Because:

  • package:one_context/one_context.dart that imports:
  • package:one_context/src/controllers/one_theme_controller.dart that imports:
  • package:shared_preferences/shared_preferences.dart that imports:
  • package:shared_preferences_linux/shared_preferences_linux.dart that declares support for platforms: Linux

Package not compatible with SDK dart

Because:

  • one_context that is a package requiring null.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
flutter 0.0.0
shared_preferences ^0.5.7+3 0.5.8
Transitive dependencies
collection 1.14.12 1.14.13
file 5.2.1
flutter_web_plugins 0.0.0
intl 0.16.1
meta 1.1.8 1.2.2
path 1.7.0
path_provider_linux 0.0.1+2
path_provider_platform_interface 1.0.2
platform 2.2.1
plugin_platform_interface 1.0.2
process 3.0.13
shared_preferences_linux 0.0.2+1
shared_preferences_macos 0.0.1+10
shared_preferences_platform_interface 1.0.4
shared_preferences_web 0.1.2+7
sky_engine 0.0.99
typed_data 1.1.6 1.2.0
vector_math 2.0.8 2.1.0-nullsafety
xdg_directories 0.1.0
Dev dependencies
flutter_test