frap 0.2.0 → 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 0a94c44eaae2cb515d4ae619672a6e2eed5d3e352c9ccceb60e49bc6123f2d2b
4
- data.tar.gz: 8e3f7a0d93b24ac0bb3ffdb5b2963cbb09e2c83c26e33d16970b88f194cc382b
3
+ metadata.gz: 2113fe87e979c5dcc6f1068901f9addbb33398ef7bbc54d138d87c37b3813145
4
+ data.tar.gz: 75f07d7ef133da72c45d1086b28e3054020a6aadeb889a5dc06ad90a2598a9f5
5
5
  SHA512:
6
- metadata.gz: e955d2a12647e5ba589f6d88baa5aa68c1105d4cb3618836ec9e60299286fede785f4d0fb190c47d516f4295a36409c6937e70e606ebebdb6593ce0ef706f96a
7
- data.tar.gz: ad972c11753fa6ecbaa24cb81c147d657650356a615909b6dd254678108daec5182643aafb23c596a50f9964f2738fd745f7afcd263eaf9428d9360b31b1d8c9
6
+ metadata.gz: 2199c30717694e927e1275b0c4c661302b7e1e6f04db69ba06b05f4cee4486aaf440340f0ad7aa85b96a364944d9f193c63dc23fd3f6d350c482f2fd5bb77e92
7
+ data.tar.gz: 93bdd37d1101b04848a6bdcd86cf69c89c2806548c53f2c54c07f0546d2b5374cc798dab578ecb267741e3021da42eeda80570f5ddfdb7210939fda28623e72d
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- frap (0.2.0)
4
+ frap (0.2.1)
5
5
  thor (~> 0.20.3)
6
6
 
7
7
  GEM
data/README.md CHANGED
@@ -32,6 +32,30 @@ This will create a new Parent directory for the Rails and Flutter App.
32
32
  |__ my_app_server
33
33
  |__ my_app_ui
34
34
  ```
35
+ Generate a Rails and Flutter Resource from the app route directory `/my_app`, **currently does NOT support references, please open an ISSUE for broken data types**
36
+ `frap generate resource post -a title:string body:text`
37
+
38
+ The next step is to implement your Rails controller method for index action and run the migrations:
39
+ ```
40
+ cd my_app/my_app_server
41
+ rails db:migrate
42
+ ```
43
+ You can then edit the `app/constrollers/posts_controller.rb`:
44
+ ```ruby
45
+ class PostsController < ApplicationController
46
+ def index
47
+ render json: { posts: Post.all.as_json }, status: :ok
48
+ end
49
+ end
50
+ ```
51
+ Next fire up Rails and Flutter (you may need to start up an emulator, just follow the terminal output:
52
+ ```bash
53
+ cd my_app/my_app_server
54
+ rails s
55
+
56
+ cd my_app/my_app_ui
57
+ flutter run
58
+ ```
35
59
 
36
60
 
37
61
  ## Motivation
@@ -4,6 +4,7 @@ require 'frap/create_resource'
4
4
  require 'frap/commands/generate'
5
5
  require 'frap/generators/config'
6
6
  require 'frap/generators/flutter_config'
7
+ require 'frap/generators/flutter_resource'
7
8
  require 'thor'
8
9
  require 'yaml'
9
10
 
@@ -17,15 +17,16 @@ module Frap
17
17
  private
18
18
 
19
19
  def generate_rails_resource
20
- Dir.chdir("#{working_dir}/#{rails_app}")
21
-
20
+ Dir.chdir("#{working_dir}/#{rails_app_dir}")
22
21
  system("rails generate resource #{name} #{fields}")
22
+ Dir.chdir("#{working_dir}")
23
23
  end
24
24
 
25
25
  def generate_flutter_resource
26
- Dir.chdir("#{working_dir}/#{flutter_app}")
27
-
28
- puts "TODO: frap g flutter resource #{name} #{fields}"
26
+ flutter_fields = options[:attributes] || 'name:string'
27
+ Frap::Generators::FlutterResource.new(
28
+ [name.capitalize, flutter_app_dir, flutter_fields]
29
+ ).invoke(:configure_directories)
29
30
  end
30
31
 
31
32
  def fields
@@ -51,11 +52,11 @@ module Frap
51
52
  @config ||= YAML.load(File.read('config.yml'))
52
53
  end
53
54
 
54
- def flutter_app
55
+ def flutter_app_dir
55
56
  config['flutter_app']
56
57
  end
57
58
 
58
- def rails_app
59
+ def rails_app_dir
59
60
  config['rails_app']
60
61
  end
61
62
  end
@@ -28,6 +28,8 @@ module Frap
28
28
 
29
29
  def create_files
30
30
  template('main.dart.erb', "#{lib_directory}/main.dart")
31
+ template('src/constants/app_constants.dart.erb', "#{src_directory}/constants/app_constants.dart")
32
+ template('src/resources/repository.dart.erb', "#{src_directory}/resources/repository.dart")
31
33
  template('src/app.dart.erb', "#{src_directory}/app.dart")
32
34
  template('src/animations/slide_right_route.dart.erb', "#{src_directory}/animations/slide_right_route.dart")
33
35
  template('src/config/router.dart.erb', "#{src_directory}/config/router.dart")
@@ -44,7 +46,7 @@ module Frap
44
46
  def setup_pages
45
47
  inject_into_file("#{src_directory}/config/router.dart", home_router, after: /^.*switch \(settings.name\) \{$/)
46
48
  inject_into_file("#{src_directory}/constants/pages_list.dart", home_route, after: /const List<Page> pages = const <Page>\[.*$/)
47
- append_to_file("#{src_directory}/constants/routing.dart", "const String HomeScreenRoute = '/';")
49
+ append_to_file("#{src_directory}/constants/routing.dart", "const String HomeScreenRoute = '/';\n")
48
50
  end
49
51
 
50
52
  private
@@ -65,7 +67,8 @@ module Frap
65
67
  %Q(
66
68
  dio: ^2.1.13
67
69
  rxdart: ^0.22.0
68
- bloc_pattern: ^2.2.3)
70
+ bloc_pattern: ^2.2.3
71
+ http: ^0.12.0+2)
69
72
  end
70
73
 
71
74
  def home_router
@@ -76,7 +79,8 @@ module Frap
76
79
 
77
80
  def home_route
78
81
  %Q(
79
- const Page(title: 'Home', icon: Icons.home, route: HomeScreenRoute),)
82
+ const Page(title: 'Home', icon: Icons.home, route: HomeScreenRoute),
83
+ )
80
84
  end
81
85
  end
82
86
  end
@@ -1,3 +1,5 @@
1
+ require 'active_support/inflector'
2
+
1
3
  module Frap
2
4
  module Generators
3
5
  class FlutterResource < Thor::Group
@@ -5,37 +7,82 @@ module Frap
5
7
 
6
8
  desc 'Generate Flutter Config files'
7
9
  argument :name
8
- argument :folder_name
9
-
10
+ argument :flutter_app_dir
11
+ argument :fields
10
12
  def self.source_root
11
13
  File.dirname(__FILE__) + '/templates/dart'
12
14
  end
13
15
 
14
16
  def configure_directories
15
- inject_into_file("#{working_directory}/pubspec.yaml", pub_files, after: /^dependencies:.*$/)
16
- remove_file("#{lib_directory}/main.dart")
17
17
  invoke :create_directories
18
18
  end
19
19
 
20
20
  def create_directories
21
- empty_directory("#{lib_directory}/src/home")
21
+ empty_directory("#{lib_directory}/src/screens/#{lower_name}")
22
+
22
23
  invoke :create_files
23
24
  end
24
25
 
25
26
  def create_files
26
- template('main.dart.erb', "#{lib_directory}/main.dart")
27
- template('src/app_bloc.dart.erb', "#{src_directory}/app_bloc.dart")
28
- template('src/app_module.dart.erb', "#{src_directory}/app_module.dart")
29
- template('src/app_widget.dart.erb', "#{src_directory}/app_widget.dart")
30
- template('src/home/home_bloc.dart.erb', "#{src_directory}/home/home_bloc.dart")
31
- template('src/home/home_module.dart.erb', "#{src_directory}/home/home_module.dart")
32
- template('src/home/home_page.dart.erb', "#{src_directory}/home/home_page.dart")
27
+ @name_capitalized_plural = name_capitalize_pluralize
28
+ @name_capitalized_single = name_capitalized_single
29
+ @name_downcased_plural = name_downcase_pluralize
30
+ @lower_name = lower_name
31
+ @field_types = build_fields
32
+ @field_names = fields.keys
33
+ template('src/screens/base_index.dart.erb', "#{screen_path}/#{lower_name}_index_screen.dart")
34
+ template('src/screens/base_bottom_navigation.dart.erb', "#{screen_path}/#{lower_name}_show_screen.dart")
35
+ template('src/blocs/base_block.dart.erb', "#{src_directory}/blocs/#{@name_downcased_plural}_bloc.dart")
36
+ template('src/models/base_model.dart.erb', "#{src_directory}/models/#{@name_downcased_plural}.dart")
37
+ template('src/resources/base_api_provider.dart.erb', "#{src_directory}/resources/#{lower_name}_api_provider.dart")
38
+ invoke :connect_widgets
39
+ end
40
+
41
+ def connect_widgets
42
+ inject_into_file("#{src_directory}/config/router.dart", router_packages, after: /^import 'package:flutter\/material.dart';$/)
43
+ inject_into_file("#{src_directory}/config/router.dart", show_screen_router, after: /^.*switch \(settings.name\) \{$/)
44
+ inject_into_file("#{src_directory}/config/router.dart", index_screen_router, after: /^.*switch \(settings.name\) \{$/)
45
+ inject_into_file("#{src_directory}/constants/pages_list.dart", index_screen_route, after: /const List<Page> pages = const <Page>\[.*$/)
46
+ inject_into_file("#{src_directory}/resources/repository.dart", repository_packages, after: /^import 'dart:async';$/)
47
+ inject_into_file("#{src_directory}/resources/repository.dart", repository_body, after: /^class Repository \{$/)
48
+ append_to_file("#{src_directory}/constants/routing.dart", "const String #{name}IndexScreenRoute = '/#{lower_name.pluralize }'; \n")
49
+ append_to_file("#{src_directory}/constants/routing.dart", "const String #{name}ShowScreenRoute = '/#{lower_name.singularize}';\n")
50
+ # Here we will make sure all imports are handled:
51
+ # Import new resource into routes route and constants
52
+ # Index page with bottom floating button for adding
53
+ # build detail screen with bottom navigations
54
+ # Link navigation buttons to Edit and back to list and delete
33
55
  end
34
56
 
35
57
  private
36
58
 
59
+ def build_fields
60
+ return unless fields
61
+
62
+ fields.map do |key, value|
63
+ case value
64
+ when 'text'
65
+ "String #{key}"
66
+ when 'string'
67
+ "String #{key}"
68
+ when 'integer'
69
+ "int #{key}"
70
+ when 'float'
71
+ "double #{key}"
72
+ when 'bigint'
73
+ "BigInt #{key}"
74
+ when 'datetime'
75
+ "DateTime #{key}"
76
+ when 'boolean'
77
+ "bool #{key}"
78
+ else
79
+ "var #{key}"
80
+ end
81
+ end
82
+ end
83
+
37
84
  def working_directory
38
- "#{destination_root}/#{folder_name}"
85
+ "#{destination_root}/#{flutter_app_dir}"
39
86
  end
40
87
 
41
88
  def lib_directory
@@ -46,11 +93,64 @@ module Frap
46
93
  "#{lib_directory}/src"
47
94
  end
48
95
 
49
- def pub_files
96
+ def screen_path
97
+ "#{src_directory}/screens/#{lower_name}"
98
+ end
99
+
100
+ def index_screen_router
101
+ %Q(
102
+ case #{name}IndexScreenRoute:
103
+ return SlideRightRoute(widget:#{name}IndexScreen());)
104
+ end
105
+
106
+ def index_screen_route
50
107
  %Q(
51
- dio: ^2.1.13
52
- rxdart: ^0.22.0
53
- bloc_pattern: ^2.2.3)
108
+ const Page(title: '#{name.pluralize}', icon: Icons.home, route: #{name}IndexScreenRoute),)
109
+ end
110
+
111
+ def show_screen_router
112
+ %Q(
113
+ case #{name}ShowScreenRoute:
114
+ return SlideRightRoute(widget:#{name}ShowScreen());)
115
+ end
116
+
117
+ def show_screen_route
118
+ %Q(
119
+ const Page(title: '#{name}', icon: Icons.home, route: #{name}ShowScreenRoute),)
120
+ end
121
+
122
+ def lower_name
123
+ name.downcase.singularize
124
+ end
125
+
126
+ def name_capitalized_single
127
+ name.capitalize.singularize
128
+ end
129
+
130
+ def name_capitalize_pluralize
131
+ name.capitalize.pluralize
132
+ end
133
+
134
+ def name_downcase_pluralize
135
+ name.downcase.pluralize
136
+ end
137
+
138
+ def router_packages
139
+ %Q(
140
+ import 'package:#{flutter_app_dir}/src/screens/#{lower_name}/#{lower_name}_index_screen.dart';
141
+ import 'package:#{flutter_app_dir}/src/screens/#{lower_name}/#{lower_name}_show_screen.dart';)
142
+ end
143
+
144
+ def repository_body
145
+ %Q(
146
+ final #{lower_name}ApiProvider = #{name_capitalized_single}ApiProvider();
147
+ Future<#{name_capitalize_pluralize}> fetchAll#{name_capitalize_pluralize}() => #{lower_name}ApiProvider.fetchAll#{name_capitalize_pluralize}();)
148
+ end
149
+
150
+ def repository_packages
151
+ %Q(
152
+ import 'package:#{flutter_app_dir}/src/resources/#{lower_name}_api_provider.dart';
153
+ import 'package:#{flutter_app_dir}/src/models/#{name_downcase_pluralize}.dart';)
54
154
  end
55
155
  end
56
156
  end
@@ -5,10 +5,9 @@ import 'package:<%= folder_name %>/src/config/router.dart' as router;
5
5
  import 'package:<%= folder_name %>/src/constants/routing.dart';
6
6
 
7
7
  class App extends StatelessWidget {
8
- @override
9
-
10
8
  static const String _title = '<%= folder_name %>';
11
9
 
10
+ @override
12
11
  Widget build(BuildContext context) {
13
12
  return MaterialApp(
14
13
  title: _title,
@@ -0,0 +1,21 @@
1
+ import 'package:rxdart/rxdart.dart';
2
+ import 'package:<%= flutter_app_dir %>/src/resources/repository.dart';
3
+ import 'package:<%= flutter_app_dir %>/src/models/<%= @name_downcased_plural %>.dart';
4
+
5
+ class <%= @name_capitalized_plural %>Bloc {
6
+ final _repository = Repository();
7
+ final _<%= @name_downcased_plural %>Fetcher = PublishSubject<<%= @name_capitalized_plural %>>();
8
+
9
+ Observable<<%= @name_capitalized_plural %>> get all<%= @name_capitalized_plural %> => _<%= @name_downcased_plural %>Fetcher.stream;
10
+
11
+ fetchAll<%= @name_capitalized_plural %>() async {
12
+ <%= @name_capitalized_plural %> <%= @name_downcased_plural %> = await _repository.fetchAll<%= @name_capitalized_plural %>();
13
+ _<%= @name_downcased_plural%>Fetcher.sink.add(<%= @name_downcased_plural %>);
14
+ }
15
+
16
+ dispose() {
17
+ _<%= @name_downcased_plural %>Fetcher.close();
18
+ }
19
+ }
20
+
21
+ final bloc = <%= @name_capitalized_plural %>Bloc();
@@ -1,5 +1,4 @@
1
1
  import 'package:flutter/material.dart';
2
-
3
2
  import 'package:<%= folder_name %>/src/animations/slide_right_route.dart';
4
3
  import 'package:<%= folder_name %>/src/constants/routing.dart';
5
4
  import 'package:<%= folder_name %>/src/screens/home_screen.dart';
@@ -0,0 +1 @@
1
+ const String RootUrl = 'http://10.0.2.2:3000';
@@ -0,0 +1,32 @@
1
+ class <%= @name_capitalized_plural %> {
2
+ int _id;
3
+ List<<%= @name_capitalized_single %>> _results = [];
4
+
5
+ <%= @name_capitalized_plural %>.fromJson(Map<String, dynamic> parsedJson) {
6
+ List<<%= @name_capitalized_single %>> temp = [];
7
+ for (int i = 0; i < parsedJson['<%= @name_downcased_plural %>'].length; i++) {
8
+ <%= @name_capitalized_single %> result = <%= @name_capitalized_single %>.fromJson(parsedJson['<%= @name_downcased_plural %>'][i]);
9
+ temp.add(result);
10
+ }
11
+ _results = temp;
12
+ }
13
+
14
+ List<<%= @name_capitalized_single %>> get results => _results;
15
+ }
16
+
17
+ class <%= @name_capitalized_single %> {
18
+ <% @field_types.each do |field| %>final <%= field %>;
19
+ <% end %>
20
+
21
+ <%= @name_capitalized_single %>({
22
+ <% @field_names.each do |field| %>this.<%= field %>,
23
+ <% end %>
24
+ });
25
+
26
+ factory <%= @name_capitalized_single %>.fromJson(Map<String, dynamic> json) {
27
+ return <%= @name_capitalized_single %>(
28
+ <% @field_names.each do |field| %><%= field %>: json['<%= field %>'],
29
+ <% end %>
30
+ );
31
+ }
32
+ }
@@ -0,0 +1,18 @@
1
+ import 'dart:async';
2
+ import 'package:http/http.dart' as http;
3
+ import 'dart:convert';
4
+ import 'package:<%= flutter_app_dir %>/src/models/<%= @name_downcased_plural %>.dart';
5
+ import 'package:<%= flutter_app_dir %>/src/constants/app_constants.dart';
6
+
7
+ class <%= @name_capitalized_single %>ApiProvider {
8
+ Future<<%= @name_capitalized_plural %>> fetchAll<%= @name_capitalized_plural %>() async {
9
+ final response =
10
+ await http.get("${RootUrl}/<%= @name_downcased_plural %>");
11
+
12
+ if (response.statusCode == 200) {
13
+ return <%= @name_capitalized_plural %>.fromJson(json.decode(response.body));
14
+ } else {
15
+ throw Exception('Failed to load <%= @name_capitalized_plural %>');
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,4 @@
1
+ import 'dart:async';
2
+
3
+ class Repository {
4
+ }
@@ -1,5 +1,4 @@
1
1
  import 'package:flutter/material.dart';
2
- import 'package:<%= folder_name %>/src/constants/routing.dart';
3
2
  import 'package:<%= folder_name %>/src/widgets/base_app_bar.dart';
4
3
  import 'package:<%= folder_name %>/src/widgets/popup_menu_widget.dart';
5
4
 
@@ -0,0 +1,57 @@
1
+ import 'package:flutter/material.dart';
2
+ import 'package:<%= flutter_app_dir %>/src/widgets/base_app_bar.dart';
3
+ import 'package:<%= flutter_app_dir %>/src/widgets/popup_menu_widget.dart';
4
+ import 'package:<%= flutter_app_dir %>/src/screens/<%= name.downcase %>/<%= name.downcase %>_index_screen.dart';
5
+
6
+ class <%= name %>ShowScreen extends StatefulWidget {
7
+ <%= name %>ShowScreen({Key key}) : super(key: key);
8
+
9
+ @override
10
+ _<%= name %>ShowScreenState createState() => _<%= name %>ShowScreenState();
11
+ }
12
+
13
+ class _<%= name %>ShowScreenState extends State<<%= name %>ShowScreen> {
14
+ int _selectedIndex = 1;
15
+
16
+ final List<Widget> _widgets = <Widget>[
17
+ <%= name %>IndexScreen(),
18
+ ];
19
+
20
+ void _onItemTapped(int index) {
21
+ setState(() {
22
+ _selectedIndex = index;
23
+ });
24
+ }
25
+
26
+ @override
27
+
28
+ Widget build(BuildContext context) {
29
+ return Scaffold(
30
+ appBar: BaseAppBar(
31
+ title: Text('<%= name %>'),
32
+ appBar: AppBar(),
33
+ widgets: <Widget>[
34
+ PopupMenuWidget(),
35
+ ],
36
+ ),
37
+ body: Center(
38
+ child: Text('<%= name %>'),
39
+ ),
40
+ bottomNavigationBar: BottomNavigationBar(
41
+ items: const <BottomNavigationBarItem>[
42
+ BottomNavigationBarItem(
43
+ icon: Icon(Icons.dashboard),
44
+ title: Text('Back'),
45
+ ),
46
+ BottomNavigationBarItem(
47
+ icon: Icon(Icons.monetization_on),
48
+ title: Text('Edit'),
49
+ ),
50
+ ],
51
+ currentIndex: _selectedIndex,
52
+ selectedItemColor: Colors.green,
53
+ onTap: _onItemTapped,
54
+ ),
55
+ );
56
+ }
57
+ }
@@ -0,0 +1,72 @@
1
+ import 'package:flutter/material.dart';
2
+ import 'package:<%= flutter_app_dir %>/src/widgets/base_app_bar.dart';
3
+ import 'package:<%= flutter_app_dir %>/src/widgets/popup_menu_widget.dart';
4
+ import 'package:<%= flutter_app_dir %>/src/models/<%= @name_downcased_plural %>.dart';
5
+ import 'package:<%= flutter_app_dir %>/src/blocs/<%= @name_downcased_plural %>_bloc.dart';
6
+
7
+ class <%= @name_capitalized_single %>IndexScreen extends StatefulWidget {
8
+ @override
9
+ State<StatefulWidget> createState() {
10
+ return <%= @name_capitalized_single %>IndexScreenState();
11
+ }
12
+ }
13
+
14
+ class <%= @name_capitalized_single %>IndexScreenState extends State<<%= @name_capitalized_single %>IndexScreen> {
15
+ @override
16
+ void initState() {
17
+ super.initState();
18
+ bloc.fetchAll<%= @name_capitalized_plural %>();
19
+ }
20
+
21
+ // @override
22
+ // void dispose() {
23
+ // bloc.dispose();
24
+ // super.dispose();
25
+ // }
26
+
27
+ Widget build(BuildContext context) {
28
+ return Scaffold(
29
+ appBar: BaseAppBar(
30
+ title: Text('<%= @name_capitalized_single %>'),
31
+ appBar: AppBar(),
32
+ widgets: <Widget>[
33
+ PopupMenuWidget(),
34
+ ],
35
+ ),
36
+ body: StreamBuilder(
37
+ stream: bloc.all<%= @name_capitalized_plural %>,
38
+ builder: (context, AsyncSnapshot<<%= @name_capitalized_plural %>> snapshot) {
39
+ if (snapshot.hasData) {
40
+ return buildList(snapshot);
41
+ } else if (snapshot.hasError) {
42
+ return Text(snapshot.error.toString());
43
+ }
44
+ return Center(child: CircularProgressIndicator());
45
+ },
46
+ ),
47
+ floatingActionButton: FloatingActionButton(
48
+ elevation: 0.0,
49
+ child: Icon(Icons.add),
50
+ onPressed: (){ }
51
+ ),
52
+ );
53
+ }
54
+
55
+ Widget buildList(AsyncSnapshot<<%= @name_capitalized_plural %>> snapshot) {
56
+ return ListView.builder(
57
+ itemCount: snapshot.data.results.length,
58
+ itemBuilder: (BuildContext context, int index) {
59
+ return Card(
60
+ child: ListTile(
61
+ leading: Icon(Icons.map),
62
+ title: Text('TODO EDIT: snapshot.data.results[index].your_field_name'),
63
+ subtitle: Text('TODO EDIT: snapshot.data.results[index].your_field_name.toString()'),
64
+ trailing: Icon(Icons.more_vert),
65
+ onTap: () {},
66
+ )
67
+ );
68
+ },
69
+ );
70
+ }
71
+ }
72
+
@@ -1,6 +1,5 @@
1
1
  import 'package:flutter/material.dart';
2
2
  import 'package:<%= folder_name %>/src/constants/pages_list.dart';
3
- import 'package:<%= folder_name %>/src/constants/routing.dart';
4
3
 
5
4
  class PopupMenuWidget extends StatefulWidget {
6
5
  @override
@@ -8,12 +7,11 @@ class PopupMenuWidget extends StatefulWidget {
8
7
  }
9
8
 
10
9
  class _PopupMenuWidgetState extends State<PopupMenuWidget> {
11
- @override
12
-
13
10
  _onSelect(Page page) {
14
11
  Navigator.pushNamed(context, page.route);
15
12
  }
16
13
 
14
+ @override
17
15
  Widget build(BuildContext context) {
18
16
  return PopupMenuButton<Page>(
19
17
  onSelected: _onSelect,
@@ -1,3 +1,3 @@
1
1
  module Frap
2
- VERSION = "0.2.0"
2
+ VERSION = "0.2.1"
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: frap
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - James Gascoigne - Taylor
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-07-29 00:00:00.000000000 Z
11
+ date: 2019-08-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: thor
@@ -115,10 +115,20 @@ files:
115
115
  - lib/frap/generators/templates/dart/main.dart.erb
116
116
  - lib/frap/generators/templates/dart/src/animations/slide_right_route.dart.erb
117
117
  - lib/frap/generators/templates/dart/src/app.dart.erb
118
+ - lib/frap/generators/templates/dart/src/blocs/base_block.dart.erb
118
119
  - lib/frap/generators/templates/dart/src/config/router.dart.erb
120
+ - lib/frap/generators/templates/dart/src/constants/app_constants.dart.erb
119
121
  - lib/frap/generators/templates/dart/src/constants/pages_list.dart.erb
120
122
  - lib/frap/generators/templates/dart/src/constants/routing.dart.erb
123
+ - lib/frap/generators/templates/dart/src/models/base_model.dart.erb
124
+ - lib/frap/generators/templates/dart/src/resources/base_api_provider.dart.erb
125
+ - lib/frap/generators/templates/dart/src/resources/repository.dart.erb
121
126
  - lib/frap/generators/templates/dart/src/screens/base.dart.erb
127
+ - lib/frap/generators/templates/dart/src/screens/base_bottom_navigation.dart.erb
128
+ - lib/frap/generators/templates/dart/src/screens/base_index.dart.erb
129
+ - lib/frap/generators/templates/dart/src/screens/edit_class.dart.erb
130
+ - lib/frap/generators/templates/dart/src/screens/index_class.dart.erb
131
+ - lib/frap/generators/templates/dart/src/screens/show_class.dart.erb
122
132
  - lib/frap/generators/templates/dart/src/screens/undefined_route_screen.dart.erb
123
133
  - lib/frap/generators/templates/dart/src/widgets/base_app_bar.dart.erb
124
134
  - lib/frap/generators/templates/dart/src/widgets/popup_menu_widget.dart.erb