Compare commits
67 Commits
Author | SHA1 | Date |
---|---|---|
Michael Pfaff | 9956b24eb2 | |
Michael Pfaff | 45949890cc | |
Michael Pfaff | 8e99c535bd | |
Luke | 30ae4378df | |
Luke Freeman | 937afe9757 | |
Luke Pighetti | aca29a1e34 | |
Luke Freeman | 337d864b62 | |
Luke Freeman | 3a1a20e03b | |
Luke Freeman | 53e1c97960 | |
Luke Freeman | 16b09f760c | |
Luke Freeman | 624626c85d | |
Luke Freeman | 2c06f63e19 | |
Luke Freeman | 2676006fe3 | |
Luke Freeman | df3434d599 | |
Luke Freeman | fd792404d3 | |
Luke Freeman | 827ecfcc65 | |
Yusuke Otsuka | 5cce0a4db2 | |
Luke Freeman | 9a3ad8d03f | |
Luke | 1536372360 | |
Luke Freeman | ddb81a6b29 | |
Luke Freeman | 3d5a90de0d | |
Miolin | bf5de991ad | |
Luke Freeman | d3b3470ac2 | |
Luke Freeman | daf1742145 | |
Jon Samwell | a11dd62910 | |
Luke Freeman | 79e35c5768 | |
Luke Freeman | 7ec4b2ed0a | |
Luke Freeman | b39baf4b8c | |
Luke Freeman | a1de0f6283 | |
Luke Freeman | c51031e6e3 | |
Luke | 3932235bfb | |
Luke Freeman | d19e689356 | |
Luke Freeman | 3ec7fbc5d2 | |
Luke Freeman | b70118b5c9 | |
Luke | 5090537969 | |
Luke Freeman | ad93ef6711 | |
Luke Freeman | f72d36bdf0 | |
Luke Freeman | 7cb9ccec56 | |
Luke Freeman | d7e6dc60e0 | |
Luke Freeman | eb7da792bc | |
Luke Freeman | e648217562 | |
Luke | 6b9a1822aa | |
Luke | bcde020404 | |
Jeongbong Seo | 27cf6c648a | |
BC Ko | cd84d8ac0e | |
Luke | d9ba273c88 | |
Luke | a0776a51ce | |
Luke | 12cb5317db | |
Jesper André Lyngesen Pedersen | c98340522c | |
Luke | 35a2254668 | |
Nami WANG | 7170d01fe7 | |
Luke | 392a66d157 | |
Luke | 1cf4267936 | |
Luke | c0f416a316 | |
Luke | 06633c8a6b | |
Luke | f89c58cb19 | |
Luke | 4cc416cb65 | |
Tudor Luca | 72a059bc0e | |
KevinTheGray | 70a71b6df6 | |
Kevin Gray | 1639f4200e | |
Kevin Gray | a48211db08 | |
Kevin Gray | f1764637ba | |
Ollie Relph | 5c32aae7fe | |
Luke | 3eec11b73e | |
Luke | b5ab39169f | |
Idan Aizik-Nissim | 8c79b537d7 | |
Albert Lardizabal | 00c84ad423 |
|
@ -0,0 +1,38 @@
|
||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Create a report to help us improve
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Describe the bug**
|
||||||
|
A clear and concise description of what the bug is.
|
||||||
|
|
||||||
|
**To Reproduce**
|
||||||
|
Steps to reproduce the behavior:
|
||||||
|
1. Go to '...'
|
||||||
|
2. Click on '....'
|
||||||
|
3. Scroll down to '....'
|
||||||
|
4. See error
|
||||||
|
|
||||||
|
**Expected behavior**
|
||||||
|
A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
|
**Screenshots**
|
||||||
|
If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
|
**Desktop (please complete the following information):**
|
||||||
|
- OS: [e.g. iOS]
|
||||||
|
- Browser [e.g. chrome, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Smartphone (please complete the following information):**
|
||||||
|
- Device: [e.g. iPhone6]
|
||||||
|
- OS: [e.g. iOS8.1]
|
||||||
|
- Browser [e.g. stock browser, safari]
|
||||||
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context about the problem here.
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: Feature request
|
||||||
|
about: Suggest an idea for this project
|
||||||
|
title: ''
|
||||||
|
labels: ''
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**Is your feature request related to a problem? Please describe.**
|
||||||
|
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
|
||||||
|
|
||||||
|
**Describe the solution you'd like**
|
||||||
|
A clear and concise description of what you want to happen.
|
||||||
|
|
||||||
|
**Describe alternatives you've considered**
|
||||||
|
A clear and concise description of any alternative solutions or features you've considered.
|
||||||
|
|
||||||
|
**Additional context**
|
||||||
|
Add any other context or screenshots about the feature request here.
|
|
@ -0,0 +1,18 @@
|
||||||
|
---
|
||||||
|
name: I need help using this library or have a question
|
||||||
|
about: Please, strongly consider posting your question to Stack Overflow or another
|
||||||
|
place. The purpose of this issue tracker is to track bugs and feature requests.
|
||||||
|
title: ''
|
||||||
|
labels: question, stack overflow
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
Please, strongly consider posting your question to Stack Overflow. The purpose of this issue tracker is to track bugs and feature requests. Questions on how to use the library should be posted to stack overflow so that everyone can benefit from your question.
|
||||||
|
|
||||||
|
If you really need to post your question here:
|
||||||
|
1. Please be super clear on what you're trying to achieve. What is the expected result?
|
||||||
|
2. Please outline what you've tried. There is no point us suggesting something you've already tried.
|
||||||
|
3. Outline the things that have failed, based on your past attempts. This will help us to diagnose whether we need to add a feature or whether it is a bug.
|
||||||
|
|
||||||
|
Thanks!
|
|
@ -9,3 +9,8 @@
|
||||||
pubspec.lock
|
pubspec.lock
|
||||||
coverage
|
coverage
|
||||||
__temp_coverage*
|
__temp_coverage*
|
||||||
|
.dart_tool/
|
||||||
|
build/
|
||||||
|
|
||||||
|
# iOS
|
||||||
|
**/flutter_export_environment.sh
|
||||||
|
|
29
.travis.yml
|
@ -1,21 +1,30 @@
|
||||||
os:
|
os:
|
||||||
- linux
|
- linux
|
||||||
sudo: false
|
sudo: false
|
||||||
|
|
||||||
addons:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
# Flutter depends on /usr/lib/x86_64-linux-gnu/libstdc++.so.6 version GLIBCXX_3.4.18
|
|
||||||
sources:
|
sources:
|
||||||
- ubuntu-toolchain-r-test # if we don't specify this, the libstdc++6 we get is the wrong version
|
- ubuntu-toolchain-r-test
|
||||||
packages:
|
packages:
|
||||||
- libstdc++6
|
- libstdc++6
|
||||||
- fonts-droid
|
- fonts-droid
|
||||||
before_script:
|
|
||||||
- ./scripts/travis_setup.sh
|
|
||||||
- ./flutter/bin/flutter doctor
|
|
||||||
script:
|
|
||||||
- ./flutter/bin/flutter test --coverage
|
|
||||||
after_success:
|
|
||||||
- bash <(curl -s https://codecov.io/bash) -t $CODE_COV_TOKEN
|
|
||||||
cache:
|
cache:
|
||||||
directories:
|
directories:
|
||||||
- $HOME/.pub-cache
|
- $HOME/.pub-cache
|
||||||
|
|
||||||
|
env:
|
||||||
|
- FLUTTER_VERSION=dev
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- env: FLUTTER_VERSION=dev
|
||||||
|
|
||||||
|
before_script:
|
||||||
|
- git clone https://github.com/flutter/flutter.git -b $FLUTTER_VERSION
|
||||||
|
- $TRAVIS_BUILD_DIR/flutter/bin/flutter doctor
|
||||||
|
script:
|
||||||
|
- ./tool/travis.sh
|
||||||
|
after_success:
|
||||||
|
- bash <(curl -s https://codecov.io/bash) -t $CODE_COV_TOKEN
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Flutter",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart",
|
||||||
|
"cwd" : "${workspaceRoot}/example",
|
||||||
|
"program": "${workspaceRoot}/example/lib/main.dart"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,81 @@
|
||||||
|
# 1.6.3
|
||||||
|
- Remove upper bounds on Flutter SDK checks because Flutter releases are a ridiculous mess
|
||||||
|
|
||||||
|
# 1.6.2
|
||||||
|
- Support for Flutter `>=1.12 <=1.17`
|
||||||
|
|
||||||
|
# 1.6.1
|
||||||
|
- Support for Flutter `1.12+`
|
||||||
|
|
||||||
|
# 1.6.0
|
||||||
|
- No changes other than fixes for non-backwards compatible Flutter changes
|
||||||
|
- Flutter `>= 1.12.0` is required due to Flutter compatibility issues
|
||||||
|
- Dart `>= 2.6.0` is required
|
||||||
|
|
||||||
|
# 1.5.2
|
||||||
|
- Remove dependency on `dart:io`
|
||||||
|
- 1.5.x and lower now only supports Flutter versions `< 1.13.0`
|
||||||
|
|
||||||
|
# 1.5.1
|
||||||
|
- Add explicit material and full screen material transition types
|
||||||
|
- Fix issue in transition logic
|
||||||
|
- Remove redundant `new`, `const`, etc qualifiers
|
||||||
|
- Tidy example
|
||||||
|
- Add font license info
|
||||||
|
|
||||||
|
# 1.5.0
|
||||||
|
- Native transitions will now use the Cupertino page route on iOS and Material page route on android. This will enable swipe gestures on iOS.
|
||||||
|
- Added cupertino specific transition types.
|
||||||
|
- **You should not be using Cupertino types on non-iOS platforms. It's up to you, but it's bad design**.
|
||||||
|
|
||||||
|
# 1.4.0
|
||||||
|
- Added the ability to define a transition at the point of route definition. Route transitions are optional and any transition defined a "push" will override the route definition.
|
||||||
|
|
||||||
|
# 1.3.7
|
||||||
|
- Add `toString` for custom `RouteNotFoundException` type
|
||||||
|
|
||||||
|
# 1.3.6
|
||||||
|
- Small fix to error return type when no route match was made
|
||||||
|
|
||||||
|
# 1.3.5
|
||||||
|
- add `pop` convenience
|
||||||
|
- add `clearStack` flag so that you can clear the history when pushing a route
|
||||||
|
|
||||||
|
# 1.3.4
|
||||||
|
- Change lower dart version to cater to older flutter versions
|
||||||
|
|
||||||
|
# 1.3.3
|
||||||
|
- Fix analyzer issues
|
||||||
|
- Remove deprecations in example code
|
||||||
|
- Fix pubspec analysis issue
|
||||||
|
|
||||||
|
# 1.3.2
|
||||||
|
- Dart 2 package (pubspec) compliance changes ONLY
|
||||||
|
- **Note**: No functional changes
|
||||||
|
|
||||||
|
# 1.3.1
|
||||||
|
- Fixes an issue with the route generator (result cannot be Null)
|
||||||
|
|
||||||
|
# 1.3.0
|
||||||
|
- **BREAKING**: Parameters now return an array of results even if they have a single value.
|
||||||
|
- Support for parameter arrays. e.g: `/some/route?color=red&color=green&color=blue`.
|
||||||
|
- Results can now be passed via `Navigator.pop` via use of a `Future`.
|
||||||
|
- A few bug fixes
|
||||||
|
|
||||||
|
# 1.1.0
|
||||||
|
|
||||||
|
**BREAKING**: In order to support function handlers you will need to change all of your route
|
||||||
|
handler definitions to use the new `Handler` class. The `RouteHandler` definition has now been
|
||||||
|
removed.
|
||||||
|
|
||||||
|
Swapping out the handlers should be as simple as changing:
|
||||||
|
|
||||||
|
```dart
|
||||||
|
RouteHandler usersHandler = (Map<String, String> params) {}
|
||||||
|
```
|
||||||
|
|
||||||
|
to
|
||||||
|
|
||||||
|
```dart
|
||||||
|
var usersHandler = new Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {});
|
||||||
|
```
|
16
LICENSE
|
@ -1,9 +1,9 @@
|
||||||
Fluro
|
Fluro
|
||||||
|
|
||||||
Created by Posse in NYC
|
Created by Yakka
|
||||||
http://goposse.com
|
https://theyakka.com
|
||||||
|
|
||||||
Copyright (c) 2017 Posse Productions LLC.
|
Copyright (c) 2019 Yakka LLC.
|
||||||
All rights reserved.
|
All rights reserved.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
Redistribution and use in source and binary forms, with or without
|
||||||
|
@ -14,17 +14,17 @@ modification, are permitted provided that the following conditions are met:
|
||||||
* Redistributions in binary form must reproduce the above copyright notice,
|
* Redistributions in binary form must reproduce the above copyright notice,
|
||||||
this list of conditions and the following disclaimer in the documentation
|
this list of conditions and the following disclaimer in the documentation
|
||||||
and/or other materials provided with the distribution.
|
and/or other materials provided with the distribution.
|
||||||
* Neither the name of the Posse Productions LLC, Posse nor the
|
* Neither the name of the Yakka LLC, Yakka nor the names of its contributors may
|
||||||
names of its contributors may be used to endorse or promote products
|
be used to endorse or promote products derived from this software without
|
||||||
derived from this software without specific prior written permission.
|
specific prior written permission.
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||||
DISCLAIMED. IN NO EVENT SHALL POSSE PRODUCTIONS LLC (POSSE) BE LIABLE FOR ANY
|
DISCLAIMED. IN NO EVENT SHALL YAKKA LLC (YAKKA) BE LIABLE FOR ANY
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
51
README.md
|
@ -1,11 +1,13 @@
|
||||||
<img src="https://storage.googleapis.com/app-logos/logo_fluro.png" width="220">
|
<img src="https://storage.googleapis.com/product-logos/logo_fluro.png" width="220">
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|
||||||
The brightest, hippest, coolest router for Flutter.
|
The brightest, hippest, coolest router for Flutter.
|
||||||
|
|
||||||
[![Version](https://img.shields.io/badge/version-1.2.1-blue.svg)](https://pub.dartlang.org/packages/fluro)
|
[![Version](https://img.shields.io/badge/version-1.6.3-blue.svg)](https://pub.dartlang.org/packages/fluro)
|
||||||
[![Build Status](https://travis-ci.org/goposse/fluro.svg?branch=master)](https://travis-ci.org/goposse/fluro)
|
[![Build Status](https://travis-ci.org/theyakka/fluro.svg?branch=master)](https://travis-ci.org/theyakka/fluro)
|
||||||
[![Coverage](https://codecov.io/gh/goposse/fluro/branch/master/graph/badge.svg)](https://codecov.io/gh/goposse/fluro)
|
[![Coverage](https://codecov.io/gh/theyakka/fluro/branch/master/graph/badge.svg)](https://codecov.io/gh/theyakka/fluro)
|
||||||
|
|
||||||
|
Version `1.6.0` (and higher) requires Flutter `>= 1.12.0` and Dart `>= 2.6.0`. If you're running an older version of Flutter, use a version `< 1.6.0`.
|
||||||
|
|
||||||
## Features
|
## Features
|
||||||
|
|
||||||
|
@ -18,36 +20,21 @@ The brightest, hippest, coolest router for Flutter.
|
||||||
|
|
||||||
## Version compatability
|
## Version compatability
|
||||||
|
|
||||||
In general we try not to introduce breaking changes but version 1.1 did introduce a
|
See CHANGELOG for all breaking (and non-breaking) changes.
|
||||||
breaking change in order to support function handlers. As such, you will need to
|
|
||||||
change all of your route handler definitions to use the new `Handler` class. The
|
|
||||||
`RouteHandler` definition has now been removed.
|
|
||||||
|
|
||||||
Swapping out the handlers should be as simple as changing:
|
|
||||||
|
|
||||||
```dart
|
|
||||||
RouteHandler usersHandler = (Map<String, String> params) {}
|
|
||||||
```
|
|
||||||
|
|
||||||
to
|
|
||||||
|
|
||||||
```dart
|
|
||||||
var usersHandler = new Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Getting started
|
## Getting started
|
||||||
|
|
||||||
You should ensure that you add the router as a dependency in your flutter project.
|
You should ensure that you add the router as a dependency in your flutter project.
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
fluro: "^1.2.1"
|
fluro: "^1.6.3"
|
||||||
```
|
```
|
||||||
|
|
||||||
You can also reference the git repo directly if you want:
|
You can also reference the git repo directly if you want:
|
||||||
```yaml
|
```yaml
|
||||||
dependencies:
|
dependencies:
|
||||||
fluro:
|
fluro:
|
||||||
git: git://github.com/goposse/fluro.git
|
git: git://github.com/theyakka/fluro.git
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
@ -61,19 +48,22 @@ There is a pretty sweet example project in the `example` folder. Check it out. O
|
||||||
|
|
||||||
First, you should define a new `Router` object by initializing it as such:
|
First, you should define a new `Router` object by initializing it as such:
|
||||||
```dart
|
```dart
|
||||||
final router = new Router();
|
final router = Router();
|
||||||
```
|
```
|
||||||
It may be convenient for you to store the router globally/statically so that
|
It may be convenient for you to store the router globally/statically so that
|
||||||
you can access the router in other areas in your application.
|
you can access the router in other areas in your application.
|
||||||
|
|
||||||
After instantiating the router, you will need to define your routes and your route handlers:
|
After instantiating the router, you will need to define your routes and your route handlers:
|
||||||
```dart
|
```dart
|
||||||
var usersHandler = new Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
|
var usersHandler = Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
|
||||||
return new UsersScreen(params["id"]);
|
return UsersScreen(params["id"][0]);
|
||||||
});
|
});
|
||||||
|
|
||||||
void defineRoutes(Router router) {
|
void defineRoutes(Router router) {
|
||||||
router.define("/users/:id", handler: usersHandler);
|
router.define("/users/:id", handler: usersHandler);
|
||||||
|
|
||||||
|
// it is also possible to define the route transition to use
|
||||||
|
// router.define("users/:id", handler: usersHandler, transitionType: TransitionType.inFromLeft);
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -93,13 +83,12 @@ for you.
|
||||||
You can also manually push to a route yourself. To do so:
|
You can also manually push to a route yourself. To do so:
|
||||||
|
|
||||||
```dart
|
```dart
|
||||||
router.navigateTo(context, "/users/1234",
|
router.navigateTo(context, "/users/1234", transition: TransitionType.fadeIn);
|
||||||
transition: TransitionType.fadeIn);
|
|
||||||
```
|
```
|
||||||
<br/>
|
|
||||||
<hr/>
|
<hr/>
|
||||||
Fluro is a Posse Production.
|
Fluro is a Yakka original.
|
||||||
<br/>
|
<br/>
|
||||||
<a href="http://goposse.com" target="_posse">
|
<a href="https://theyakka.com" target="_yakka">
|
||||||
<img src="https://storage.googleapis.com/posse-logos/logo-posse.png"
|
<img src="https://storage.googleapis.com/yakka-logos/logo_wordmark.png"
|
||||||
width="60"></a>
|
width="60"></a>
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Flutter",
|
||||||
|
"request": "launch",
|
||||||
|
"type": "dart"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
|
@ -1,101 +1,41 @@
|
||||||
// flutter
|
|
||||||
def localProperties = new Properties()
|
|
||||||
def localPropertiesFile = rootProject.file('local.properties')
|
|
||||||
if (localPropertiesFile.exists()) {
|
|
||||||
localPropertiesFile.withInputStream { stream ->
|
|
||||||
localProperties.load(stream)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
def flutterRoot = localProperties.getProperty('flutter.sdk')
|
|
||||||
if (flutterRoot == null) {
|
|
||||||
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
|
|
||||||
}
|
|
||||||
|
|
||||||
apply plugin: 'com.android.application'
|
apply plugin: 'com.android.application'
|
||||||
apply plugin: 'kotlin-android'
|
apply plugin: 'kotlin-android'
|
||||||
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
|
apply from: "../flutter.gradle"
|
||||||
|
|
||||||
flutter {
|
|
||||||
source '../..'
|
|
||||||
}
|
|
||||||
|
|
||||||
// build versioning
|
|
||||||
def currentVersionCode() {
|
|
||||||
def propsFile = file('versions.properties')
|
|
||||||
def props = new Properties()
|
|
||||||
props.load(new FileInputStream(propsFile))
|
|
||||||
return props['build.versionCode'].toInteger()
|
|
||||||
}
|
|
||||||
|
|
||||||
def incrementVersionCode() {
|
|
||||||
def propsFile = file('versions.properties')
|
|
||||||
def props = new Properties()
|
|
||||||
props.load(new FileInputStream(propsFile))
|
|
||||||
def currentCode = props['build.versionCode'].toInteger()
|
|
||||||
def nextCode = currentCode + 1
|
|
||||||
props['build.versionCode'] = nextCode.toString()
|
|
||||||
props.store(propsFile.newWriter(), null)
|
|
||||||
return nextCode
|
|
||||||
}
|
|
||||||
|
|
||||||
// increments build version code on release builds
|
|
||||||
task('incrementVersionCode') << {
|
|
||||||
incrementVersionCode()
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.whenTaskAdded { task ->
|
|
||||||
if (task.name == 'assembleRelease') {
|
|
||||||
task.dependsOn 'incrementVersionCode'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildscript {
|
|
||||||
// application variables
|
|
||||||
ext.app_ver_name = "1.0"
|
|
||||||
|
|
||||||
// google version codes
|
|
||||||
ext.build_tools_ver = '25.0.3'
|
|
||||||
ext.support_lib_ver = '25.3.1'
|
|
||||||
ext.google_play_ver = '10.2.4'
|
|
||||||
ext.constraint_layout_ver = '1.0.2'
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 25
|
compileSdkVersion 29
|
||||||
buildToolsVersion "$build_tools_ver"
|
buildToolsVersion "29.0.3"
|
||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
minSdkVersion 19
|
minSdkVersion 24
|
||||||
targetSdkVersion 25
|
targetSdkVersion 29
|
||||||
applicationId "com.goposse.routersample"
|
applicationId "app.yakka.fluroexample"
|
||||||
versionCode currentVersionCode()
|
versionCode 1
|
||||||
versionName "$app_ver_name"
|
versionName "1.6.0"
|
||||||
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
lintOptions {
|
lintOptions {
|
||||||
disable 'InvalidPackage'
|
disable 'InvalidPackage'
|
||||||
}
|
}
|
||||||
buildTypes {
|
buildTypes {
|
||||||
release {
|
release {
|
||||||
// TODO: Add your own signing config for the release build.
|
// TODO: Add your own signing config for the release build.
|
||||||
// Signing with the debug keys for now, so `flutter run --release` works.
|
// Signing with the debug keys for now, so `flutter run --release` works.
|
||||||
signingConfig signingConfigs.debug
|
signingConfig signingConfigs.debug
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
compile fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
// kotlin
|
||||||
// google
|
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:1.3.61"
|
||||||
compile "com.android.support:appcompat-v7:$support_lib_ver"
|
// google
|
||||||
compile "com.android.support:support-v13:$support_lib_ver"
|
implementation 'androidx.appcompat:appcompat:1.1.0'
|
||||||
compile "com.android.support:support-v4:$support_lib_ver"
|
implementation 'androidx.legacy:legacy-support-v13:1.0.0'
|
||||||
|
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
|
||||||
// testing
|
// testing
|
||||||
androidTestCompile "com.android.support:support-annotations:$support_lib_ver"
|
androidTestImplementation 'androidx.annotation:annotation:1.1.0'
|
||||||
androidTestCompile 'com.android.support.test:runner:0.5'
|
androidTestImplementation 'androidx.test.ext:junit:1.1.1'
|
||||||
androidTestCompile 'com.android.support.test:rules:0.5'
|
androidTestImplementation 'androidx.test:rules:1.2.0'
|
||||||
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:$kotlin_version"
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="com.goposse.routersample">
|
package="com.goposse.fluro">
|
||||||
|
|
||||||
<!-- needed for flutter development tools -->
|
<!-- needed for flutter development tools -->
|
||||||
<uses-permission android:name="android.permission.INTERNET" />
|
<uses-permission android:name="android.permission.INTERNET" />
|
||||||
|
|
||||||
<application
|
<application
|
||||||
android:name=".App"
|
android:name="com.goposse.fluro.App"
|
||||||
android:allowBackup="false"
|
android:allowBackup="false"
|
||||||
android:icon="@mipmap/ic_launcher"
|
android:icon="@mipmap/ic_launcher"
|
||||||
android:label="@string/appName">
|
android:label="@string/appName">
|
||||||
<activity
|
<activity
|
||||||
android:name=".activities.MainActivity"
|
android:name="com.goposse.fluro.activities.MainActivity"
|
||||||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection"
|
||||||
android:hardwareAccelerated="true"
|
android:hardwareAccelerated="true"
|
||||||
android:theme="@android:style/Theme.Black.NoTitleBar"
|
android:theme="@android:style/Theme.Black.NoTitleBar"
|
||||||
|
@ -23,7 +23,7 @@
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
<category android:name="android.intent.category.BROWSABLE" />
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
<data android:host="link" android:scheme="fluro" />
|
<data android:host="deeplink" android:scheme="fluro" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
</application>
|
</application>
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.goposse.routersample
|
package com.goposse.fluro
|
||||||
|
|
||||||
import io.flutter.app.FlutterApplication
|
import io.flutter.app.FlutterApplication
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.goposse.fluro.activities
|
||||||
|
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.util.Log
|
||||||
|
|
||||||
|
import io.flutter.app.FlutterActivity
|
||||||
|
import io.flutter.plugins.GeneratedPluginRegistrant
|
||||||
|
|
||||||
|
class MainActivity : FlutterActivity() {
|
||||||
|
|
||||||
|
private val logTag = "A:Main"
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
GeneratedPluginRegistrant.registerWith(this)
|
||||||
|
checkForLinkEvent(intent)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun checkForLinkEvent(intent: Intent) {
|
||||||
|
val data = intent.data
|
||||||
|
if (intent.action == Intent.ACTION_VIEW && data != null) {
|
||||||
|
val path = data.getQueryParameter("path")
|
||||||
|
val text = data.getQueryParameter("message") ?: "Why you don't enter text?"
|
||||||
|
if (path != null) {
|
||||||
|
Log.d(logTag, "Setting initial route to: $path?message=$text")
|
||||||
|
flutterView.setInitialRoute("$path?message=$text")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.goposse.routersample.constants
|
package com.goposse.fluro.constants
|
||||||
|
|
||||||
object Channels {
|
object Channels {
|
||||||
private val CHANNEL_PREFIX = "channel:com.goposse.routersample"
|
private val CHANNEL_PREFIX = "channel:com.goposse.routersample"
|
|
@ -1,44 +0,0 @@
|
||||||
package com.goposse.routersample.activities
|
|
||||||
|
|
||||||
import android.content.Intent
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.util.Log
|
|
||||||
|
|
||||||
import com.goposse.routersample.constants.Channels
|
|
||||||
|
|
||||||
import io.flutter.app.FlutterActivity
|
|
||||||
import io.flutter.plugin.common.MethodChannel
|
|
||||||
import io.flutter.plugins.GeneratedPluginRegistrant
|
|
||||||
|
|
||||||
class MainActivity : FlutterActivity() {
|
|
||||||
|
|
||||||
private val LOG_TAG = "A:Main"
|
|
||||||
private var deepLinkChannel: MethodChannel? = null
|
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
GeneratedPluginRegistrant.registerWith(this)
|
|
||||||
deepLinkChannel = MethodChannel(flutterView, Channels.DEEP_LINK_RECEIVED)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
checkForLinkEvent(intent)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun checkForLinkEvent(intent: Intent) {
|
|
||||||
if (intent.action == Intent.ACTION_VIEW && intent.data != null) {
|
|
||||||
val path = intent.data.getQueryParameter("path")
|
|
||||||
val query = intent.data.getQueryParameter("query")
|
|
||||||
if (path != null) {
|
|
||||||
val passedObjs = mutableMapOf<String, Any>("path" to path)
|
|
||||||
if (query != null) {
|
|
||||||
passedObjs["query"] = query
|
|
||||||
}
|
|
||||||
deepLinkChannel?.invokeMethod("linkReceived", passedObjs)
|
|
||||||
Log.d(LOG_TAG, "Sent message to flutter: linkReceived=$path")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -7,5 +7,17 @@ import io.flutter.plugin.common.PluginRegistry;
|
||||||
*/
|
*/
|
||||||
public final class GeneratedPluginRegistrant {
|
public final class GeneratedPluginRegistrant {
|
||||||
public static void registerWith(PluginRegistry registry) {
|
public static void registerWith(PluginRegistry registry) {
|
||||||
|
if (alreadyRegisteredWith(registry)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static boolean alreadyRegisteredWith(PluginRegistry registry) {
|
||||||
|
final String key = GeneratedPluginRegistrant.class.getCanonicalName();
|
||||||
|
if (registry.hasPlugin(key)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
registry.registrarFor(key);
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,21 +1,20 @@
|
||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.1.3-2'
|
ext.kotlin_version = '1.3.61'
|
||||||
repositories {
|
repositories {
|
||||||
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:2.3.3'
|
classpath 'com.android.tools.build:gradle:3.5.3'
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
allprojects {
|
allprojects {
|
||||||
repositories {
|
repositories {
|
||||||
|
google()
|
||||||
jcenter()
|
jcenter()
|
||||||
maven {
|
|
||||||
url "https://maven.google.com"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
ext.appInfo = [
|
||||||
|
version: '1.6.0',
|
||||||
|
build: 1,
|
||||||
|
applicationID: "com.goposse.fluro"
|
||||||
|
]
|
||||||
|
|
||||||
|
ext.versions = [
|
||||||
|
minSDK: 21,
|
||||||
|
targetSDK: 29,
|
||||||
|
buildTools: '29.0.3',
|
||||||
|
kotlin: '1.3.61',
|
||||||
|
googleSupport: '27.1.0'
|
||||||
|
]
|
|
@ -0,0 +1,22 @@
|
||||||
|
// Flutter root path helper
|
||||||
|
ext.flutterRoot = {
|
||||||
|
def flutterProperties = new Properties()
|
||||||
|
def flutterPropertiesFile = rootProject.file('local.properties')
|
||||||
|
if (!flutterPropertiesFile.exists()) {
|
||||||
|
throw new GradleException("Flutter properties file not found. Define a flutter.properties file in your project root.")
|
||||||
|
}
|
||||||
|
flutterPropertiesFile.withInputStream { stream ->
|
||||||
|
flutterProperties.load(stream)
|
||||||
|
}
|
||||||
|
def flutterRoot = flutterProperties.getProperty('flutter.sdk')
|
||||||
|
if (flutterRoot == null) {
|
||||||
|
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the flutter.properties file.")
|
||||||
|
}
|
||||||
|
return flutterRoot
|
||||||
|
}
|
||||||
|
|
||||||
|
apply from: "${flutterRoot()}/packages/flutter_tools/gradle/flutter.gradle"
|
||||||
|
|
||||||
|
flutter {
|
||||||
|
source '../..'
|
||||||
|
}
|
|
@ -1 +1,4 @@
|
||||||
org.gradle.jvmargs=-Xmx1536M
|
org.gradle.jvmargs=-Xmx1536M
|
||||||
|
android.enableR8=true
|
||||||
|
android.useAndroidX=true
|
||||||
|
android.enableJetifier=true
|
||||||
|
|
|
@ -0,0 +1,93 @@
|
||||||
|
Copyright 2015 SUNRISE DIGITAL, Juan Hodgson Authors (srdigital@msn.com)
|
||||||
|
|
||||||
|
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||||
|
This license is copied below, and is also available with a FAQ at:
|
||||||
|
http://scripts.sil.org/OFL
|
||||||
|
|
||||||
|
|
||||||
|
-----------------------------------------------------------
|
||||||
|
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
PREAMBLE
|
||||||
|
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||||
|
development of collaborative font projects, to support the font creation
|
||||||
|
efforts of academic and linguistic communities, and to provide a free and
|
||||||
|
open framework in which fonts may be shared and improved in partnership
|
||||||
|
with others.
|
||||||
|
|
||||||
|
The OFL allows the licensed fonts to be used, studied, modified and
|
||||||
|
redistributed freely as long as they are not sold by themselves. The
|
||||||
|
fonts, including any derivative works, can be bundled, embedded,
|
||||||
|
redistributed and/or sold with any software provided that any reserved
|
||||||
|
names are not used by derivative works. The fonts and derivatives,
|
||||||
|
however, cannot be released under any other type of license. The
|
||||||
|
requirement for fonts to remain under this license does not apply
|
||||||
|
to any document created using the fonts or their derivatives.
|
||||||
|
|
||||||
|
DEFINITIONS
|
||||||
|
"Font Software" refers to the set of files released by the Copyright
|
||||||
|
Holder(s) under this license and clearly marked as such. This may
|
||||||
|
include source files, build scripts and documentation.
|
||||||
|
|
||||||
|
"Reserved Font Name" refers to any names specified as such after the
|
||||||
|
copyright statement(s).
|
||||||
|
|
||||||
|
"Original Version" refers to the collection of Font Software components as
|
||||||
|
distributed by the Copyright Holder(s).
|
||||||
|
|
||||||
|
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||||
|
or substituting -- in part or in whole -- any of the components of the
|
||||||
|
Original Version, by changing formats or by porting the Font Software to a
|
||||||
|
new environment.
|
||||||
|
|
||||||
|
"Author" refers to any designer, engineer, programmer, technical
|
||||||
|
writer or other person who contributed to the Font Software.
|
||||||
|
|
||||||
|
PERMISSION & CONDITIONS
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining
|
||||||
|
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||||
|
redistribute, and sell modified and unmodified copies of the Font
|
||||||
|
Software, subject to the following conditions:
|
||||||
|
|
||||||
|
1) Neither the Font Software nor any of its individual components,
|
||||||
|
in Original or Modified Versions, may be sold by itself.
|
||||||
|
|
||||||
|
2) Original or Modified Versions of the Font Software may be bundled,
|
||||||
|
redistributed and/or sold with any software, provided that each copy
|
||||||
|
contains the above copyright notice and this license. These can be
|
||||||
|
included either as stand-alone text files, human-readable headers or
|
||||||
|
in the appropriate machine-readable metadata fields within text or
|
||||||
|
binary files as long as those fields can be easily viewed by the user.
|
||||||
|
|
||||||
|
3) No Modified Version of the Font Software may use the Reserved Font
|
||||||
|
Name(s) unless explicit written permission is granted by the corresponding
|
||||||
|
Copyright Holder. This restriction only applies to the primary font name as
|
||||||
|
presented to the users.
|
||||||
|
|
||||||
|
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||||
|
Software shall not be used to promote, endorse or advertise any
|
||||||
|
Modified Version, except to acknowledge the contribution(s) of the
|
||||||
|
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||||
|
permission.
|
||||||
|
|
||||||
|
5) The Font Software, modified or unmodified, in part or in whole,
|
||||||
|
must be distributed entirely under this license, and must not be
|
||||||
|
distributed under any other license. The requirement for fonts to
|
||||||
|
remain under this license does not apply to any document created
|
||||||
|
using the Font Software.
|
||||||
|
|
||||||
|
TERMINATION
|
||||||
|
This license becomes null and void if any of the above conditions are
|
||||||
|
not met.
|
||||||
|
|
||||||
|
DISCLAIMER
|
||||||
|
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||||
|
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||||
|
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||||
|
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||||
|
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||||
|
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||||
|
OTHER DEALINGS IN THE FONT SOFTWARE.
|
After Width: | Height: | Size: 731 B |
After Width: | Height: | Size: 978 B |
After Width: | Height: | Size: 882 B |
After Width: | Height: | Size: 587 B |
After Width: | Height: | Size: 645 B |
After Width: | Height: | Size: 978 B |
After Width: | Height: | Size: 1.0 KiB |
|
@ -0,0 +1,18 @@
|
||||||
|
#
|
||||||
|
# NOTE: This podspec is NOT to be published. It is only used as a local source!
|
||||||
|
#
|
||||||
|
|
||||||
|
Pod::Spec.new do |s|
|
||||||
|
s.name = 'Flutter'
|
||||||
|
s.version = '1.0.0'
|
||||||
|
s.summary = 'High-performance, high-fidelity mobile apps.'
|
||||||
|
s.description = <<-DESC
|
||||||
|
Flutter provides an easy and productive way to build and deploy high-performance mobile apps for Android and iOS.
|
||||||
|
DESC
|
||||||
|
s.homepage = 'https://flutter.io'
|
||||||
|
s.license = { :type => 'MIT' }
|
||||||
|
s.author = { 'Flutter Dev Team' => 'flutter-dev@googlegroups.com' }
|
||||||
|
s.source = { :git => 'https://github.com/flutter/engine', :tag => s.version.to_s }
|
||||||
|
s.ios.deployment_target = '8.0'
|
||||||
|
s.vendored_frameworks = 'Flutter.framework'
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
{"assets/images/logo_fluro.png":["assets/images/logo_fluro.png","assets/images/2.0x/logo_fluro.png"],"assets/images/acc_boom.png":["assets/images/acc_boom.png","assets/images/2.0x/acc_boom.png"],"assets/fonts/Lazer84.ttf":["assets/fonts/Lazer84.ttf"]}
|
|
@ -0,0 +1 @@
|
||||||
|
[{"fonts":[{"asset":"assets/fonts/Lazer84.ttf"}],"family":"Lazer84"}]
|
After Width: | Height: | Size: 9.2 KiB |
After Width: | Height: | Size: 23 KiB |
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
@ -15,7 +15,6 @@
|
||||||
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
|
||||||
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
|
9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };
|
||||||
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
|
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB31CF90195004384FC /* Generated.xcconfig */; };
|
||||||
9740EEBB1CF902C7004384FC /* app.flx in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB71CF902C7004384FC /* app.flx */; };
|
|
||||||
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
|
978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };
|
||||||
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
|
97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
|
@ -48,7 +47,6 @@
|
||||||
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB71CF902C7004384FC /* app.flx */ = {isa = PBXFileReference; lastKnownFileType = file; name = app.flx; path = Flutter/app.flx; sourceTree = "<group>"; };
|
|
||||||
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
|
9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = "<group>"; };
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
|
||||||
|
@ -74,7 +72,6 @@
|
||||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
9740EEB71CF902C7004384FC /* app.flx */,
|
|
||||||
3B80C3931E831B6300D905FE /* App.framework */,
|
3B80C3931E831B6300D905FE /* App.framework */,
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||||
9740EEBA1CF902C7004384FC /* Flutter.framework */,
|
9740EEBA1CF902C7004384FC /* Flutter.framework */,
|
||||||
|
@ -187,7 +184,6 @@
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
9740EEBB1CF902C7004384FC /* app.flx in Resources */,
|
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,
|
||||||
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
|
9740EEB51CF90195004384FC /* Generated.xcconfig in Resources */,
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,
|
||||||
|
|
|
@ -7,9 +7,11 @@
|
||||||
|
|
||||||
#import <Flutter/Flutter.h>
|
#import <Flutter/Flutter.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
@interface GeneratedPluginRegistrant : NSObject
|
@interface GeneratedPluginRegistrant : NSObject
|
||||||
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
|
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
#endif /* GeneratedPluginRegistrant_h */
|
#endif /* GeneratedPluginRegistrant_h */
|
||||||
|
|
|
@ -1,59 +1,43 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
import '../../config/application.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:fluro/fluro.dart';
|
import 'package:fluro/fluro.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
import '../../config/application.dart';
|
||||||
import '../../config/routes.dart';
|
import '../../config/routes.dart';
|
||||||
import '../home/home_component.dart';
|
|
||||||
|
|
||||||
class AppComponent extends StatefulWidget {
|
class AppComponent extends StatefulWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
State createState() {
|
State createState() {
|
||||||
return new AppComponentState();
|
return AppComponentState();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppComponentState extends State<AppComponent> {
|
class AppComponentState extends State<AppComponent> {
|
||||||
|
|
||||||
static MethodChannel platform = const MethodChannel('channel:com.goposse.routersample/deeplink');
|
|
||||||
|
|
||||||
AppComponentState() {
|
AppComponentState() {
|
||||||
Router router = new Router();
|
final router = Router();
|
||||||
Routes.configureRoutes(router);
|
Routes.configureRoutes(router);
|
||||||
Application.router = router;
|
Application.router = router;
|
||||||
configureDeepLinker();
|
|
||||||
print("Configured channel receiver in flutter ..");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void configureDeepLinker() {
|
|
||||||
platform.setMethodCallHandler((MethodCall call) async {
|
|
||||||
if (call.method == "linkReceived") {
|
|
||||||
Map<String, dynamic> passedObjs = call.arguments;
|
|
||||||
if (passedObjs != null) {
|
|
||||||
var path = passedObjs["path"];
|
|
||||||
Application.router.navigateTo(context, path);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return new MaterialApp(
|
final app = MaterialApp(
|
||||||
title: 'Flutter Demo',
|
title: 'Fluro',
|
||||||
theme: new ThemeData(
|
debugShowCheckedModeBanner: false,
|
||||||
|
theme: ThemeData(
|
||||||
primarySwatch: Colors.blue,
|
primarySwatch: Colors.blue,
|
||||||
),
|
),
|
||||||
home: new HomeComponent(),
|
onGenerateRoute: Application.router.generator,
|
||||||
|
navigatorKey: Application.routerKey,
|
||||||
);
|
);
|
||||||
|
// print("initial route = ${app.initialRoute}");
|
||||||
|
return app;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,33 +1,32 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:meta/meta.dart';
|
|
||||||
|
|
||||||
class DemoMessageComponent extends StatelessWidget {
|
class DemoMessageComponent extends StatelessWidget {
|
||||||
|
DemoMessageComponent(
|
||||||
DemoMessageComponent({@required this.message, this.color = const Color(0xFFFFFFFF)});
|
{@required this.message, this.color = const Color(0xFFFFFFFF)});
|
||||||
|
|
||||||
final String message;
|
final String message;
|
||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return new Material(
|
return Material(
|
||||||
color: this.color,
|
color: this.color,
|
||||||
child: new Center(
|
child: Center(
|
||||||
child: new Text(
|
child: Text(
|
||||||
message,
|
message,
|
||||||
style: new TextStyle(
|
style: TextStyle(
|
||||||
fontFamily: "Lazer84",
|
fontFamily: "Lazer84",
|
||||||
),
|
),
|
||||||
)
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
/*
|
||||||
|
* fluro
|
||||||
|
* Created by Yakka
|
||||||
|
* https://theyakka.com
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
|
* See LICENSE for distribution and usage details.
|
||||||
|
*/
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class DemoResultComponent extends StatefulWidget {
|
||||||
|
@override
|
||||||
|
_DemoResultComponentState createState() => _DemoResultComponentState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DemoResultComponentState extends State<DemoResultComponent> {
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Container();
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,56 +1,72 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
import '../../helpers/color_helpers.dart';
|
import '../../helpers/color_helpers.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class DemoSimpleComponent extends StatelessWidget {
|
class DemoSimpleComponent extends StatelessWidget {
|
||||||
|
DemoSimpleComponent(
|
||||||
DemoSimpleComponent({String message = "Testing", Color color = const Color(0xFFFFFFFF)})
|
{String message = "Testing",
|
||||||
|
Color color = const Color(0xFFFFFFFF),
|
||||||
|
String result})
|
||||||
: this.message = message,
|
: this.message = message,
|
||||||
this.color = color;
|
this.color = color,
|
||||||
|
this.result = result;
|
||||||
|
|
||||||
final String message;
|
final String message;
|
||||||
final Color color;
|
final Color color;
|
||||||
|
final String result;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return new Material(
|
return Material(
|
||||||
color: color,
|
color: color,
|
||||||
child: new Column(
|
child: Column(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
new Image(
|
Image(
|
||||||
image: new AssetImage("assets/images/acc_boom.png"),
|
image: AssetImage("assets/images/acc_boom.png"),
|
||||||
color: ColorHelpers.blackOrWhiteContrastColor(color),
|
color: ColorHelpers.blackOrWhiteContrastColor(color),
|
||||||
width: 350.0,
|
width: 260.0,
|
||||||
),
|
),
|
||||||
new Padding(
|
Padding(
|
||||||
padding: new EdgeInsets.only(left: 50.0, right: 50.0, top: 15.0),
|
padding: EdgeInsets.only(left: 50.0, right: 50.0, top: 15.0),
|
||||||
child: new Text(
|
child: Text(
|
||||||
message,
|
message,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: new TextStyle(
|
style: TextStyle(
|
||||||
color: ColorHelpers.blackOrWhiteContrastColor(color),
|
color: ColorHelpers.blackOrWhiteContrastColor(color),
|
||||||
height: 2.0,
|
height: 2.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
new Padding(
|
Padding(
|
||||||
padding: new EdgeInsets.only(top: 15.0),
|
padding: EdgeInsets.only(top: 15.0),
|
||||||
child: new FlatButton(
|
child: ConstrainedBox(
|
||||||
onPressed: () {
|
constraints: BoxConstraints(minHeight: 42.0),
|
||||||
Navigator.pop(context);
|
child: FlatButton(
|
||||||
},
|
highlightColor:
|
||||||
child: new Text(
|
ColorHelpers.blackOrWhiteContrastColor(color).withAlpha(17),
|
||||||
"OK",
|
splashColor:
|
||||||
style: new TextStyle(
|
ColorHelpers.blackOrWhiteContrastColor(color).withAlpha(34),
|
||||||
fontSize: 18.0,
|
onPressed: () {
|
||||||
color: ColorHelpers.blackOrWhiteContrastColor(color),
|
if (result == null) {
|
||||||
|
Navigator.pop(context);
|
||||||
|
} else {
|
||||||
|
Navigator.pop(context, result);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
child: Text(
|
||||||
|
"OK",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 18.0,
|
||||||
|
color: ColorHelpers.blackOrWhiteContrastColor(color),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -59,4 +75,4 @@ class DemoSimpleComponent extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,72 +1,193 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
|
import 'package:fluro/fluro.dart';
|
||||||
|
import 'package:flutter/cupertino.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
|
||||||
import '../../config/application.dart';
|
import '../../config/application.dart';
|
||||||
import 'package:fluro/fluro.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
|
|
||||||
class HomeComponent extends StatelessWidget {
|
class HomeComponent extends StatefulWidget {
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
State createState() => HomeComponentState();
|
||||||
var menuWidgets = <Widget>[
|
}
|
||||||
new Padding(
|
|
||||||
padding: new EdgeInsets.only(bottom: 25.0),
|
|
||||||
child: new Image(image: new AssetImage("assets/images/logo_fluro.png"), width: 200.0),
|
|
||||||
),
|
|
||||||
menuButton(context, "Native Animation", "native"),
|
|
||||||
menuButton(context, "Preset (In from Left)", "preset-from-left"),
|
|
||||||
menuButton(context, "Preset (Fade In)", "preset-fade"),
|
|
||||||
menuButton(context, "Custom Transition", "custom"),
|
|
||||||
menuButton(context, "Function Call", "function-call"),
|
|
||||||
new Padding(
|
|
||||||
padding: new EdgeInsets.only(top: 65.0, left: 60.0, right: 60.0),
|
|
||||||
child: new Center(
|
|
||||||
child: new ConstrainedBox(
|
|
||||||
constraints: new BoxConstraints.tightFor(height: 50.0),
|
|
||||||
child: new FlatButton(
|
|
||||||
onPressed: () {
|
|
||||||
|
|
||||||
|
class HomeComponentState extends State<HomeComponent> {
|
||||||
|
var _deepLinkOpacity = 1.0;
|
||||||
|
final _deepLinkURL =
|
||||||
|
"fluro://deeplink?path=/message&mesage=fluro%20rocks%21%21";
|
||||||
|
final _daysOfWeek = const [
|
||||||
|
"Monday",
|
||||||
|
"Tuesday",
|
||||||
|
"Wednesday",
|
||||||
|
"Thursday",
|
||||||
|
"Friday",
|
||||||
|
"Saturday",
|
||||||
|
"Sunday"
|
||||||
|
];
|
||||||
|
|
||||||
|
Widget deepLinkWidget(BuildContext context) {
|
||||||
|
return Stack(
|
||||||
|
children: <Widget>[
|
||||||
|
// copied widget
|
||||||
|
AnimatedOpacity(
|
||||||
|
opacity: (_deepLinkOpacity - 1.0).abs(),
|
||||||
|
duration: Duration(milliseconds: 400),
|
||||||
|
child: Center(
|
||||||
|
child: Text(
|
||||||
|
"Copied to clipboard!",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14.0,
|
||||||
|
color: const Color(0xFFFFFFFF),
|
||||||
|
fontWeight: FontWeight.w500,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// button widget
|
||||||
|
AnimatedOpacity(
|
||||||
|
opacity: _deepLinkOpacity,
|
||||||
|
duration: Duration(milliseconds: 250),
|
||||||
|
child: Center(
|
||||||
|
child: FlatButton(
|
||||||
|
highlightColor: const Color(0x11FFFFFF),
|
||||||
|
splashColor: const Color(0x22FFFFFF),
|
||||||
|
onPressed: () {
|
||||||
|
if (_deepLinkOpacity == 1.0) {
|
||||||
|
Timer(Duration(milliseconds: 2000), () {
|
||||||
|
setState(() {
|
||||||
|
_deepLinkOpacity = 1.0;
|
||||||
|
});
|
||||||
|
});
|
||||||
|
setState(() {
|
||||||
|
_deepLinkOpacity = 0.0;
|
||||||
|
});
|
||||||
|
final clipboardData = ClipboardData(text: _deepLinkURL);
|
||||||
|
Clipboard.setData(clipboardData);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: new Text(
|
child: Padding(
|
||||||
"Try going to fluro://deeplink?path=/message&text=fluro%20rocks%21%21",
|
padding: EdgeInsets.all(8.0),
|
||||||
textAlign: TextAlign.center,
|
child: Text(
|
||||||
style: new TextStyle(
|
"Click here to copy a deep link url to the clipboard",
|
||||||
fontSize: 10.0,
|
textAlign: TextAlign.center,
|
||||||
color: const Color(0xFFFFFFFF),
|
style: TextStyle(
|
||||||
|
fontSize: 12.0,
|
||||||
|
color: const Color(0xCCFFFFFF),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
var menuWidgets = <Widget>[
|
||||||
|
menuButton(context, 'assets/images/ic_transform_native_hz.png',
|
||||||
|
"Native Animation", "native"),
|
||||||
|
menuButton(context, 'assets/images/ic_transform_fade_in_hz.png',
|
||||||
|
"Preset (Fade In)", "preset-fade"),
|
||||||
|
menuButton(context, 'assets/images/ic_transform_global_hz.png',
|
||||||
|
"Preset (Global transition)", "fixed-trans"),
|
||||||
|
menuButton(context, 'assets/images/ic_transform_custom_hz.png',
|
||||||
|
"Custom Transition", "custom"),
|
||||||
|
menuButton(context, 'assets/images/ic_result_hz.png', "Navigator Result",
|
||||||
|
"pop-result"),
|
||||||
|
menuButton(context, 'assets/images/ic_function_hz.png', "Function Call",
|
||||||
|
"function-call"),
|
||||||
];
|
];
|
||||||
|
|
||||||
return new Material(
|
final size = MediaQuery.of(context).size;
|
||||||
|
final childRatio = (size.width / size.height) * 2.5;
|
||||||
|
|
||||||
|
return Material(
|
||||||
color: const Color(0xFF00D6F7),
|
color: const Color(0xFF00D6F7),
|
||||||
child: new Column(
|
child: SafeArea(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
top: true,
|
||||||
children: menuWidgets,
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.max,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(top: 25, bottom: 35, left: 25),
|
||||||
|
child: Image(
|
||||||
|
image: AssetImage("assets/images/logo_fluro.png"),
|
||||||
|
width: 100.0,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 25),
|
||||||
|
child: GridView.count(
|
||||||
|
childAspectRatio: childRatio,
|
||||||
|
crossAxisCount: 2,
|
||||||
|
mainAxisSpacing: 5,
|
||||||
|
children: menuWidgets,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Padding(
|
||||||
|
// padding: EdgeInsets.only(top: 35.0, bottom: 25),
|
||||||
|
// child: Center(
|
||||||
|
// child: ConstrainedBox(
|
||||||
|
// constraints: BoxConstraints.tightFor(height: 60.0),
|
||||||
|
// child: deepLinkWidget(context),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
// ),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// helpers
|
// helpers
|
||||||
Widget menuButton(BuildContext context, String title, String key) {
|
Widget menuButton(
|
||||||
return new Padding(
|
BuildContext context, String assetSrc, String title, String key) {
|
||||||
padding: new EdgeInsets.all(4.0),
|
return Padding(
|
||||||
child: new ConstrainedBox(
|
padding: EdgeInsets.all(4.0),
|
||||||
constraints: new BoxConstraints(minHeight: 32.0),
|
child: Container(
|
||||||
child: new FlatButton(
|
height: 42.0,
|
||||||
child: new Text(
|
child: FlatButton(
|
||||||
title,
|
color: const Color(0x22FFFFFF),
|
||||||
style: new TextStyle(
|
highlightColor: const Color(0x11FFFFFF),
|
||||||
color: const Color(0xFF004F8F),
|
splashColor: const Color(0x22FFFFFF),
|
||||||
),
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.only(bottom: 10),
|
||||||
|
child: Container(
|
||||||
|
height: 36,
|
||||||
|
child: Image.asset(
|
||||||
|
assetSrc,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
title,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: const Color(0xAA001133),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
],
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
tappedMenuButton(context, key);
|
tappedMenuButton(context, key);
|
||||||
|
@ -80,44 +201,70 @@ class HomeComponent extends StatelessWidget {
|
||||||
void tappedMenuButton(BuildContext context, String key) {
|
void tappedMenuButton(BuildContext context, String key) {
|
||||||
String message = "";
|
String message = "";
|
||||||
String hexCode = "#FFFFFF";
|
String hexCode = "#FFFFFF";
|
||||||
|
String result;
|
||||||
TransitionType transitionType = TransitionType.native;
|
TransitionType transitionType = TransitionType.native;
|
||||||
if (key != "custom" && key != "function-call") {
|
if (key != "custom" && key != "function-call" && key != "fixed-trans") {
|
||||||
if (key == "native") {
|
if (key == "native") {
|
||||||
hexCode = "#F76F00";
|
hexCode = "#F76F00";
|
||||||
message = "This screen should have appeared using the default flutter animation for the current OS";
|
message =
|
||||||
|
"This screen should have appeared using the default flutter animation for the current OS";
|
||||||
} else if (key == "preset-from-left") {
|
} else if (key == "preset-from-left") {
|
||||||
hexCode = "#5BF700";
|
hexCode = "#5BF700";
|
||||||
message = "This screen should have appeared with a slide in from left transition";
|
message =
|
||||||
|
"This screen should have appeared with a slide in from left transition";
|
||||||
transitionType = TransitionType.inFromLeft;
|
transitionType = TransitionType.inFromLeft;
|
||||||
} else if (key == "preset-fade") {
|
} else if (key == "preset-fade") {
|
||||||
hexCode = "#F700D2";
|
hexCode = "#F700D2";
|
||||||
message = "This screen should have appeared with a fade in transition";
|
message = "This screen should have appeared with a fade in transition";
|
||||||
transitionType = TransitionType.fadeIn;
|
transitionType = TransitionType.fadeIn;
|
||||||
|
} else if (key == "pop-result") {
|
||||||
|
transitionType = TransitionType.native;
|
||||||
|
hexCode = "#7d41f4";
|
||||||
|
message =
|
||||||
|
"When you close this screen you should see the current day of the week";
|
||||||
|
result = "Today is ${_daysOfWeek[DateTime.now().weekday - 1]}!";
|
||||||
}
|
}
|
||||||
Application.router.navigateTo(context, "/demo?message=$message&color_hex=$hexCode", transition: transitionType);
|
|
||||||
|
String route = "/demo?message=$message&color_hex=$hexCode";
|
||||||
|
|
||||||
|
if (result != null) {
|
||||||
|
route = "$route&result=$result";
|
||||||
|
}
|
||||||
|
|
||||||
|
Application.router
|
||||||
|
.navigateTo(Application.routerKey, route, transition: transitionType)
|
||||||
|
.then((result) {
|
||||||
|
if (key == "pop-result") {
|
||||||
|
Application.router.navigateTo(Application.routerKey, "/demo/func?message=$result");
|
||||||
|
}
|
||||||
|
});
|
||||||
} else if (key == "custom") {
|
} else if (key == "custom") {
|
||||||
hexCode = "#DFF700";
|
hexCode = "#DFF700";
|
||||||
message = "This screen should have appeared with a crazy custom transition";
|
message =
|
||||||
var transition =
|
"This screen should have appeared with a crazy custom transition";
|
||||||
(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
|
var transition = (BuildContext context, Animation<double> animation,
|
||||||
return new ScaleTransition(
|
Animation<double> secondaryAnimation, Widget child) {
|
||||||
|
return ScaleTransition(
|
||||||
scale: animation,
|
scale: animation,
|
||||||
child: new RotationTransition(
|
child: RotationTransition(
|
||||||
turns: animation,
|
turns: animation,
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
Application.router.navigateTo(
|
Application.router.navigateTo(
|
||||||
context,
|
Application.routerKey,
|
||||||
"/demo?message=$message&color_hex=$hexCode",
|
"/demo?message=$message&color_hex=$hexCode",
|
||||||
transition: TransitionType.custom,
|
transition: TransitionType.custom,
|
||||||
transitionBuilder: transition,
|
transitionBuilder: transition,
|
||||||
transitionDuration: const Duration(milliseconds: 600),
|
transitionDuration: const Duration(milliseconds: 600),
|
||||||
);
|
);
|
||||||
|
} else if (key == "fixed-trans") {
|
||||||
|
Application.router.navigateTo(
|
||||||
|
Application.routerKey, "/demo/fixedtrans?message=Hello!&color_hex=#f4424b");
|
||||||
} else {
|
} else {
|
||||||
message = "You tapped the function button!";
|
message = "You tapped the function button!";
|
||||||
Application.router.navigateTo(context, "/demo/func?message=$message");
|
Application.router.navigateTo(Application.routerKey, "/demo/func?message=$message");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,13 +1,16 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:fluro/fluro.dart';
|
import 'package:fluro/fluro.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class Application {
|
class Application {
|
||||||
static Router router;
|
static Router router;
|
||||||
}
|
|
||||||
|
static GlobalKey<NavigatorState> routerKey = GlobalKey<NavigatorState>();
|
||||||
|
}
|
||||||
|
|
|
@ -1,56 +1,80 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
import '../helpers/color_helpers.dart';
|
import '../helpers/color_helpers.dart';
|
||||||
import '../components/demo/demo_simple_component.dart';
|
import '../components/demo/demo_simple_component.dart';
|
||||||
|
import '../components/home/home_component.dart';
|
||||||
import 'package:flutter/painting.dart';
|
import 'package:flutter/painting.dart';
|
||||||
import 'package:fluro/fluro.dart';
|
import 'package:fluro/fluro.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
var demoRouteHandler = new Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
|
var rootHandler = Handler(
|
||||||
String message = params["message"];
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
String colorHex = params["color_hex"];
|
return HomeComponent();
|
||||||
Color color = new Color(0xFFFFFFFF);
|
|
||||||
if (colorHex != null && colorHex.length > 0) {
|
|
||||||
color = new Color(ColorHelpers.fromHexString(colorHex));
|
|
||||||
}
|
|
||||||
return new DemoSimpleComponent(message: message, color: color);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
var demoFunctionHandler = new Handler(type: HandlerType.function,
|
var demoRouteHandler = Handler(
|
||||||
handlerFunc: (BuildContext context, Map<String, dynamic> params)
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
{
|
String message = params["message"]?.first;
|
||||||
String message = params["message"];
|
String colorHex = params["color_hex"]?.first;
|
||||||
showDialog(context: context,
|
String result = params["result"]?.first;
|
||||||
child: new AlertDialog(
|
Color color = Color(0xFFFFFFFF);
|
||||||
title: new Text(
|
if (colorHex != null && colorHex.length > 0) {
|
||||||
"Hey Hey!",
|
color = Color(ColorHelpers.fromHexString(colorHex));
|
||||||
style: new TextStyle(
|
}
|
||||||
color: const Color(0xFF00D6F7),
|
return DemoSimpleComponent(message: message, color: color, result: result);
|
||||||
fontFamily: "Lazer84",
|
});
|
||||||
fontSize: 22.0,
|
|
||||||
),
|
var demoFunctionHandler = Handler(
|
||||||
),
|
type: HandlerType.function,
|
||||||
content: new Text("$message"),
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
actions: <Widget>[
|
String message = params["message"]?.first;
|
||||||
new Padding(
|
showDialog(
|
||||||
padding: new EdgeInsets.only(bottom: 8.0, right: 8.0),
|
context: context,
|
||||||
child: new FlatButton(
|
builder: (context) {
|
||||||
onPressed: () {
|
return AlertDialog(
|
||||||
Navigator.of(context).pop(true);
|
title: Text(
|
||||||
},
|
"Hey Hey!",
|
||||||
child: new Text("OK"),
|
style: TextStyle(
|
||||||
|
color: const Color(0xFF00D6F7),
|
||||||
|
fontFamily: "Lazer84",
|
||||||
|
fontSize: 22.0,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
content: Text("$message"),
|
||||||
),
|
actions: <Widget>[
|
||||||
|
Padding(
|
||||||
|
padding: EdgeInsets.only(bottom: 8.0, right: 8.0),
|
||||||
|
child: FlatButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop(true);
|
||||||
|
},
|
||||||
|
child: Text("OK"),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
var deepLinkHandler = new Handler(handlerFunc: (BuildContext context, Map<String, dynamic> params) {
|
/// Handles deep links into the app
|
||||||
|
/// To test on Android:
|
||||||
});
|
///
|
||||||
|
/// `adb shell am start -W -a android.intent.action.VIEW -d "fluro://deeplink?path=/message&mesage=fluro%20rocks%21%21" com.theyakka.fluro`
|
||||||
|
var deepLinkHandler = Handler(
|
||||||
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
|
String colorHex = params["color_hex"]?.first;
|
||||||
|
String result = params["result"]?.first;
|
||||||
|
Color color = Color(0xFFFFFFFF);
|
||||||
|
if (colorHex != null && colorHex.length > 0) {
|
||||||
|
color = Color(ColorHelpers.fromHexString(colorHex));
|
||||||
|
}
|
||||||
|
return DemoSimpleComponent(
|
||||||
|
message: "DEEEEEP LINK!!!", color: color, result: result);
|
||||||
|
});
|
||||||
|
|
|
@ -1,16 +1,32 @@
|
||||||
|
/*
|
||||||
|
* fluro
|
||||||
|
* Created by Yakka
|
||||||
|
* https://theyakka.com
|
||||||
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
|
* See LICENSE for distribution and usage details.
|
||||||
|
*/
|
||||||
import 'package:fluro/fluro.dart';
|
import 'package:fluro/fluro.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
import './route_handlers.dart';
|
import './route_handlers.dart';
|
||||||
|
|
||||||
class Routes {
|
class Routes {
|
||||||
|
static String root = "/";
|
||||||
static String demoSimple = "/demo";
|
static String demoSimple = "/demo";
|
||||||
|
static String demoSimpleFixedTrans = "/demo/fixedtrans";
|
||||||
static String demoFunc = "/demo/func";
|
static String demoFunc = "/demo/func";
|
||||||
static String deepLink = "/message";
|
static String deepLink = "/message";
|
||||||
|
|
||||||
static void configureRoutes(Router router) {
|
static void configureRoutes(Router router) {
|
||||||
|
router.notFoundHandler = Handler(
|
||||||
|
handlerFunc: (BuildContext context, Map<String, List<String>> params) {
|
||||||
|
print("ROUTE WAS NOT FOUND !!!");
|
||||||
|
});
|
||||||
|
router.define(root, handler: rootHandler);
|
||||||
router.define(demoSimple, handler: demoRouteHandler);
|
router.define(demoSimple, handler: demoRouteHandler);
|
||||||
|
router.define(demoSimpleFixedTrans,
|
||||||
|
handler: demoRouteHandler, transitionType: TransitionType.inFromLeft);
|
||||||
router.define(demoFunc, handler: demoFunctionHandler);
|
router.define(demoFunc, handler: demoFunctionHandler);
|
||||||
router.define(deepLink, handler: deepLinkHandler);
|
router.define(deepLink, handler: deepLinkHandler);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
@ -14,7 +15,6 @@ enum ContrastPreference {
|
||||||
}
|
}
|
||||||
|
|
||||||
class ColorHelpers {
|
class ColorHelpers {
|
||||||
|
|
||||||
static int fromHexString(String argbHexString) {
|
static int fromHexString(String argbHexString) {
|
||||||
String useString = argbHexString;
|
String useString = argbHexString;
|
||||||
if (useString.startsWith("#")) {
|
if (useString.startsWith("#")) {
|
||||||
|
@ -36,16 +36,22 @@ class ColorHelpers {
|
||||||
/// or lighter. If darker, will return white. If lighter, will return
|
/// or lighter. If darker, will return white. If lighter, will return
|
||||||
/// black. If the color is within 35-65% of the spectrum and a prefer
|
/// black. If the color is within 35-65% of the spectrum and a prefer
|
||||||
/// value is specified, then white or black will be preferred.
|
/// value is specified, then white or black will be preferred.
|
||||||
static Color blackOrWhiteContrastColor(Color sourceColor, {ContrastPreference prefer = ContrastPreference.none}) {
|
static Color blackOrWhiteContrastColor(Color sourceColor,
|
||||||
|
{ContrastPreference prefer = ContrastPreference.none}) {
|
||||||
// Will return a value between 0.0 (black) and 1.0 (white)
|
// Will return a value between 0.0 (black) and 1.0 (white)
|
||||||
double value = (((sourceColor.red * 299.0) + (sourceColor.green * 587.0) +
|
double value = (((sourceColor.red * 299.0) +
|
||||||
(sourceColor.blue * 114.0)) / 1000.0) / 255.0;
|
(sourceColor.green * 587.0) +
|
||||||
|
(sourceColor.blue * 114.0)) /
|
||||||
|
1000.0) /
|
||||||
|
255.0;
|
||||||
if (prefer != ContrastPreference.none) {
|
if (prefer != ContrastPreference.none) {
|
||||||
if (value >= _kMinContrastModifierRange && value <= _kMaxContrastModifierRange) {
|
if (value >= _kMinContrastModifierRange &&
|
||||||
return prefer == ContrastPreference.light ? new Color(0xFFFFFFFF) : new Color(0xFF000000);
|
value <= _kMaxContrastModifierRange) {
|
||||||
|
return prefer == ContrastPreference.light
|
||||||
|
? Color(0xFFFFFFFF)
|
||||||
|
: Color(0xFF000000);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return value > 0.6 ? new Color(0xFF000000) : new Color(0xFFFFFFFF);
|
return value > 0.6 ? Color(0xFF000000) : Color(0xFFFFFFFF);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
|
@ -1,13 +1,14 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
import 'components/app/app_component.dart';
|
import 'components/app/app_component.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
runApp(new AppComponent());
|
runApp(AppComponent());
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,6 +11,13 @@ flutter:
|
||||||
assets:
|
assets:
|
||||||
- assets/images/logo_fluro.png
|
- assets/images/logo_fluro.png
|
||||||
- assets/images/acc_boom.png
|
- assets/images/acc_boom.png
|
||||||
|
- assets/images/ic_result_hz.png
|
||||||
|
- assets/images/ic_function_hz.png
|
||||||
|
- assets/images/ic_transform_custom_hz.png
|
||||||
|
- assets/images/ic_transform_fade_in_hz.png
|
||||||
|
- assets/images/ic_transform_fade_out_hz.png
|
||||||
|
- assets/images/ic_transform_global_hz.png
|
||||||
|
- assets/images/ic_transform_native_hz.png
|
||||||
fonts:
|
fonts:
|
||||||
- family: Lazer84
|
- family: Lazer84
|
||||||
fonts:
|
fonts:
|
||||||
|
|
|
@ -1,16 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
library fluro;
|
library fluro;
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
export 'src/common.dart';
|
||||||
import 'package:flutter/material.dart';
|
export 'src/router.dart';
|
||||||
import 'package:flutter/widgets.dart';
|
export 'src/tree.dart';
|
||||||
|
|
||||||
part 'src/common.dart';
|
|
||||||
part 'src/router.dart';
|
|
||||||
part 'src/tree.dart';
|
|
||||||
|
|
|
@ -1,11 +1,13 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
part of fluro;
|
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
///
|
///
|
||||||
enum HandlerType {
|
enum HandlerType {
|
||||||
|
@ -15,22 +17,39 @@ enum HandlerType {
|
||||||
|
|
||||||
///
|
///
|
||||||
class Handler {
|
class Handler {
|
||||||
Handler({this.type = HandlerType.route, this.handlerFunc});
|
const Handler({this.type = HandlerType.route, this.handlerFunc});
|
||||||
final HandlerType type;
|
final HandlerType type;
|
||||||
final HandlerFunc handlerFunc;
|
final HandlerFunc handlerFunc;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
typedef Route<Null> RouteCreator(RouteSettings route, Map<String, dynamic> parameters);
|
typedef Route<T> RouteCreator<T>(
|
||||||
|
RouteSettings route, Map<String, List<String>> parameters);
|
||||||
|
|
||||||
///
|
///
|
||||||
typedef Widget HandlerFunc(BuildContext context, Map<String, dynamic> parameters);
|
typedef Widget HandlerFunc(
|
||||||
|
BuildContext context, Map<String, List<String>> parameters);
|
||||||
|
|
||||||
///
|
///
|
||||||
class AppRoute {
|
class AppRoute {
|
||||||
String route;
|
String route;
|
||||||
dynamic handler;
|
dynamic handler;
|
||||||
AppRoute(this.route, this.handler);
|
TransitionType transitionType;
|
||||||
|
AppRoute(this.route, this.handler, {this.transitionType});
|
||||||
|
}
|
||||||
|
|
||||||
|
enum TransitionType {
|
||||||
|
native,
|
||||||
|
nativeModal,
|
||||||
|
inFromLeft,
|
||||||
|
inFromRight,
|
||||||
|
inFromBottom,
|
||||||
|
fadeIn,
|
||||||
|
custom, // if using custom then you must also provide a transition
|
||||||
|
material,
|
||||||
|
materialFullScreenDialog,
|
||||||
|
cupertino,
|
||||||
|
cupertinoFullScreenDialog,
|
||||||
}
|
}
|
||||||
|
|
||||||
enum RouteMatchType {
|
enum RouteMatchType {
|
||||||
|
@ -41,12 +60,22 @@ enum RouteMatchType {
|
||||||
|
|
||||||
///
|
///
|
||||||
class RouteMatch {
|
class RouteMatch {
|
||||||
RouteMatch({
|
RouteMatch(
|
||||||
@required this.matchType = RouteMatchType.noMatch,
|
{this.matchType = RouteMatchType.noMatch,
|
||||||
this.route = null,
|
this.route,
|
||||||
this.errorMessage = "Unable to match route. Please check the logs."
|
this.errorMessage = "Unable to match route. Please check the logs."});
|
||||||
});
|
final Route<dynamic> route;
|
||||||
final Route<Null> route;
|
|
||||||
final RouteMatchType matchType;
|
final RouteMatchType matchType;
|
||||||
final String errorMessage;
|
final String errorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class RouteNotFoundException implements Exception {
|
||||||
|
final String message;
|
||||||
|
final String path;
|
||||||
|
RouteNotFoundException(this.message, this.path);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return "No registered route was found to handle '$path'";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,33 +1,35 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
part of fluro;
|
|
||||||
|
|
||||||
enum TransitionType {
|
import 'dart:async';
|
||||||
native,
|
|
||||||
nativeModal,
|
import 'package:fluro/fluro.dart';
|
||||||
inFromLeft,
|
import 'package:fluro/src/common.dart';
|
||||||
inFromRight,
|
import 'package:flutter/foundation.dart';
|
||||||
inFromBottom,
|
import 'package:flutter/cupertino.dart';
|
||||||
fadeIn,
|
import 'package:flutter/material.dart';
|
||||||
custom, // if using custom then you must also provide a transition
|
|
||||||
}
|
|
||||||
|
|
||||||
class Router {
|
class Router {
|
||||||
|
static final appRouter = Router();
|
||||||
|
|
||||||
/// The tree structure that stores the defined routes
|
/// The tree structure that stores the defined routes
|
||||||
RouteTree _routeTree = new RouteTree();
|
final RouteTree _routeTree = RouteTree();
|
||||||
|
|
||||||
/// Generic handler for when a route has not been defined
|
/// Generic handler for when a route has not been defined
|
||||||
Handler notFoundHandler;
|
Handler notFoundHandler;
|
||||||
|
|
||||||
/// Creates a [PageRoute] definition for the passed [RouteHandler]. You can optionally provide a custom
|
/// Creates a [PageRoute] definition for the passed [RouteHandler]. You can optionally provide a default transition type.
|
||||||
/// transition builder for the route.
|
void define(String routePath,
|
||||||
void define(String routePath, {@required Handler handler}) {
|
{@required Handler handler, TransitionType transitionType}) {
|
||||||
_routeTree.addRoute(new AppRoute(routePath, handler));
|
_routeTree.addRoute(
|
||||||
|
AppRoute(routePath, handler, transitionType: transitionType),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Finds a defined [AppRoute] for the path value. If no [AppRoute] definition was found
|
/// Finds a defined [AppRoute] for the path value. If no [AppRoute] definition was found
|
||||||
|
@ -36,74 +38,139 @@ class Router {
|
||||||
return _routeTree.matchRoute(path);
|
return _routeTree.matchRoute(path);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void pop(GlobalKey<NavigatorState> key) => key.currentState.pop();
|
||||||
|
|
||||||
///
|
///
|
||||||
void navigateTo(BuildContext context, String path, {bool replace = false, TransitionType transition = TransitionType.native,
|
Future navigateTo(GlobalKey<NavigatorState> key, String path,
|
||||||
Duration transitionDuration = const Duration(milliseconds: 250),
|
{bool replace = false,
|
||||||
RouteTransitionsBuilder transitionBuilder})
|
bool clearStack = false,
|
||||||
{
|
TransitionType transition,
|
||||||
RouteMatch routeMatch = matchRoute(context, path, transitionType: transition,
|
Duration transitionDuration = const Duration(milliseconds: 250),
|
||||||
transitionsBuilder: transitionBuilder, transitionDuration: transitionDuration);
|
RouteTransitionsBuilder transitionBuilder}) {
|
||||||
Route<Null> route = routeMatch.route;
|
RouteMatch routeMatch = matchRoute(key.currentContext, path,
|
||||||
|
transitionType: transition,
|
||||||
|
transitionsBuilder: transitionBuilder,
|
||||||
|
transitionDuration: transitionDuration);
|
||||||
|
Route<dynamic> route = routeMatch.route;
|
||||||
|
Completer completer = Completer();
|
||||||
|
Future future = completer.future;
|
||||||
if (routeMatch.matchType == RouteMatchType.nonVisual) {
|
if (routeMatch.matchType == RouteMatchType.nonVisual) {
|
||||||
return;
|
completer.complete("Non visual route type.");
|
||||||
}
|
|
||||||
if (route == null && notFoundHandler != null) {
|
|
||||||
route = _notFoundRoute(context, path);
|
|
||||||
}
|
|
||||||
if (route != null) {
|
|
||||||
replace ? Navigator.pushReplacement(context, route) : Navigator.push(context, route);
|
|
||||||
} else {
|
} else {
|
||||||
print("No registered route was found to handle '$path'.");
|
if (route == null && notFoundHandler != null) {
|
||||||
|
route = _notFoundRoute(path);
|
||||||
|
}
|
||||||
|
if (route != null) {
|
||||||
|
if (clearStack) {
|
||||||
|
future =
|
||||||
|
key.currentState.pushAndRemoveUntil(route, (check) => false);
|
||||||
|
} else {
|
||||||
|
future = replace
|
||||||
|
? key.currentState.pushReplacement(route)
|
||||||
|
: key.currentState.push(route);
|
||||||
|
}
|
||||||
|
completer.complete();
|
||||||
|
} else {
|
||||||
|
String error = "No registered route was found to handle '$path'.";
|
||||||
|
print(error);
|
||||||
|
completer.completeError(RouteNotFoundException(error, path));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
Route<Null> _notFoundRoute(BuildContext context, String path) {
|
Route<Null> _notFoundRoute(String path) {
|
||||||
RouteCreator creator = (RouteSettings routeSettings, Map<String, dynamic> parameters) {
|
RouteCreator<Null> creator =
|
||||||
return new MaterialPageRoute<Null>(settings: routeSettings, builder: (BuildContext context) {
|
(RouteSettings routeSettings, Map<String, List<String>> parameters) {
|
||||||
return notFoundHandler.handlerFunc(context, parameters);
|
return MaterialPageRoute<Null>(
|
||||||
});
|
settings: routeSettings,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return notFoundHandler.handlerFunc(context, parameters);
|
||||||
|
});
|
||||||
};
|
};
|
||||||
return creator(new RouteSettings(name: path), null);
|
return creator(RouteSettings(name: path), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
///
|
///
|
||||||
RouteMatch matchRoute(BuildContext buildContext, String path, {RouteSettings routeSettings = null,
|
RouteMatch matchRoute(BuildContext buildContext, String path,
|
||||||
TransitionType transitionType, Duration transitionDuration = const Duration(milliseconds: 250),
|
{RouteSettings routeSettings,
|
||||||
RouteTransitionsBuilder transitionsBuilder})
|
TransitionType transitionType,
|
||||||
{
|
Duration transitionDuration = const Duration(milliseconds: 250),
|
||||||
|
RouteTransitionsBuilder transitionsBuilder}) {
|
||||||
RouteSettings settingsToUse = routeSettings;
|
RouteSettings settingsToUse = routeSettings;
|
||||||
if (routeSettings == null) {
|
if (routeSettings == null) {
|
||||||
settingsToUse = new RouteSettings(name: path);
|
settingsToUse = RouteSettings(name: path);
|
||||||
}
|
}
|
||||||
AppRouteMatch match = _routeTree.matchRoute(path);
|
AppRouteMatch match = _routeTree.matchRoute(path);
|
||||||
AppRoute route = match?.route;
|
AppRoute route = match?.route;
|
||||||
Handler handler = (route != null ? route.handler : notFoundHandler);
|
Handler handler = (route != null ? route.handler : notFoundHandler);
|
||||||
if (route == null && notFoundHandler == null) {
|
var transition = transitionType;
|
||||||
return new RouteMatch(matchType: RouteMatchType.noMatch, errorMessage: "No matching route was found");
|
if (transitionType == null) {
|
||||||
|
transition = route != null ? route.transitionType : TransitionType.native;
|
||||||
}
|
}
|
||||||
Map<String, String> parameters = match?.parameters ?? <String, String>{};
|
if (route == null && notFoundHandler == null) {
|
||||||
|
return RouteMatch(
|
||||||
|
matchType: RouteMatchType.noMatch,
|
||||||
|
errorMessage: "No matching route was found");
|
||||||
|
}
|
||||||
|
Map<String, List<String>> parameters =
|
||||||
|
match?.parameters ?? <String, List<String>>{};
|
||||||
if (handler.type == HandlerType.function) {
|
if (handler.type == HandlerType.function) {
|
||||||
handler.handlerFunc(buildContext, parameters);
|
handler.handlerFunc(buildContext, parameters);
|
||||||
return new RouteMatch(matchType: RouteMatchType.nonVisual);
|
return RouteMatch(matchType: RouteMatchType.nonVisual);
|
||||||
}
|
}
|
||||||
|
|
||||||
RouteCreator creator = (RouteSettings routeSettings, Map<String, dynamic> parameters) {
|
RouteCreator creator =
|
||||||
bool isNativeTransition = (transitionType == TransitionType.native || transitionType == TransitionType.nativeModal);
|
(RouteSettings routeSettings, Map<String, List<String>> parameters) {
|
||||||
|
bool isNativeTransition = (transition == TransitionType.native ||
|
||||||
|
transition == TransitionType.nativeModal);
|
||||||
if (isNativeTransition) {
|
if (isNativeTransition) {
|
||||||
return new MaterialPageRoute<Null>(settings: routeSettings, fullscreenDialog: transitionType == TransitionType.nativeModal,
|
if (Theme.of(buildContext).platform == TargetPlatform.iOS) {
|
||||||
|
return CupertinoPageRoute<dynamic>(
|
||||||
|
settings: routeSettings,
|
||||||
|
fullscreenDialog: transition == TransitionType.nativeModal,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return handler.handlerFunc(context, parameters);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
return MaterialPageRoute<dynamic>(
|
||||||
|
settings: routeSettings,
|
||||||
|
fullscreenDialog: transition == TransitionType.nativeModal,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return handler.handlerFunc(context, parameters);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
} else if (transition == TransitionType.material ||
|
||||||
|
transition == TransitionType.materialFullScreenDialog) {
|
||||||
|
return MaterialPageRoute<dynamic>(
|
||||||
|
settings: routeSettings,
|
||||||
|
fullscreenDialog:
|
||||||
|
transition == TransitionType.materialFullScreenDialog,
|
||||||
|
builder: (BuildContext context) {
|
||||||
|
return handler.handlerFunc(context, parameters);
|
||||||
|
});
|
||||||
|
} else if (transition == TransitionType.cupertino ||
|
||||||
|
transition == TransitionType.cupertinoFullScreenDialog) {
|
||||||
|
return CupertinoPageRoute<dynamic>(
|
||||||
|
settings: routeSettings,
|
||||||
|
fullscreenDialog:
|
||||||
|
transition == TransitionType.cupertinoFullScreenDialog,
|
||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
return handler.handlerFunc(context, parameters);
|
return handler.handlerFunc(context, parameters);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
var routeTransitionsBuilder;
|
var routeTransitionsBuilder;
|
||||||
if (transitionType == TransitionType.custom) {
|
if (transition == TransitionType.custom) {
|
||||||
routeTransitionsBuilder = transitionsBuilder;
|
routeTransitionsBuilder = transitionsBuilder;
|
||||||
} else {
|
} else {
|
||||||
routeTransitionsBuilder = _standardTransitionsBuilder(transitionType);
|
routeTransitionsBuilder = _standardTransitionsBuilder(transition);
|
||||||
}
|
}
|
||||||
return new PageRouteBuilder<Null>(settings: routeSettings,
|
return PageRouteBuilder<dynamic>(
|
||||||
pageBuilder: (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
|
settings: routeSettings,
|
||||||
|
pageBuilder: (BuildContext context, Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation) {
|
||||||
return handler.handlerFunc(context, parameters);
|
return handler.handlerFunc(context, parameters);
|
||||||
},
|
},
|
||||||
transitionDuration: transitionDuration,
|
transitionDuration: transitionDuration,
|
||||||
|
@ -111,16 +178,18 @@ class Router {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
return new RouteMatch(
|
return RouteMatch(
|
||||||
matchType: RouteMatchType.visual,
|
matchType: RouteMatchType.visual,
|
||||||
route: creator(settingsToUse, parameters),
|
route: creator(settingsToUse, parameters),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
RouteTransitionsBuilder _standardTransitionsBuilder(TransitionType transitionType) {
|
RouteTransitionsBuilder _standardTransitionsBuilder(
|
||||||
return (BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation, Widget child) {
|
TransitionType transitionType) {
|
||||||
|
return (BuildContext context, Animation<double> animation,
|
||||||
|
Animation<double> secondaryAnimation, Widget child) {
|
||||||
if (transitionType == TransitionType.fadeIn) {
|
if (transitionType == TransitionType.fadeIn) {
|
||||||
return new FadeTransition(opacity: animation, child: child);
|
return FadeTransition(opacity: animation, child: child);
|
||||||
} else {
|
} else {
|
||||||
const Offset topLeft = const Offset(0.0, 0.0);
|
const Offset topLeft = const Offset(0.0, 0.0);
|
||||||
const Offset topRight = const Offset(1.0, 0.0);
|
const Offset topRight = const Offset(1.0, 0.0);
|
||||||
|
@ -135,8 +204,8 @@ class Router {
|
||||||
endOffset = topLeft;
|
endOffset = topLeft;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SlideTransition(
|
return SlideTransition(
|
||||||
position: new Tween<Offset>(
|
position: Tween<Offset>(
|
||||||
begin: startOffset,
|
begin: startOffset,
|
||||||
end: endOffset,
|
end: endOffset,
|
||||||
).animate(animation),
|
).animate(animation),
|
||||||
|
@ -149,8 +218,9 @@ class Router {
|
||||||
/// Route generation method. This function can be used as a way to create routes on-the-fly
|
/// Route generation method. This function can be used as a way to create routes on-the-fly
|
||||||
/// if any defined handler is found. It can also be used with the [MaterialApp.onGenerateRoute]
|
/// if any defined handler is found. It can also be used with the [MaterialApp.onGenerateRoute]
|
||||||
/// property as callback to create routes that can be used with the [Navigator] class.
|
/// property as callback to create routes that can be used with the [Navigator] class.
|
||||||
Route<Null> generator(RouteSettings routeSettings) {
|
Route<dynamic> generator(RouteSettings routeSettings) {
|
||||||
RouteMatch match = matchRoute(null, routeSettings.name, routeSettings: routeSettings);
|
RouteMatch match =
|
||||||
|
matchRoute(null, routeSettings.name, routeSettings: routeSettings);
|
||||||
return match.route;
|
return match.route;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
part of fluro;
|
|
||||||
|
import 'package:fluro/src/common.dart';
|
||||||
|
import 'package:flutter/widgets.dart';
|
||||||
|
|
||||||
enum RouteTreeNodeType {
|
enum RouteTreeNodeType {
|
||||||
component,
|
component,
|
||||||
|
@ -18,7 +21,7 @@ class AppRouteMatch {
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
AppRoute route;
|
AppRoute route;
|
||||||
Map<String, String> parameters = <String, String>{};
|
Map<String, List<String>> parameters = <String, List<String>>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
class RouteTreeNodeMatch {
|
class RouteTreeNodeMatch {
|
||||||
|
@ -26,7 +29,7 @@ class RouteTreeNodeMatch {
|
||||||
RouteTreeNodeMatch(this.node);
|
RouteTreeNodeMatch(this.node);
|
||||||
|
|
||||||
RouteTreeNodeMatch.fromMatch(RouteTreeNodeMatch match, this.node) {
|
RouteTreeNodeMatch.fromMatch(RouteTreeNodeMatch match, this.node) {
|
||||||
parameters = <String, String>{};
|
parameters = <String, List<String>>{};
|
||||||
if (match != null) {
|
if (match != null) {
|
||||||
parameters.addAll(match.parameters);
|
parameters.addAll(match.parameters);
|
||||||
}
|
}
|
||||||
|
@ -34,13 +37,12 @@ class RouteTreeNodeMatch {
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
RouteTreeNode node;
|
RouteTreeNode node;
|
||||||
Map<String, String> parameters = <String, String>{};
|
Map<String, List<String>> parameters = <String, List<String>>{};
|
||||||
}
|
}
|
||||||
|
|
||||||
class RouteTreeNode {
|
class RouteTreeNode {
|
||||||
// constructors
|
// constructors
|
||||||
RouteTreeNode(this.part,
|
RouteTreeNode(this.part, this.type);
|
||||||
this.type);
|
|
||||||
|
|
||||||
// properties
|
// properties
|
||||||
String part;
|
String part;
|
||||||
|
@ -56,7 +58,7 @@ class RouteTreeNode {
|
||||||
|
|
||||||
class RouteTree {
|
class RouteTree {
|
||||||
// private
|
// private
|
||||||
List<RouteTreeNode> _nodes = <RouteTreeNode>[];
|
final List<RouteTreeNode> _nodes = <RouteTreeNode>[];
|
||||||
bool _hasDefaultRoute = false;
|
bool _hasDefaultRoute = false;
|
||||||
|
|
||||||
// addRoute - add a route to the route tree
|
// addRoute - add a route to the route tree
|
||||||
|
@ -69,7 +71,7 @@ class RouteTree {
|
||||||
// could be affected
|
// could be affected
|
||||||
throw ("Default route was already defined");
|
throw ("Default route was already defined");
|
||||||
}
|
}
|
||||||
var node = new RouteTreeNode(path, RouteTreeNodeType.component);
|
var node = RouteTreeNode(path, RouteTreeNodeType.component);
|
||||||
node.routes = [route];
|
node.routes = [route];
|
||||||
_nodes.add(node);
|
_nodes.add(node);
|
||||||
_hasDefaultRoute = true;
|
_hasDefaultRoute = true;
|
||||||
|
@ -85,7 +87,7 @@ class RouteTree {
|
||||||
RouteTreeNode node = _nodeForComponent(component, parent);
|
RouteTreeNode node = _nodeForComponent(component, parent);
|
||||||
if (node == null) {
|
if (node == null) {
|
||||||
RouteTreeNodeType type = _typeForComponent(component);
|
RouteTreeNodeType type = _typeForComponent(component);
|
||||||
node = new RouteTreeNode(component, type);
|
node = RouteTreeNode(component, type);
|
||||||
node.parent = parent;
|
node.parent = parent;
|
||||||
if (parent == null) {
|
if (parent == null) {
|
||||||
_nodes.add(node);
|
_nodes.add(node);
|
||||||
|
@ -114,14 +116,16 @@ class RouteTree {
|
||||||
components = ["/"];
|
components = ["/"];
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<RouteTreeNode, RouteTreeNodeMatch> nodeMatches = <RouteTreeNode, RouteTreeNodeMatch>{};
|
Map<RouteTreeNode, RouteTreeNodeMatch> nodeMatches =
|
||||||
|
<RouteTreeNode, RouteTreeNodeMatch>{};
|
||||||
List<RouteTreeNode> nodesToCheck = _nodes;
|
List<RouteTreeNode> nodesToCheck = _nodes;
|
||||||
for (String checkComponent in components) {
|
for (String checkComponent in components) {
|
||||||
Map<RouteTreeNode, RouteTreeNodeMatch> currentMatches = <RouteTreeNode, RouteTreeNodeMatch>{};
|
Map<RouteTreeNode, RouteTreeNodeMatch> currentMatches =
|
||||||
|
<RouteTreeNode, RouteTreeNodeMatch>{};
|
||||||
List<RouteTreeNode> nextNodes = <RouteTreeNode>[];
|
List<RouteTreeNode> nextNodes = <RouteTreeNode>[];
|
||||||
for (RouteTreeNode node in nodesToCheck) {
|
for (RouteTreeNode node in nodesToCheck) {
|
||||||
String pathPart = checkComponent;
|
String pathPart = checkComponent;
|
||||||
Map<String, String> queryMap;
|
Map<String, List<String>> queryMap;
|
||||||
if (checkComponent.contains("?")) {
|
if (checkComponent.contains("?")) {
|
||||||
var splitParam = checkComponent.split("?");
|
var splitParam = checkComponent.split("?");
|
||||||
pathPart = splitParam[0];
|
pathPart = splitParam[0];
|
||||||
|
@ -130,10 +134,11 @@ class RouteTree {
|
||||||
bool isMatch = (node.part == pathPart || node.isParameter());
|
bool isMatch = (node.part == pathPart || node.isParameter());
|
||||||
if (isMatch) {
|
if (isMatch) {
|
||||||
RouteTreeNodeMatch parentMatch = nodeMatches[node.parent];
|
RouteTreeNodeMatch parentMatch = nodeMatches[node.parent];
|
||||||
RouteTreeNodeMatch match = new RouteTreeNodeMatch.fromMatch(parentMatch, node);
|
RouteTreeNodeMatch match =
|
||||||
|
RouteTreeNodeMatch.fromMatch(parentMatch, node);
|
||||||
if (node.isParameter()) {
|
if (node.isParameter()) {
|
||||||
String paramKey = node.part.substring(1);
|
String paramKey = node.part.substring(1);
|
||||||
match.parameters[paramKey] = pathPart;
|
match.parameters[paramKey] = [pathPart];
|
||||||
}
|
}
|
||||||
if (queryMap != null) {
|
if (queryMap != null) {
|
||||||
match.parameters.addAll(queryMap);
|
match.parameters.addAll(queryMap);
|
||||||
|
@ -156,9 +161,11 @@ class RouteTree {
|
||||||
RouteTreeNodeMatch match = matches.first;
|
RouteTreeNodeMatch match = matches.first;
|
||||||
RouteTreeNode nodeToUse = match.node;
|
RouteTreeNode nodeToUse = match.node;
|
||||||
// print("using match: ${match}, ${nodeToUse?.part}, ${match?.parameters}");
|
// print("using match: ${match}, ${nodeToUse?.part}, ${match?.parameters}");
|
||||||
if (nodeToUse != null && nodeToUse.routes != null && nodeToUse.routes.length > 0) {
|
if (nodeToUse != null &&
|
||||||
|
nodeToUse.routes != null &&
|
||||||
|
nodeToUse.routes.length > 0) {
|
||||||
List<AppRoute> routes = nodeToUse.routes;
|
List<AppRoute> routes = nodeToUse.routes;
|
||||||
AppRouteMatch routeMatch = new AppRouteMatch(routes[0]);
|
AppRouteMatch routeMatch = AppRouteMatch(routes[0]);
|
||||||
routeMatch.parameters = match.parameters;
|
routeMatch.parameters = match.parameters;
|
||||||
return routeMatch;
|
return routeMatch;
|
||||||
}
|
}
|
||||||
|
@ -211,13 +218,19 @@ class RouteTree {
|
||||||
return component.startsWith(":");
|
return component.startsWith(":");
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<String, String> parseQueryString(String query) {
|
Map<String, List<String>> parseQueryString(String query) {
|
||||||
var search = new RegExp('([^&=]+)=?([^&]*)');
|
var search = RegExp('([^&=]+)=?([^&]*)');
|
||||||
var params = new Map();
|
var params = Map<String, List<String>>();
|
||||||
if (query.startsWith('?')) query = query.substring(1);
|
if (query.startsWith('?')) query = query.substring(1);
|
||||||
decode(String s) => Uri.decodeComponent(s.replaceAll('+', ' '));
|
decode(String s) => Uri.decodeComponent(s.replaceAll('+', ' '));
|
||||||
for (Match match in search.allMatches(query)) {
|
for (Match match in search.allMatches(query)) {
|
||||||
params[decode(match.group(1))] = decode(match.group(2));
|
String key = decode(match.group(1));
|
||||||
|
String value = decode(match.group(2));
|
||||||
|
if (params.containsKey(key)) {
|
||||||
|
params[key].add(value);
|
||||||
|
} else {
|
||||||
|
params[key] = [value];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
14
pubspec.yaml
|
@ -1,8 +1,13 @@
|
||||||
name: fluro
|
name: fluro
|
||||||
description: The brightest, hippest, coolest router for Flutter.
|
description: >
|
||||||
version: 1.2.1
|
Fluro is a Flutter routing library that adds flexible routing options like wildcards, named
|
||||||
author: Posse Productions LLC <apps@goposse.com>
|
parameters and clear route definitions.
|
||||||
homepage: https://github.com/goposse/fluro
|
version: 1.6.3
|
||||||
|
homepage: https://github.com/theyakka/fluro
|
||||||
|
|
||||||
|
environment:
|
||||||
|
sdk: ">=2.6.0 <3.0.0"
|
||||||
|
flutter: ">=1.12.0"
|
||||||
|
|
||||||
dependencies:
|
dependencies:
|
||||||
flutter:
|
flutter:
|
||||||
|
@ -11,6 +16,7 @@ dependencies:
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
sdk: flutter
|
sdk: flutter
|
||||||
|
test: ^1.6.0
|
||||||
|
|
||||||
flutter:
|
flutter:
|
||||||
uses-material-design: false
|
uses-material-design: false
|
||||||
|
|
|
@ -1 +0,0 @@
|
||||||
git clone https://github.com/flutter/flutter.git -b alpha --depth 1
|
|
|
@ -1,49 +1,85 @@
|
||||||
/*
|
/*
|
||||||
* fluro
|
* fluro
|
||||||
* A Posse Production
|
* Created by Yakka
|
||||||
* http://goposse.com
|
* https://theyakka.com
|
||||||
* Copyright (c) 2017 Posse Productions LLC. All rights reserved.
|
*
|
||||||
|
* Copyright (c) 2019 Yakka, LLC. All rights reserved.
|
||||||
* See LICENSE for distribution and usage details.
|
* See LICENSE for distribution and usage details.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
import 'package:fluro/fluro.dart';
|
import 'package:fluro/fluro.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
|
testWidgets("Router correctly parses named parameters",
|
||||||
testWidgets("Router correctly parses named parameters", (WidgetTester tester) async {
|
(WidgetTester tester) async {
|
||||||
String path = "/users/1234";
|
String path = "/users/1234";
|
||||||
String route = "/users/:id";
|
String route = "/users/:id";
|
||||||
Router router = new Router();
|
Router router = Router();
|
||||||
router.define(route, handler: null);
|
router.define(route, handler: null);
|
||||||
AppRouteMatch match = router.match(path);
|
AppRouteMatch match = router.match(path);
|
||||||
expect(match?.parameters, equals(<String, String>{
|
expect(
|
||||||
"id" : "1234",
|
match?.parameters,
|
||||||
}));
|
equals(<String, List<String>>{
|
||||||
|
"id": ["1234"],
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets("Router correctly parses named parameters with query", (WidgetTester tester) async {
|
testWidgets("Router correctly parses named parameters with query",
|
||||||
|
(WidgetTester tester) async {
|
||||||
String path = "/users/1234?name=luke";
|
String path = "/users/1234?name=luke";
|
||||||
String route = "/users/:id";
|
String route = "/users/:id";
|
||||||
Router router = new Router();
|
Router router = Router();
|
||||||
router.define(route, handler: null);
|
router.define(route, handler: null);
|
||||||
AppRouteMatch match = router.match(path);
|
AppRouteMatch match = router.match(path);
|
||||||
expect(match?.parameters, equals(<String, String>{
|
expect(
|
||||||
"id" : "1234",
|
match?.parameters,
|
||||||
"name" : "luke",
|
equals(<String, List<String>>{
|
||||||
}));
|
"id": ["1234"],
|
||||||
|
"name": ["luke"],
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
testWidgets("Router correctly parses query parameters", (WidgetTester tester) async {
|
testWidgets("Router correctly parses query parameters",
|
||||||
|
(WidgetTester tester) async {
|
||||||
String path = "/users/create?name=luke&phrase=hello%20world&number=7";
|
String path = "/users/create?name=luke&phrase=hello%20world&number=7";
|
||||||
String route = "/users/create";
|
String route = "/users/create";
|
||||||
Router router = new Router();
|
Router router = Router();
|
||||||
router.define(route, handler: null);
|
router.define(route, handler: null);
|
||||||
AppRouteMatch match = router.match(path);
|
AppRouteMatch match = router.match(path);
|
||||||
expect(match?.parameters, equals(<String, String>{
|
expect(
|
||||||
"name" : "luke",
|
match?.parameters,
|
||||||
"phrase" : "hello world",
|
equals(<String, List<String>>{
|
||||||
"number" : "7",
|
"name": ["luke"],
|
||||||
}));
|
"phrase": ["hello world"],
|
||||||
|
"number": ["7"],
|
||||||
|
}));
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
testWidgets("Router correctly parses array parameters",
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
String path =
|
||||||
|
"/users/create?name=luke&phrase=hello%20world&number=7&number=10&number=13";
|
||||||
|
String route = "/users/create";
|
||||||
|
Router router = Router();
|
||||||
|
router.define(route, handler: null);
|
||||||
|
AppRouteMatch match = router.match(path);
|
||||||
|
expect(
|
||||||
|
match?.parameters,
|
||||||
|
equals(<String, List<String>>{
|
||||||
|
"name": ["luke"],
|
||||||
|
"phrase": ["hello world"],
|
||||||
|
"number": ["7", "10", "13"],
|
||||||
|
}));
|
||||||
|
});
|
||||||
|
testWidgets("Router correctly matches route and transition type",
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
String path = "/users/1234";
|
||||||
|
String route = "/users/:id";
|
||||||
|
Router router = Router();
|
||||||
|
router.define(route,
|
||||||
|
handler: null, transitionType: TransitionType.inFromRight);
|
||||||
|
AppRouteMatch match = router.match(path);
|
||||||
|
expect(TransitionType.inFromRight, match.route.transitionType);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,3 @@
|
||||||
|
#!/bin/sh
|
||||||
|
set -e
|
||||||
|
$TRAVIS_BUILD_DIR/flutter/bin/flutter test --coverage
|