voyager 0.9.0 copy "voyager: ^0.9.0" to clipboard
voyager: ^0.9.0 copied to clipboard

outdated

Router and basic dependency injection library for Flutter. Define navigation paths in YAML and power them up with custom plugins.

example/lib/main.dart

import 'package:example/gen/voyager_gen.dart';
import 'package:flutter/material.dart';
import 'package:voyager/voyager.dart';
import 'package:provider/provider.dart';

String requirements() {
  return '''
---
'/home' :
  type: 'home'
  widget: PageWidget
  title: "This is Home"
  body: "Hello World"
  fabPath: /fab
  actions:
    - target: /list
      icon: e896
'/other/:title' :
  type: 'other'
  widget: PageWidget
  body: "Welcome to the other side"
  title: "This is %{title}"
'/fab' :
  type: fab
  widget: FabWidget
  target: /other/thing
  icon: e88f # check icons.dart for reference
'/list' :
  type: 'list'
  widget: ListWidget
  title: "Voyager Talks"
  items:
    - city: "Berlin"
      event: Droidcon
      date: July 1, 2019
    - city: "London"
      event: FlutterLDN
      date: October 21, 2019
    - city: "Łódź"
      event: Mobilization
      date: October 26, 2019
'/_object/:className':
  type: object_item
  widget: "%{className}Widget"
''';
}

Future<List<RouterPath>> paths() {
  return loadPathsFromString(requirements());
}

/// plugins that are mentioned in requirements
List<RouterPlugin> plugins() => [
      /// provide widget builders for expressions used in YAML
      WidgetPluginBuilder()
          .add<PageWidget>((context) => PageWidget())
          .add<ListWidget>((context) => ListWidget())
          .add<TalkWidget>((context) => TalkWidget())
          .addMethod(makeMeFab, "FabWidget")
          .build(),
      IconPlugin()
    ];

class IconPlugin extends RouterPlugin {
  IconPlugin() : super("icon");

  @override
  void outputFor(RouterContext context, dynamic config, Voyager output) {
    output["icon"] = Icon(IconData(int.parse(config.toString(), radix: 16),
        fontFamily: 'MaterialIcons'));
  }

  static Icon fromHexValue(String hexValue) {
    return Icon(
        IconData(int.parse(hexValue, radix: 16), fontFamily: 'MaterialIcons'));
  }
}

void main() {
  // wrapped with a builder, otherwise hot reload doesn't quite click
  runApp(Builder(builder: (builder) => appOrSplash()));
}

Widget appOrSplash() {
  return FutureBuilder(
      future: loadRouter(paths(), plugins()),
      builder: (BuildContext context, AsyncSnapshot<RouterNG> snapshot) {
        if (snapshot.hasData && snapshot.data != null) {
          final router = snapshot.data;
          return Provider<RouterNG>.value(
              value: router,
              child: MaterialApp(
                title: "Voyager Demo",
                home:
                    VoyagerWidget(path: VoyagerPaths.pathHome, router: router),
                theme: themeData(),
                onGenerateRoute: router.generator(),
              ));
        } else {
          return SplashScreen();
        }
      });
}

Widget makeMeFab(BuildContext context) {
  final voyager = Provider.of<Voyager>(context);
  return FloatingActionButton(
    onPressed: () {
      Navigator.of(context).pushNamed(voyager["target"]);
    },
    tooltip: 'Navigate',
    child: voyager["icon"],
  );
}

ThemeData themeData() {
  return ThemeData(
      brightness: Brightness.dark,
      primaryColor: const Color(0xff5bb974),
      canvasColor: Colors.black,
      accentColor: const Color(0xfffcc934));
}

class PageWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final voyager = Provider.of<Voyager>(context);
    final String title = voyager["title"];

    return Scaffold(
        appBar: AppBar(
          title: Text(title),
          actions: actions(context),
        ),
        body: Center(
          child: Text(voyager["body"], style: const TextStyle(fontSize: 24)),
        ),
        floatingActionButton: voyager["fabPath"] != null
            ? VoyagerWidget(
                path: voyager["fabPath"],
              )
            : null);
  }
}

class ListWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final voyager = Provider.of<Voyager>(context);
    final String title = voyager["title"];

    // ignore: avoid_as
    final talks = (voyager["items"] as List<dynamic>)
        .toList()
        .map((dynamic item) => Talk(item["city"], item["event"], item["date"]))
        .toList();

    return Scaffold(
        appBar: AppBar(
          title: Text(title),
          actions: actions(context),
        ),
        body: VoyagerListView(talks, idMapper, objectMapper, null),
        floatingActionButton: voyager["fabPath"] != null
            ? VoyagerWidget(
                path: voyager["fabPath"],
              )
            : null);
  }

  // ignore: avoid_as
  static String idMapper(dynamic item) => (item as Talk).city;
  static String objectMapper(dynamic item) =>
      "/_object/${item.runtimeType.toString()}";
}

class Talk {
  const Talk(this.city, this.event, this.date);
  final String city;
  final String event;
  final String date;
}

class TalkWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final Talk talk = Provider.of<VoyagerArgument>(context).value;
    return Padding(
        padding: const EdgeInsets.fromLTRB(16, 8, 16, 8),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: <Widget>[
            Text(talk.city,
                style: TextStyle(
                    fontSize: 20,
                    color: theme.accentColor,
                    fontWeight: FontWeight.bold)),
            Text(talk.event, style: const TextStyle(fontSize: 16)),
            Text(talk.date, style: const TextStyle(fontSize: 14)),
          ],
        ));
  }
}

class SplashScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Center(
        child: const Text("Loading",
            style: TextStyle(fontSize: 24), textDirection: TextDirection.ltr));
  }
}

List<Widget> actions(BuildContext context) {
  final List<dynamic> actions = Provider.of<Voyager>(context)["actions"];
  if (actions == null || actions.isEmpty) {
    return null;
  }
  final widgets = <Widget>[];
  actions.forEach((dynamic action) {
    widgets.add(IconButton(
      icon: IconPlugin.fromHexValue(action["icon"]),
      onPressed: () {
        Navigator.of(context).pushNamed(action["target"]);
      },
    ));
  });
  return widgets;
}
27
likes
0
points
53
downloads

Publisher

verified publishervishna.dev

Weekly Downloads

Router and basic dependency injection library for Flutter. Define navigation paths in YAML and power them up with custom plugins.

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

flutter, provider, sprintf, yaml

More

Packages that depend on voyager