Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
8f91be5a
Commit
8f91be5a
authored
Sep 30, 2015
by
Ian Hickson
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #1405 from Hixie/dynamic-routes
Dynamic named routes
parents
32558478
f2b7dd62
Changes
10
Hide whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
153 additions
and
35 deletions
+153
-35
main.dart
examples/stocks/lib/main.dart
+21
-4
stock_data.dart
examples/stocks/lib/stock_data.dart
+7
-3
stock_home.dart
examples/stocks/lib/stock_home.dart
+12
-7
stock_list.dart
examples/stocks/lib/stock_list.dart
+4
-2
stock_row.dart
examples/stocks/lib/stock_row.dart
+7
-1
stock_symbol_viewer.dart
examples/stocks/lib/stock_symbol_viewer.dart
+57
-0
app.dart
packages/flutter/lib/src/fn3/app.dart
+5
-2
material.dart
packages/flutter/lib/src/fn3/material.dart
+11
-8
navigator.dart
packages/flutter/lib/src/fn3/navigator.dart
+28
-7
popup_menu.dart
packages/flutter/lib/src/fn3/popup_menu.dart
+1
-1
No files found.
examples/stocks/lib/main.dart
View file @
8f91be5a
...
...
@@ -22,6 +22,7 @@ part 'stock_list.dart';
part
'stock_menu.dart'
;
part
'stock_row.dart'
;
part
'stock_settings.dart'
;
part
'stock_symbol_viewer.dart'
;
part
'stock_types.dart'
;
class
StocksApp
extends
StatefulComponent
{
...
...
@@ -30,13 +31,14 @@ class StocksApp extends StatefulComponent {
class
StocksAppState
extends
State
<
StocksApp
>
{
final
List
<
Stock
>
_stocks
=
[];
final
Map
<
String
,
Stock
>
_stocks
=
<
String
,
Stock
>{};
final
List
<
String
>
_symbols
=
<
String
>[];
void
initState
(
BuildContext
context
)
{
super
.
initState
(
context
);
new
StockDataFetcher
((
StockData
data
)
{
setState
(()
{
data
.
appendTo
(
_stocks
);
data
.
appendTo
(
_stocks
,
_symbols
);
});
});
}
...
...
@@ -72,14 +74,29 @@ class StocksAppState extends State<StocksApp> {
}
}
RouteBuilder
_getRoute
(
String
name
)
{
List
<
String
>
path
=
name
.
split
(
'/'
);
if
(
path
[
0
]
!=
''
)
return
null
;
if
(
path
[
1
]
==
'stock'
)
{
if
(
path
.
length
!=
3
)
return
null
;
if
(
_stocks
.
containsKey
(
path
[
2
]))
return
(
navigator
,
route
)
=>
new
StockSymbolViewer
(
navigator
,
_stocks
[
path
[
2
]]);
return
null
;
}
return
null
;
}
Widget
build
(
BuildContext
context
)
{
return
new
App
(
title:
'Stocks'
,
theme:
theme
,
routes:
<
String
,
RouteBuilder
>{
'/'
:
(
navigator
,
route
)
=>
new
StockHome
(
navigator
,
_stocks
,
_optimismSetting
,
modeUpdater
),
'/'
:
(
navigator
,
route
)
=>
new
StockHome
(
navigator
,
_stocks
,
_
symbols
,
_
optimismSetting
,
modeUpdater
),
'/settings'
:
(
navigator
,
route
)
=>
new
StockSettings
(
navigator
,
_optimismSetting
,
_backupSetting
,
settingsUpdater
)
}
},
onGenerateRoute:
_getRoute
);
}
}
...
...
examples/stocks/lib/stock_data.dart
View file @
8f91be5a
...
...
@@ -42,9 +42,13 @@ class StockData {
StockData
(
this
.
_data
);
void
appendTo
(
List
<
Stock
>
stocks
)
{
for
(
List
<
String
>
fields
in
_data
)
stocks
.
add
(
new
Stock
.
fromFields
(
fields
));
void
appendTo
(
Map
<
String
,
Stock
>
stocks
,
List
<
String
>
symbols
)
{
for
(
List
<
String
>
fields
in
_data
)
{
Stock
stock
=
new
Stock
.
fromFields
(
fields
);
symbols
.
add
(
stock
.
symbol
);
stocks
[
stock
.
symbol
]
=
stock
;
}
symbols
.
sort
();
}
}
...
...
examples/stocks/lib/stock_home.dart
View file @
8f91be5a
...
...
@@ -9,10 +9,11 @@ typedef void ModeUpdater(StockMode mode);
const
Duration
_kSnackbarSlideDuration
=
const
Duration
(
milliseconds:
200
);
class
StockHome
extends
StatefulComponent
{
StockHome
(
this
.
navigator
,
this
.
stocks
,
this
.
stockMode
,
this
.
modeUpdater
);
StockHome
(
this
.
navigator
,
this
.
stocks
,
this
.
s
ymbols
,
this
.
s
tockMode
,
this
.
modeUpdater
);
final
NavigatorState
navigator
;
final
List
<
Stock
>
stocks
;
final
Map
<
String
,
Stock
>
stocks
;
final
List
<
String
>
symbols
;
final
StockMode
stockMode
;
final
ModeUpdater
modeUpdater
;
...
...
@@ -170,10 +171,9 @@ class StockHomeState extends State<StockHome> {
}
int
selectedTabIndex
=
0
;
List
<
String
>
portfolioSymbols
=
[
"AAPL"
,
"FIZZ"
,
"FIVE"
,
"FLAT"
,
"ZINC"
,
"ZNGA"
];
Iterable
<
Stock
>
_
filterByPortfolio
(
Iterable
<
Stock
>
stock
s
)
{
return
s
tocks
.
where
((
stock
)
=>
portfolioSymbols
.
contains
(
stock
.
symbol
)
);
Iterable
<
Stock
>
_
getStockList
(
Iterable
<
String
>
symbol
s
)
{
return
s
ymbols
.
map
((
symbol
)
=>
config
.
stocks
[
symbol
]
);
}
Iterable
<
Stock
>
_filterBySearchQuery
(
Iterable
<
Stock
>
stocks
)
{
...
...
@@ -191,20 +191,25 @@ class StockHomeState extends State<StockHome> {
stock
.
percentChange
=
100.0
*
(
1.0
/
stock
.
lastSale
);
stock
.
lastSale
+=
1.0
;
});
},
onOpen:
(
Stock
stock
)
{
config
.
navigator
.
pushNamed
(
'/stock/
${stock.symbol}
'
);
}
);
}
static
const
List
<
String
>
portfolioSymbols
=
const
<
String
>[
"AAPL"
,
"FIZZ"
,
"FIVE"
,
"FLAT"
,
"ZINC"
,
"ZNGA"
];
Widget
buildTabNavigator
()
{
return
new
TabNavigator
(
views:
<
TabNavigatorView
>[
new
TabNavigatorView
(
label:
const
TabLabel
(
text:
'MARKET'
),
builder:
(
BuildContext
context
)
=>
buildStockList
(
context
,
_filterBySearchQuery
(
config
.
stocks
))
builder:
(
BuildContext
context
)
=>
buildStockList
(
context
,
_filterBySearchQuery
(
_getStockList
(
config
.
symbols
)).
toList
(
))
),
new
TabNavigatorView
(
label:
const
TabLabel
(
text:
'PORTFOLIO'
),
builder:
(
BuildContext
context
)
=>
buildStockList
(
context
,
_filterBy
Portfolio
(
config
.
stocks
))
builder:
(
BuildContext
context
)
=>
buildStockList
(
context
,
_filterBy
SearchQuery
(
_getStockList
(
portfolioSymbols
)).
toList
(
))
)
],
selectedIndex:
selectedTabIndex
,
...
...
examples/stocks/lib/stock_list.dart
View file @
8f91be5a
...
...
@@ -7,10 +7,11 @@ part of stocks;
typedef
void
StockActionListener
(
Stock
stock
);
class
StockList
extends
StatelessComponent
{
StockList
({
Key
key
,
this
.
stocks
,
this
.
onAction
})
:
super
(
key:
key
);
StockList
({
Key
key
,
this
.
stocks
,
this
.
onAction
,
this
.
onOpen
})
:
super
(
key:
key
);
final
List
<
Stock
>
stocks
;
final
StockActionListener
onAction
;
final
StockActionListener
onOpen
;
Widget
build
(
BuildContext
context
)
{
return
new
Material
(
...
...
@@ -21,7 +22,8 @@ class StockList extends StatelessComponent {
itemBuilder:
(
BuildContext
context
,
Stock
stock
)
{
return
new
StockRow
(
stock:
stock
,
onPressed:
()
{
onAction
(
stock
);
}
onPressed:
()
{
onAction
(
stock
);
},
onLongPressed:
()
{
onOpen
(
stock
);
}
);
}
)
...
...
examples/stocks/lib/stock_row.dart
View file @
8f91be5a
...
...
@@ -5,10 +5,15 @@
part of
stocks
;
class
StockRow
extends
StatelessComponent
{
StockRow
({
Stock
stock
,
this
.
onPressed
})
:
this
.
stock
=
stock
,
super
(
key:
new
Key
(
stock
.
symbol
));
StockRow
({
Stock
stock
,
this
.
onPressed
,
this
.
onLongPressed
})
:
this
.
stock
=
stock
,
super
(
key:
new
Key
(
stock
.
symbol
));
final
Stock
stock
;
final
GestureTapListener
onPressed
;
final
GestureLongPressListener
onLongPressed
;
static
const
double
kHeight
=
79.0
;
...
...
@@ -39,6 +44,7 @@ class StockRow extends StatelessComponent {
return
new
GestureDetector
(
onTap:
onPressed
,
onLongPress:
onLongPressed
,
child:
new
InkWell
(
child:
new
Container
(
padding:
const
EdgeDims
(
16.0
,
16.0
,
20.0
,
16.0
),
...
...
examples/stocks/lib/stock_symbol_viewer.dart
0 → 100644
View file @
8f91be5a
// Copyright 2015 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
part of
stocks
;
class
StockSymbolViewer
extends
StatefulComponent
{
StockSymbolViewer
(
this
.
navigator
,
this
.
stock
);
final
NavigatorState
navigator
;
final
Stock
stock
;
StockSymbolViewerState
createState
()
=>
new
StockSymbolViewerState
();
}
class
StockSymbolViewerState
extends
State
<
StockSymbolViewer
>
{
Widget
build
(
BuildContext
context
)
{
String
lastSale
=
"
\$
${config.stock.lastSale.toStringAsFixed(2)}
"
;
String
changeInPrice
=
"
${config.stock.percentChange.toStringAsFixed(2)}
%"
;
if
(
config
.
stock
.
percentChange
>
0
)
changeInPrice
=
"+"
+
changeInPrice
;
TextStyle
headings
=
Theme
.
of
(
context
).
text
.
body2
;
return
new
Scaffold
(
toolbar:
new
ToolBar
(
left:
new
IconButton
(
icon:
'navigation/arrow_back'
,
onPressed:
config
.
navigator
.
pop
),
center:
new
Text
(
'
${config.stock.name}
(
${config.stock.symbol}
)'
)
),
body:
new
Material
(
type:
MaterialType
.
canvas
,
child:
new
Block
([
new
Container
(
padding:
new
EdgeDims
.
all
(
20.0
),
child:
new
Column
([
new
Text
(
'Last Sale'
,
style:
headings
),
new
Text
(
'
${lastSale}
(
${changeInPrice}
)'
),
new
Container
(
height:
8.0
),
new
Text
(
'Market Cap'
,
style:
headings
),
new
Text
(
'
${config.stock.marketCap}
'
),
],
alignItems:
FlexAlignItems
.
stretch
)
)
])
)
);
}
}
packages/flutter/lib/src/fn3/app.dart
View file @
8f91be5a
...
...
@@ -30,12 +30,14 @@ class App extends StatefulComponent {
Key
key
,
this
.
title
,
this
.
theme
,
this
.
routes
this
.
routes
,
this
.
onGenerateRoute
}):
super
(
key:
key
);
final
String
title
;
final
ThemeData
theme
;
final
Map
<
String
,
RouteBuilder
>
routes
;
final
RouteGenerator
onGenerateRoute
;
AppState
createState
()
=>
new
AppState
();
}
...
...
@@ -76,7 +78,8 @@ class AppState extends State<App> {
title:
config
.
title
,
child:
new
Navigator
(
key:
_navigator
,
routes:
config
.
routes
routes:
config
.
routes
,
onGenerateRoute:
config
.
onGenerateRoute
)
)
)
...
...
packages/flutter/lib/src/fn3/material.dart
View file @
8f91be5a
...
...
@@ -62,14 +62,17 @@ class Material extends StatelessComponent {
}
}
// TODO(abarth): This should use AnimatedContainer.
return
new
Container
(
decoration:
new
BoxDecoration
(
backgroundColor:
getBackgroundColor
(
context
),
borderRadius:
edges
[
type
],
boxShadow:
level
==
0
?
null
:
shadows
[
level
],
shape:
type
==
MaterialType
.
circle
?
Shape
.
circle
:
Shape
.
rectangle
),
child:
contents
return
new
DefaultTextStyle
(
style:
Theme
.
of
(
context
).
text
.
body1
,
child:
new
Container
(
decoration:
new
BoxDecoration
(
backgroundColor:
getBackgroundColor
(
context
),
borderRadius:
edges
[
type
],
boxShadow:
level
==
0
?
null
:
shadows
[
level
],
shape:
type
==
MaterialType
.
circle
?
Shape
.
circle
:
Shape
.
rectangle
),
child:
contents
)
);
}
}
packages/flutter/lib/src/fn3/navigator.dart
View file @
8f91be5a
...
...
@@ -9,15 +9,24 @@ import 'package:sky/src/fn3/framework.dart';
import
'package:sky/src/fn3/transitions.dart'
;
typedef
Widget
RouteBuilder
(
NavigatorState
navigator
,
Route
route
);
typedef
RouteBuilder
RouteGenerator
(
String
name
);
typedef
void
RouteStateCallback
(
RouteState
route
);
typedef
void
NotificationCallback
(
);
class
Navigator
extends
StatefulComponent
{
Navigator
({
this
.
routes
,
Key
key
})
:
super
(
key:
key
)
{
Navigator
({
Key
key
,
this
.
routes
,
this
.
onGenerateRoute
,
// you need to implement this if you pushNamed() to names that might not be in routes.
this
.
onUnknownRoute
// 404 generator. You only need to implement this if you have a way to navigate to arbitrary names.
})
:
super
(
key:
key
)
{
// To use a navigator, you must at a minimum define the route with the name '/'.
assert
(
routes
.
containsKey
(
'/'
));
}
final
Map
<
String
,
RouteBuilder
>
routes
;
final
RouteGenerator
onGenerateRoute
;
final
RouteBuilder
onUnknownRoute
;
NavigatorState
createState
()
=>
new
NavigatorState
();
}
...
...
@@ -47,9 +56,17 @@ class NavigatorState extends State<Navigator> {
}
void
pushNamed
(
String
name
)
{
PageRoute
route
=
new
PageRoute
(
config
.
routes
[
name
]);
assert
(
route
!=
null
);
push
(
route
);
RouteBuilder
builder
;
if
(!
config
.
routes
.
containsKey
(
name
))
{
assert
(
config
.
onGenerateRoute
!=
null
);
builder
=
config
.
onGenerateRoute
(
name
);
}
else
{
builder
=
config
.
routes
[
name
];
}
if
(
builder
==
null
)
builder
=
config
.
onUnknownRoute
;
// 404!
assert
(
builder
!=
null
);
// 404 getting your 404!
push
(
new
PageRoute
(
builder
));
}
void
push
(
Route
route
)
{
...
...
@@ -172,6 +189,10 @@ abstract class Route {
/// NavigatorState.pushState().
///
/// Set hasContent to false if you have nothing useful to return from build().
///
/// modal must be false if hasContent is false, since otherwise any
/// interaction with the system at all would imply that the current route is
/// popped, which would be pointless.
bool
get
hasContent
=>
true
;
/// If ephemeral is true, then to explicitly pop the route you have to use
...
...
@@ -196,6 +217,7 @@ abstract class Route {
/// popped.
///
/// ephemeral must be true if modal is false.
/// hasContent must be true if modal is true.
bool
get
modal
=>
true
;
/// If opaque is true, then routes below this one will not be built or painted
...
...
@@ -253,8 +275,6 @@ class PageRoute extends Route {
}
}
typedef
void
RouteStateCallback
(
RouteState
route
);
class
RouteState
extends
Route
{
RouteState
({
this
.
route
,
this
.
owner
,
this
.
callback
});
...
...
@@ -262,6 +282,8 @@ class RouteState extends Route {
State
owner
;
RouteStateCallback
callback
;
bool
get
hasContent
=>
false
;
bool
get
modal
=>
false
;
bool
get
opaque
=>
false
;
void
didPop
([
dynamic
result
])
{
...
...
@@ -271,6 +293,5 @@ class RouteState extends Route {
super
.
didPop
(
result
);
}
bool
get
hasContent
=>
false
;
Widget
build
(
Key
key
,
NavigatorState
navigator
)
=>
null
;
}
packages/flutter/lib/src/fn3/popup_menu.dart
View file @
8f91be5a
...
...
@@ -167,7 +167,7 @@ class MenuRoute extends Route {
return
result
;
}
bool
get
ephemeral
=>
true
;
bool
get
ephemeral
=>
false
;
// we could make this true, but then we'd have to use popRoute(), not pop(), in menus
bool
get
modal
=>
true
;
Duration
get
transitionDuration
=>
_kMenuDuration
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment