Full Code of gfaraday/g_faraday for AI

develop f6f73d59812b cached
224 files
384.1 KB
110.4k tokens
175 symbols
1 requests
Download .txt
Showing preview only (452K chars total). Download the full file or copy to clipboard to get everything.
Repository: gfaraday/g_faraday
Branch: develop
Commit: f6f73d59812b
Files: 224
Total size: 384.1 KB

Directory structure:
gitextract_t4tm_p0m/

├── .fvm/
│   └── fvm_config.json
├── .gitattributes
├── .github/
│   ├── labeler.yml
│   └── workflows/
│       ├── greetings.yml
│       ├── label.yml
│       └── publish.yml
├── .gitignore
├── .metadata
├── .vscode/
│   ├── launch.json
│   └── settings.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── README_EN.md
├── analysis_options.yaml
├── android/
│   ├── .gitignore
│   ├── app/
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── io/
│   │                   └── flutter/
│   │                       └── plugins/
│   │                           └── GeneratedPluginRegistrant.java
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   ├── settings.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── kotlin/
│               └── com/
│                   └── yuxiaor/
│                       └── flutter/
│                           └── g_faraday/
│                               ├── Faraday.kt
│                               ├── FaradayActivity.kt
│                               ├── FaradayColorBaseSplashScreen.kt
│                               ├── FaradayConstants.kt
│                               ├── FaradayFragment.kt
│                               ├── FaradayNavigator.kt
│                               ├── GFaradayPlugin.kt
│                               ├── ResultProvider.kt
│                               └── channels/
│                                   ├── CommonChannel.kt
│                                   ├── NavigatorAnchor.kt
│                                   ├── NetChannel.kt
│                                   └── NoticeChannel.kt
├── doc/
│   ├── bridge.md
│   ├── callback.md
│   ├── ci.md
│   ├── ios-simulator-install.md
│   ├── ios_navigation_bar.md
│   ├── json.md
│   ├── net.md
│   ├── notification.md
│   └── route.md
├── example/
│   ├── .gitignore
│   ├── .metadata
│   ├── .vscode/
│   │   ├── launch.json
│   │   └── settings.json
│   ├── README.md
│   ├── analysis_options.yaml
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   ├── release/
│   │   │   │   └── output-metadata.json
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── com/
│   │   │       │   │       └── yuxiaor/
│   │   │       │   │           └── flutter/
│   │   │       │   │               └── g_faraday_example/
│   │   │       │   │                   ├── App.kt
│   │   │       │   │                   ├── activity/
│   │   │       │   │                   │   ├── MainActivity.kt
│   │   │       │   │                   │   ├── SingleTaskFlutterActivity.kt
│   │   │       │   │                   │   ├── SingleTopFlutterActivity.kt
│   │   │       │   │                   │   └── splash/
│   │   │       │   │                   │       └── FirstFlutterActivity.kt
│   │   │       │   │                   ├── basic/
│   │   │       │   │                   │   ├── FlutterToNativeActivity.kt
│   │   │       │   │                   │   ├── Native2FlutterActivity.kt
│   │   │       │   │                   │   ├── TabContainerActivity.kt
│   │   │       │   │                   │   ├── TransparentBackgroundFlutterActivity.kt
│   │   │       │   │                   │   └── fragments/
│   │   │       │   │                   │       └── NativeFragment.kt
│   │   │       │   │                   ├── faraday/
│   │   │       │   │                   │   └── CustomNavigator.kt
│   │   │       │   │                   ├── fragment/
│   │   │       │   │                   │   └── TestFragment.kt
│   │   │       │   │                   ├── utils/
│   │   │       │   │                   │   └── ViewExt.kt
│   │   │       │   │                   └── widget/
│   │   │       │   │                       ├── BaseDialog.kt
│   │   │       │   │                       └── NotificationDialog.kt
│   │   │       │   └── res/
│   │   │       │       ├── anim/
│   │   │       │       │   ├── in_from_left.xml
│   │   │       │       │   ├── in_from_right.xml
│   │   │       │       │   ├── out_from_left.xml
│   │   │       │       │   └── out_from_right.xml
│   │   │       │       ├── color/
│   │   │       │       │   └── check_primary_light.xml
│   │   │       │       ├── drawable/
│   │   │       │       │   ├── launch_background.xml
│   │   │       │       │   ├── tab_file.xml
│   │   │       │       │   ├── tab_home.xml
│   │   │       │       │   ├── tab_house.xml
│   │   │       │       │   └── tab_msg.xml
│   │   │       │       ├── layout/
│   │   │       │       │   ├── activity_flutter2native.xml
│   │   │       │       │   ├── activity_fragment.xml
│   │   │       │       │   ├── activity_main.xml
│   │   │       │       │   ├── activity_native2flutter.xml
│   │   │       │       │   ├── activity_tab_container.xml
│   │   │       │       │   ├── dialog_notification.xml
│   │   │       │       │   └── frag_test.xml
│   │   │       │       ├── navigation/
│   │   │       │       │   └── nav_graph.xml
│   │   │       │       ├── values/
│   │   │       │       │   ├── colors.xml
│   │   │       │       │   ├── strings.xml
│   │   │       │       │   └── styles.xml
│   │   │       │       └── values-v31/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   └── settings.gradle
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── Contents.json
│   │   │   │   ├── LaunchImage.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── logo.imageset/
│   │   │   │       └── Contents.json
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── Faraday/
│   │   │   │   ├── FaradayCommon.swift
│   │   │   │   ├── FaradayNet.swift
│   │   │   │   └── FaradayRoute.swift
│   │   │   ├── GeneratedPluginRegistrant.h
│   │   │   ├── GeneratedPluginRegistrant.m
│   │   │   ├── Info.plist
│   │   │   ├── Runner-Bridging-Header.h
│   │   │   └── ViewControllers/
│   │   │       ├── BaseViewController.swift
│   │   │       ├── Basic/
│   │   │       │   ├── Flutter2NativeViewController.swift
│   │   │       │   ├── Flutter2NativeViewController.xib
│   │   │       │   ├── Native2FlutterViewController.swift
│   │   │       │   ├── Native2FlutterViewController.xib
│   │   │       │   └── TabContainer/
│   │   │       │       ├── Tab1ViewController.swift
│   │   │       │       ├── Tab2ViewController.swift
│   │   │       │       ├── TabContainer.storyboard
│   │   │       │       └── TabSplitViewController.swift
│   │   │       ├── MainavigationViewController.swift
│   │   │       ├── Others/
│   │   │       │   ├── NeedNavigationBarViewController.swift
│   │   │       │   ├── NoNavigationBarViewController.swift
│   │   │       │   └── Other.storyboard
│   │   │       ├── Splash/
│   │   │       │   └── HomeFlutterViewController.swift
│   │   │       └── Tab0ViewController.swift
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           ├── IDEWorkspaceChecks.plist
│   │           └── WorkspaceSettings.xcsettings
│   ├── lib/
│   │   ├── fluro_router.dart
│   │   ├── main.dart
│   │   ├── main_fluro.dart
│   │   ├── main_get.dart
│   │   └── src/
│   │       ├── debug/
│   │       │   └── debug.dart
│   │       ├── pages/
│   │       │   ├── example_page_scaffold.dart
│   │       │   ├── features/
│   │       │   │   ├── basic/
│   │       │   │   │   ├── basic.dart
│   │       │   │   │   └── pages/
│   │       │   │   │       ├── flutter_to_flutter.dart
│   │       │   │   │       ├── flutter_to_native.dart
│   │       │   │   │       ├── native_to_flutter.dart
│   │       │   │   │       ├── tab_page.dart
│   │       │   │   │       └── transparent_page.dart
│   │       │   │   ├── notification/
│   │       │   │   │   └── notification.dart
│   │       │   │   ├── other/
│   │       │   │   │   └── other.dart
│   │       │   │   └── splash/
│   │       │   │       └── splash.dart
│   │       │   └── home_page.dart
│   │       ├── utils/
│   │       │   ├── observer.dart
│   │       │   └── simple_localizations.dart
│   │       └── widgets/
│   │           ├── action.dart
│   │           └── section.dart
│   ├── pubspec.yaml
│   └── test/
│       └── widget_test.dart
├── example_objc_only/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.h
│   │   │   ├── AppDelegate.m
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── LaunchImage.imageset/
│   │   │   │       ├── Contents.json
│   │   │   │       └── README.md
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── DemoViewController.h
│   │   │   ├── DemoViewController.m
│   │   │   ├── FaradayHelper.swift
│   │   │   ├── Info.plist
│   │   │   ├── Runner-Bridging-Header.h
│   │   │   └── main.m
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           ├── IDEWorkspaceChecks.plist
│   │           └── WorkspaceSettings.xcsettings
│   ├── lib/
│   │   └── main.dart
│   ├── pubspec.yaml
│   └── test/
│       └── widget_test.dart
├── g_faraday.iml
├── ios/
│   ├── .gitignore
│   ├── Assets/
│   │   └── .gitkeep
│   ├── Classes/
│   │   ├── Faraday.swift
│   │   ├── FaradayExtended.swift
│   │   ├── FaradayFlutterViewController.swift
│   │   ├── FlutterEngine+Identifier.swift
│   │   ├── GFaradayPlugin.h
│   │   ├── GFaradayPlugin.m
│   │   ├── NotificationCenter+Faraday.swift
│   │   ├── Options.swift
│   │   ├── SwiftGFaradayPlugin.swift
│   │   ├── UIViewController+Faraday.swift
│   │   ├── UIViewController+Swizzle.swift
│   │   └── UIViewController+TopMost.swift
│   └── g_faraday.podspec
├── lib/
│   ├── g_faraday.dart
│   └── src/
│       ├── common/
│       │   ├── common.dart
│       │   ├── entry.dart
│       │   └── net.dart
│       ├── faraday.dart
│       ├── route/
│       │   ├── arg.dart
│       │   ├── native_bridge.dart
│       │   ├── navigator.dart
│       │   ├── navigator_ext.dart
│       │   ├── observer.dart
│       │   ├── options.dart
│       │   └── route.dart
│       └── widgets/
│           ├── debugger.dart
│           ├── log.dart
│           └── notification_listener.dart
└── pubspec.yaml

================================================
FILE CONTENTS
================================================

================================================
FILE: .fvm/fvm_config.json
================================================
{
  "flutterSdkVersion": "3.16.9",
  "flavors": {}
}

================================================
FILE: .gitattributes
================================================
*.swift linguist-language=dart
*.kt linguist-language=dart
*.java linguist-language=dart
*.rb linguist-language=dart


================================================
FILE: .github/labeler.yml
================================================
repo:
  - ./*
  
ios:
  - ios/**/*.swift

android:
  - android/**/*.java
  - android/**/*.kt

flutter:
  - src/**/*.dart


================================================
FILE: .github/workflows/greetings.yml
================================================
name: Greetings

on: [pull_request, issues]

jobs:
  greeting:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/first-interaction@v1
      with:
        repo-token: ${{ secrets.GITHUB_TOKEN }}
        issue-message: 'first issue 🚀'
        pr-message: 'first pr 👍'


================================================
FILE: .github/workflows/label.yml
================================================
# This workflow will triage pull requests and apply a label based on the
# paths that are modified in the pull request.
#
# To use this workflow, you will need to set up a .github/labeler.yml
# file with configuration.  For more information, see:
# https://github.com/actions/labeler

name: Labeler
on: [pull_request]

jobs:
  label:

    runs-on: ubuntu-latest

    steps:
    - uses: actions/labeler@v2
      with:
        repo-token: "${{ secrets.GITHUB_TOKEN }}"


================================================
FILE: .github/workflows/publish.yml
================================================
# This is a basic workflow to help you get started with Actions

name: Publisher

on:
  push:
    branches: [master]

  workflow_dispatch:

env:
  GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

jobs:
  check_version:
    name: Check Version
    runs-on: ubuntu-latest
    outputs:
      git_tag_name: ${{ steps.tag_check.outputs.git_tag_name }}
    steps:
      - uses: actions/checkout@v2 # https://github.com/actions/checkout

      - uses: CumulusDS/get-yaml-paths-action@v0.1.0
        id: get_package_version
        with:
          file: pubspec.yaml
          version: version
      # debug
      - name: Output package version
        run: echo 'version:' ${{ steps.get_package_version.outputs.version }}

      - uses: dudo/tag_check@v1.0.2
        id: tag_check
        with:
          version: ${{ steps.get_package_version.outputs.version }}
          git_tag_prefix: v

  push_tag:
    name: Push Tag
    needs: check_version
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2 # https://github.com/actions/checkout

      - name: push tag
        uses: anothrNick/github-tag-action@1.36.0
        env:
          GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
          CUSTOM_TAG: ${{ needs.check_version.outputs.git_tag_name }}
          SOURCE: master

  publish_pub:
    name: Publish new Pub version
    needs: check_version
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v2
      - name: Publish Dart/Flutter package
        uses: sakebook/actions-flutter-pub-publisher@v1.3.1
        with:
          credential: ${{ secrets.PUB_PUBLISHER_CREDENTIAL_JSON }}
          flutter_package: true
          skip_test: true
          dry_run: false


================================================
FILE: .gitignore
================================================
.DS_Store
.dart_tool/
.idea

.packages
.pub/

build/
.flutter-plugins

android-aar-repo
ios-frameworks
.faraday.json

================================================
FILE: .metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
  revision: bbfbf1770cca2da7c82e887e4e4af910034800b6
  channel: stable

project_type: plugin


================================================
FILE: .vscode/launch.json
================================================
{
  // 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": "g_faraday attach",
      "type": "dart",
      "request": "attach",
      "program": "example/lib/main.dart"
    },
    {
      "name": "g_faraday debug",
      "program": "example/lib/main.dart",
      "request": "launch",
      "type": "dart"
    },
  ]
}

================================================
FILE: .vscode/settings.json
================================================
{
  "cSpell.words": [
    "anothr",
    "ARGB",
    "BUPT",
    "cocoapod",
    "cocoapods",
    "Dealloc",
    "Deallocation",
    "dudo",
    "executables",
    "fluro",
    "fullscreen",
    "Podfile",
    "recase",
    "sakebook",
    "Scrollable",
    "simctl",
    "xcrun"
  ]
}

================================================
FILE: CHANGELOG.md
================================================
# 1.0.2
* Fix NPE when platform plugin delegate is null

# 1.0.1

* migrate to flutter 3.16.9
* ios add FaradayNavigationControllerBarHiddenProtocol

# 1.0.0

* migrate to flutter 3.0.5
* rewrite android plugin

## 1.0.0-beta.1

* migrate to flutter 3.0.3
* rewrite android plugin

## 0.7.2

* migrate to flutter 2.5.0
* fix typo
  
## 0.7.1

* fix refresh error when save file

## 0.7.0

* migrate to flutter 2.0

## 0.6.0-nullsafety.33

* fix typo

## 0.6.0-nullsafety.32

* add top navigator accessor
* add top context accessor
* compatible with objc

## 0.5.1-nullsafety.31

* add navigator observer
  
## 0.5.1-nullsafety.30

* refactor logger
* improve widget dispose logic after native container dealloc

## 0.5.1-nullsafety.29

* [android] fix status bar style

## 0.5.1-nullsafety.28

* [ios] reset additionalSafeAreaInsets
* [android] refactor `initEngine` to `startEngine`
  
## 0.5.1-nullsafety.27

* [ios] post status bar notification

## 0.5.1-nullsafety.26

* [android] downgrade minSdkVersion to 16
  
## 0.5.1-nullsafety.25

* [ios] fix ios notification issue

## 0.5.1-nullsafety.24

* [ios] refine swipe pop gesture
* refine example project

## 0.5.1-nullsafety.23

* remove useless asset

## 0.5.1-nullsafety.22

* [ios] resize channel buffer
  
## 0.5.1-nullsafety.21

* remove navigator anchor
* [android] refine `onNewIntent`

## 0.5.1-nullsafety.20

* add anchor native api
* [android] fix splash reuse issue

## 0.5.1-nullsafety.19

* fix page dealloc logic
  
## 0.5.1-nullsafety.18

* add popToAnchor native api

## 0.5.1-nullsafety.17

* compatible xcode 11.5

## 0.5.1-nullsafety.16

* support pop to any flutter route

## 0.5.1-nullsafety.15

* refine options default value

## 0.5.1-nullsafety.14

* refine options api

## 0.5.1-nullsafety.13

* downgrade flutter version to 1.24.0-10.2.pre

## 0.5.1-nullsafety.12

* revert FaradayBrdige of api

## 0.5.1-nullsafety.11

* refine notification api

## 0.5.1-nullsafety.10

* [android] fix splash issue

## 0.5.1-nullsafety.9

* [android] make route&params public
* add more examples

## 0.5.1-nullsafety.8

* [ios] refine callback api
* migrate to `Flutter 1.25.0-8.1.pre`

## 0.5.0-nullsafety.7

* [ios] refine push api
* refine nullsafety

## 0.5.0-nullsafety.6

* [ios] fix pop gesture logic

## 0.5.0-nullsafety.5

* upgrade json package to 4.0.0.nullsafety.2

## 0.5.0-nullsafety.4

* upgrade json package to 4.0.0.nullsafety.1

## 0.5.0-nullsafety.3

* [ios] fix callback issue
* add invokeMapMethod&invokeListMethod for common channel

## 0.5.0-nullsafety.2

* fix navigator onGenerateInitialRouteIssue

## 0.5.0-nullsafety.1

* [ios] make flutter engine public

## 0.5.0-nullsafety.0

* support null safety basically

## 0.4.3-pre.3

* refine android activity lifecycle

## 0.4.3-pre.2

* detach activity before destroy

## 0.4.3-pre.1

* test publish by github action

## 0.4.3-pre.0

* refactor activity builder api

## 0.4.2

* add examples

## 0.4.2-pre.2

* fix Activity animation issue
* fix ViewController swipe back gesture

## 0.4.2-pre.1

* Support custom splash screen with pure color

## 0.4.2-pre.0

* Support activity all launch modes
* Support custom transition animation
* Support transparent background

## 0.4.1-pre.1

* Support Activity animation
* Support Fragment

## 0.4.1-pre.0

* Remove Page.Hidden event
* Custom FlutterActivity

## 0.4.0

* Support hybrid route stack.
* Automatically handle ios navigation bar hidden/show.
* Support `WillPopScope` widget.
* Send/Receive global notification.
* Complete documentation.


================================================
FILE: CONTRIBUTING.md
================================================
# Contributing to g_faraday

## 1. Things you will need

- Linux, Mac OS X, or Windows.
- [git](https://git-scm.com) (used for source version control).
- An IDE such as [Android Studio](https://developer.android.com/studio) or [Visual Studio Code](https://code.visualstudio.com/).

## 2. Forking & cloning the repository

- Ensure all the dependencies described in the previous section are installed.
- Fork `https://github.com/gfaraday/g_faraday` into your own GitHub account. If
  you already have a fork, and are now installing a development environment on
  a new machine, make sure you've updated your fork so that you don't use stale
  configuration options from long ago.
- `git clone git@github.com:<your_name_here>/g_faraday.git`
- `git remote add upstream git@github.com:g_faraday/g_faraday.git` (So that you
  fetch from the master repository, not your clone, when running `git fetch`
  et al.)

## TODO


================================================
FILE: LICENSE
================================================
Copyright (c) 2020 Faraday Team (http://www.faraday.中国)

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.

================================================
FILE: README.md
================================================
# ![log](./doc/images/logo.png)  Faraday [English](./README_EN.md)

![Build](https://img.shields.io/github/workflow/status/gfaraday/g_faraday/Publisher/master?logo=github&style=for-the-badge)
![pub_Version](https://img.shields.io/pub/v/g_faraday?include_prereleases&style=for-the-badge&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNjAwcHgiIGhlaWdodD0iNjAwcHgiIHZpZXdCb3g9IjAgMCA2MDAgNjAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPHRpdGxlPmZhcmFkYXk8L3RpdGxlPgogICAgPGRlZnM+CiAgICAgICAgPGxpbmVhckdyYWRpZW50IHgxPSIxMC42ODAxNzA0JSIgeTE9IjI2Ljk5MzAyODclIiB4Mj0iNzIuMTEzMDU3NiUiIHkyPSI1Mi45MTkyNjU3JSIgaWQ9ImxpbmVhckdyYWRpZW50LTEiPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMDAwMDAwIiBvZmZzZXQ9IjAlIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMCIgb2Zmc2V0PSIxMDAlIj48L3N0b3A+CiAgICAgICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJmYXJhZGF5IiBmaWxsLXJ1bGU9Im5vbnplcm8iPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAiPgogICAgICAgICAgICAgICAgPGcgaWQ9ImZsdXR0ZXItc2Vla2xvZ28uY29tIj4KICAgICAgICAgICAgICAgICAgICA8cG9seWdvbiBpZD0iUGF0aCIgZmlsbD0iI0VCRkNGNCIgcG9pbnRzPSIyMDQuNTY2ODQ1IDAgMCAyMjEuOTI4NzQ2IDYzLjMxNzM1OSAyOTAuNjE5OTQ2IDMzMS4yMDI5ODkgMCI+PC9wb2x5Z29uPgogICAgICAgICAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJQYXRoIiBmaWxsPSIjRUJGQ0Y0IiBwb2ludHM9IjIwMy4zNDU5MzggMjA0LjI0MTI0IDkzLjk5MDAzNzQgMzIyLjYyMDg5OSAxNTcuNDQzOTAxIDM5Mi4zMzY5MjcgMjIwLjU0MzM2OCAzMjQuMDMwNjU4IDMzMS4yMDI5ODkgMjA0LjI0MTI0Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIGZpbGw9IiNFQkZDRjQiIHBvaW50cz0iMTU3LjM5NjAxNSAzOTIuODE5ODQxIDIwNS40NDUxNzMgNDQ0LjgwOTk3MyAzMzEuMjAyOTg5IDQ0NC44MDk5NzMgMjIwLjUxMTk2NSAzMjQuNTI1NjA2Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIGZpbGw9IiNFQkZDRjQiIHBvaW50cz0iOTMuMjQ0MDg0NyAzMjMuODY0MiAxNTYuNjA3OTA4IDI1NS4wOTk3MyAyMjAuODAxOTkzIDMyNC41MDgyMzIgMTU3LjU1ODAwMSAzOTMuMTQ0MjA1Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIGZpbGwtb3BhY2l0eT0iMC44IiBmaWxsPSJ1cmwoI2xpbmVhckdyYWRpZW50LTEpIiBwb2ludHM9IjE1Ny4zOTYwMTUgMzkyLjMzNjkyNyAyMTAuMzIyOTA0IDM3My4zMzA1NzYgMjE1LjU4MDMyNCAzMjkuMzY5MjcyIj48L3BvbHlnb24+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZmx1dHRlci1zZWVrbG9nby5jb20iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2Ny43OTcwMTEsIDE1NC4xOTAwMjcpIiBmaWxsPSIjRUJGQ0Y0Ij4KICAgICAgICAgICAgICAgICAgICA8cG9seWdvbiBpZD0iUGF0aCIgcG9pbnRzPSIyMDQuNTY2ODQ1IDAgMCAyMjEuOTI4NzQ2IDYzLjMxNzM1OSAyOTAuNjE5OTQ2IDMzMS4yMDI5ODkgMCI+PC9wb2x5Z29uPgogICAgICAgICAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJQYXRoIiBwb2ludHM9IjIwMy4zNDU5MzggMjA0LjI0MTI0IDkzLjk5MDAzNzQgMzIyLjYyMDg5OSAxNTcuNDQzOTAxIDM5Mi4zMzY5MjcgMjIwLjU0MzM2OCAzMjQuMDMwNjU4IDMzMS4yMDI5ODkgMjA0LjI0MTI0Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIHBvaW50cz0iMTU3LjM5NjAxNSAzOTIuODE5ODQxIDIwNS40NDUxNzMgNDQ0LjgwOTk3MyAzMzEuMjAyOTg5IDQ0NC44MDk5NzMgMjIwLjUxMTk2NSAzMjQuNTI1NjA2Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIHBvaW50cz0iOTMuMjQ0MDg0NyAzMjMuODY0MiAxNTYuNjA3OTA4IDI1NS4wOTk3MyAyMjAuODAxOTkzIDMyNC41MDgyMzIgMTU3LjU1ODAwMSAzOTMuMTQ0MjA1Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==)
![Flutter_Version](https://img.shields.io/badge/Flutter-stable-blue?style=for-the-badge&logo=flutter)
![License](https://img.shields.io/github/license/gfaraday/g_faraday?style=for-the-badge)

[一个`Flutter`混合栈开发解决方案](https://juejin.cn/post/6911985354488676365)

## Features

- [x] 支持`ios`、`android`、`flutter`三端所有原生路由(页面切换)跳转行为
- [x] 支持混合栈(native -> flutter -> native)路由跳转(popTo、replace ...)
- [x] 支持flutter页面作为root页面
- [x] 支持flutter作为子页面加入原生堆栈
- [x] 支持flutter作为弹出页面(背景透明到native层)
- [x] [页面间回调传值完整支持](doc/callback.md)
- [x] [iOS导航条自动隐藏/显示](doc/ios_navigation_bar.md)
- [x] `WillPopScope`拦截滑动返回(ios)或者返回按键键(android)
- [x] [发送/接收全局通知](doc/notification.md)
- [x] 支持自定义页面切换动画
- [x] 支持完整的生命周期监听
- [ ] 单元测试
- [x] 完整的文档(7/10)

## 使用`g_faraday`的APP

| 序号 | 名称   | 版本号 | iOS                                                                            | Android                                                         |
| ---- | ------ | ------ | ------------------------------------------------------------------------------ | --------------------------------------------------------------- |
| 0    | 寓小二 | 8.0.0  | [AppStore](https://apps.apple.com/cn/app/寓小二-公寓系统定制专家/id1081403007) | [应用宝](https://a.app.qq.com/o/simple.jsp?pkgname=com.yuxiaor) |

> 您的app也在使用?[联系我们](#Communication)

## Show Cases

![demo](doc/images/demo.png)

## Example App

[Android下载apk](https://github.com/gfaraday/g_faraday/releases/download/v0.5.0-nullsafety.3/appv2.apk)

<!-- [iOS下载app](https://github.com/gfaraday/g_faraday/releases/download/0.4.2/example.app.zip)
> [模拟器安装app](doc/ios-simulator-install.md) -->

## 设计原则

- 对原有平台最小侵入
- 对现有代码最小改动
- API尽量保持和原有平台一致

## 更新策略

_Flutter **stable channel** 发布后 **一周内**适配发布对应的`g_faraday`版本_

## Requirements

- Flutter 3.0.5 • channel stable
- iOS 10.0+ Xcode 12.0+ Swift 5.1+
- Android minSdkVersion 16 Kotlin 1.4.10+

## 版本对应关系

| g_faraday           | flutter                                                                   | cocoapods | remark        |
| ------------------- | ------------------------------------------------------------------------- | --------- | ------------- |
| ^1.0.0       | Flutter 3.0.5 • channel stable • `https://github.com/flutter/flutter.git`   | any       | recommend        |
| ^1.0.0-beta.1       | Flutter 3.0.3 • channel stable • `https://github.com/flutter/flutter.git`   | any       | not recommend        |
| ^0.7.2              | Flutter 2.5.0 • channel stable • `https://github.com/flutter/flutter.git` | any       | not recommend     |
| ^0.7.0              | Flutter 2.0.0 • channel stable                                            | any       | not recommend |
| ^0.5.1-nullsafety.0 | Flutter 1.24.0-10.2.pre • channel beta                                    | any       | not recommend |
| ^0.5.0-nullsafety.0 | Flutter 1.24.0-10.2.pre • channel beta                                    | any       | not recommend |
| ^0.4.0              | Flutter 1.24.0-10.2.pre • channel beta                                    | any       | not recommend |

## 快速开始

如果您已经有其他类似框架使用经验,可以直接查看[Example](example/)浏览最佳实践。

> run example project: `flutter run --no-sound-null-safety`

### 添加依赖

``` yaml
dependencies:
  g_faraday: ^0.7.0
```

### Flutter 端集成

flutter侧的集成工作,主要是注册需要从原生打开的页面。

``` dart

// 0x00 定义 route
final route = faraday.wrapper((settings) {
    switch (settings.name) {
    case 'first_page':
        return CupertinoPageRoute(builder: (context) => Text('First Page'));
    case 'second_page':
        return CupertinoPageRoute(builder: (context) => Text('Second Page'));
    }
    return CupertinoPageRoute(builder: (context) => Text(settings.name));
});

// 0x01 将 route 赋给你的app widget
CupertinoApp(onGenerateRoute: (_) => route);

// 0x02 flutter 侧集成完毕,接下来你可以选择 集成iOS/Android
```

> 注意不管是`CupertinoApp`还是`MaterialApp`都不要设置`home`

### iOS 集成

[Objective-C集成看这里](./example_objc_only/README.md)

为了实现从`Flutter`端打开原生页面的应用场景,所以我们需要实现一个打开原生页面的protocol

``` swift

// 0x00 实现 `FaradayNavigationDelegate`
extension AppDelegate: FaradayNavigationDelegate {

    func push(_ name: String, arguments: Any?, options: [String : Any]?, callback token: CallbackToken) {

        let isFlutter = options?["flutter"] as? Bool ?? false
        let isPresent = options?["present"] as? Bool ?? false

        let vc = isFlutter ? FaradayFlutterViewController(name, arguments: arguments) : FirstViewController(name, arguments: arguments)

        let topMost = UIViewController.fa.topMost
        if (isPresent) {
            // 此处注意
            // vc.modalPresentationStyle 不能是`pageSheet`
            // 如果的确需要这种UI效果,可以配合透明背景,在Flutter侧实现
            topMost?.present(vc, animated: true, completion: nil)
        } else {
            topMost?.navigationController?.pushViewController(vc, animated: true)
        }

        // 非常重要
        // 如果此处不调用 `enableCallback` 那么flutter侧`await Navigator`则永远不会返回
        vc.fa.enableCallback(with: token)
    }
}

// 0x01 在 `application: didFinishLaunchingWithOptions`中启动flutter engine
Faraday.default.startFlutterEngine(navigatorDelegate: self)


// 0x02 打开一个flutter 页面
let vc = FaradayFlutterViewController("first_page", arguments: nil)
navigationController?.pushViewController(vc, animated: true)

// 0x03 集成完毕
```

### Android 集成

为了实现从`Flutter`端打开原生页面的应用场景,所以我们需要实现一组打开原生页面的接口

``` kotlin

// 0x00 实现 navigator
class SimpleFlutterNavigator : FaradayNavigator {

    companion object {
        const val KEY_ARGS = "_args"
    }

    override fun create(name: String, arguments: Serializable?, options: HashMap<String, *>?): Intent? {
        val context = Faraday.getCurrentActivity() ?: return null

        val isFlutterRoute = options?.get("flutter") == true

        if (isFlutterRoute) {
            // singleTask 模式
            val builder = FaradayActivity.builder(name, arguments)

            // 你看到的绿色的闪屏就是这个
            builder.backgroundColor = Color.WHITE
            builder.activityClass = SingleTaskFlutterActivity::class.java

            return builder.build(context);
        }

        when (name) {
            "flutter2native" -> {
                return Intent(context, FlutterToNativeActivity::class.java)
            }
            "native2flutter" -> {
                return Intent(context, Native2FlutterActivity::class.java)
            }
            "tabContainer" -> {
                return Intent(context, TabContainerActivity::class.java)
            }
            else -> {
                val intent = Intent(Intent.ACTION_VIEW)
                intent.data = Uri.parse(name)
                intent.putExtra(KEY_ARGS, arguments)
                return intent
            }
        }

    }

    override fun pop(result: Serializable?) {
        val activity = Faraday.getCurrentActivity() ?: return
        if (result != null) {
            activity.setResult(Activity.RESULT_OK, Intent().apply { putExtra(KEY_ARGS, result) })
        }
        activity.finish()
    }

    override fun enableSwipeBack(enable: Boolean) {

    }

}

// 0x01 在 Application 的onCreate方法中启动FlutterEngine
if (!Faraday.startFlutterEngine(this, SimpleFlutterNavigator())) {
    GeneratedPluginRegistrant.registerWith(Faraday.engine)
}

// 0x02 打开一个Flutter页面
val intent = FaradayActivity.build(context, routeName, params)
context.startActivity(intent)

```

## faraday 全家桶 (推荐)

在进行Flutter混合开发时会遇到很多相似的问题,我们提供了相应的解决方案大家玩的开心。

- [路由](doc/route.md)
- [桥接原生方法](doc/bridge.md)
- [网络请求](doc/net.md)
- [JSON](doc/json.md)
- [命令行工具 | 代码生成](https://github.com/gfaraday/cli)
- [vscode 插件 | 自动补全](https://github.com/gfaraday/faraday_extension)
- [打包发布 | CI/CD](./doc/ci.md)

## FAQ

### 是否支持使用第三方路由框架?

支持。

example中提供了[fluro](https://github.com/lukepighetti/fluro)和[getx](https://github.com/jonataslaw/getx)的实现范例

### 是否支持使用`url`配置路由?

支持。

- ios推荐使用[⛵️ URLNavigator](https://github.com/devxoul/URLNavigator)
- android[原生支持](https://developer.android.com/training/app-links/deep-linking)
- flutter推荐[fluro](https://github.com/lukepighetti/fluro)

可以保证3端统一使用url进行路由管理。

### 打包时提示 `failed to load module 'g_faraday'`

请使用`xcode 12.3`及以上版本

## Communication

[扫码加入微信群,请备注 faraday](https://github.com/KevinGong2013)

![wechat group](doc/images/wechat.JPG)

## Contributing

If you wish to contribute a change to any of the existing plugins in this repo, please review our [contribution](CONTRIBUTING.md) guide and open a pull request.

## License

g_faraday is released under the MIT license. [See LICENSE](LICENSE) for details.


================================================
FILE: README_EN.md
================================================
# ![log](./doc/images/logo.png)  Faraday [中文文档](./README.md)

![Build](https://img.shields.io/github/workflow/status/gfaraday/g_faraday/Publisher/master?logo=github&style=for-the-badge)
![pub_Version](https://img.shields.io/pub/v/g_faraday?include_prereleases&style=for-the-badge&logo=data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPHN2ZyB3aWR0aD0iNjAwcHgiIGhlaWdodD0iNjAwcHgiIHZpZXdCb3g9IjAgMCA2MDAgNjAwIiB2ZXJzaW9uPSIxLjEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiPgogICAgPHRpdGxlPmZhcmFkYXk8L3RpdGxlPgogICAgPGRlZnM+CiAgICAgICAgPGxpbmVhckdyYWRpZW50IHgxPSIxMC42ODAxNzA0JSIgeTE9IjI2Ljk5MzAyODclIiB4Mj0iNzIuMTEzMDU3NiUiIHkyPSI1Mi45MTkyNjU3JSIgaWQ9ImxpbmVhckdyYWRpZW50LTEiPgogICAgICAgICAgICA8c3RvcCBzdG9wLWNvbG9yPSIjMDAwMDAwIiBvZmZzZXQ9IjAlIj48L3N0b3A+CiAgICAgICAgICAgIDxzdG9wIHN0b3AtY29sb3I9IiMwMDAwMDAiIHN0b3Atb3BhY2l0eT0iMCIgb2Zmc2V0PSIxMDAlIj48L3N0b3A+CiAgICAgICAgPC9saW5lYXJHcmFkaWVudD4KICAgIDwvZGVmcz4KICAgIDxnIGlkPSJQYWdlLTEiIHN0cm9rZT0ibm9uZSIgc3Ryb2tlLXdpZHRoPSIxIiBmaWxsPSJub25lIiBmaWxsLXJ1bGU9ImV2ZW5vZGQiPgogICAgICAgIDxnIGlkPSJmYXJhZGF5IiBmaWxsLXJ1bGU9Im5vbnplcm8iPgogICAgICAgICAgICA8ZyBpZD0iR3JvdXAiPgogICAgICAgICAgICAgICAgPGcgaWQ9ImZsdXR0ZXItc2Vla2xvZ28uY29tIj4KICAgICAgICAgICAgICAgICAgICA8cG9seWdvbiBpZD0iUGF0aCIgZmlsbD0iI0VCRkNGNCIgcG9pbnRzPSIyMDQuNTY2ODQ1IDAgMCAyMjEuOTI4NzQ2IDYzLjMxNzM1OSAyOTAuNjE5OTQ2IDMzMS4yMDI5ODkgMCI+PC9wb2x5Z29uPgogICAgICAgICAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJQYXRoIiBmaWxsPSIjRUJGQ0Y0IiBwb2ludHM9IjIwMy4zNDU5MzggMjA0LjI0MTI0IDkzLjk5MDAzNzQgMzIyLjYyMDg5OSAxNTcuNDQzOTAxIDM5Mi4zMzY5MjcgMjIwLjU0MzM2OCAzMjQuMDMwNjU4IDMzMS4yMDI5ODkgMjA0LjI0MTI0Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIGZpbGw9IiNFQkZDRjQiIHBvaW50cz0iMTU3LjM5NjAxNSAzOTIuODE5ODQxIDIwNS40NDUxNzMgNDQ0LjgwOTk3MyAzMzEuMjAyOTg5IDQ0NC44MDk5NzMgMjIwLjUxMTk2NSAzMjQuNTI1NjA2Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIGZpbGw9IiNFQkZDRjQiIHBvaW50cz0iOTMuMjQ0MDg0NyAzMjMuODY0MiAxNTYuNjA3OTA4IDI1NS4wOTk3MyAyMjAuODAxOTkzIDMyNC41MDgyMzIgMTU3LjU1ODAwMSAzOTMuMTQ0MjA1Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIGZpbGwtb3BhY2l0eT0iMC44IiBmaWxsPSJ1cmwoI2xpbmVhckdyYWRpZW50LTEpIiBwb2ludHM9IjE1Ny4zOTYwMTUgMzkyLjMzNjkyNyAyMTAuMzIyOTA0IDM3My4zMzA1NzYgMjE1LjU4MDMyNCAzMjkuMzY5MjcyIj48L3BvbHlnb24+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgICAgICA8ZyBpZD0iZmx1dHRlci1zZWVrbG9nby5jb20iIHRyYW5zZm9ybT0idHJhbnNsYXRlKDI2Ny43OTcwMTEsIDE1NC4xOTAwMjcpIiBmaWxsPSIjRUJGQ0Y0Ij4KICAgICAgICAgICAgICAgICAgICA8cG9seWdvbiBpZD0iUGF0aCIgcG9pbnRzPSIyMDQuNTY2ODQ1IDAgMCAyMjEuOTI4NzQ2IDYzLjMxNzM1OSAyOTAuNjE5OTQ2IDMzMS4yMDI5ODkgMCI+PC9wb2x5Z29uPgogICAgICAgICAgICAgICAgICAgIDxwb2x5Z29uIGlkPSJQYXRoIiBwb2ludHM9IjIwMy4zNDU5MzggMjA0LjI0MTI0IDkzLjk5MDAzNzQgMzIyLjYyMDg5OSAxNTcuNDQzOTAxIDM5Mi4zMzY5MjcgMjIwLjU0MzM2OCAzMjQuMDMwNjU4IDMzMS4yMDI5ODkgMjA0LjI0MTI0Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIHBvaW50cz0iMTU3LjM5NjAxNSAzOTIuODE5ODQxIDIwNS40NDUxNzMgNDQ0LjgwOTk3MyAzMzEuMjAyOTg5IDQ0NC44MDk5NzMgMjIwLjUxMTk2NSAzMjQuNTI1NjA2Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICAgICAgPHBvbHlnb24gaWQ9IlBhdGgiIHBvaW50cz0iOTMuMjQ0MDg0NyAzMjMuODY0MiAxNTYuNjA3OTA4IDI1NS4wOTk3MyAyMjAuODAxOTkzIDMyNC41MDgyMzIgMTU3LjU1ODAwMSAzOTMuMTQ0MjA1Ij48L3BvbHlnb24+CiAgICAgICAgICAgICAgICA8L2c+CiAgICAgICAgICAgIDwvZz4KICAgICAgICA8L2c+CiAgICA8L2c+Cjwvc3ZnPg==)
![Flutter_Version](https://img.shields.io/badge/Flutter-1.24.0--10.2.pre-blue?style=for-the-badge&logo=flutter)
![License](https://img.shields.io/github/license/gfaraday/g_faraday?style=for-the-badge)

Flutter plugin for integrate flutter to existing app

## Features

- [x] `ios`、`android`、`flutter` Native route apis
- [x] Hybrid stack(native -> flutter -> native)
- [x] Initial Page Support
- [x] ChildViewController、Fragment Support
- [x] Alert Page Support
- [x] [CallBack](doc/callback.md)
- [x] [iOS NavigationBar Auto hide/show](doc/ios_navigation_bar.md)
- [x] WillPopScope Handle `onBackPress`
- [x] [Global Notification](doc/notification.md)
- [x] Custom Page Transition
- [ ] Unit Test
- [ ] Complete Documentation(7/10)

## Show Cases

![demo](doc/images/demo_en.png)

## Example App

[Android Download apk](https://github.com/gfaraday/g_faraday/releases/download/v0.5.0-nullsafety.3/appv2.apk)

<!-- [iOS下载app](https://github.com/gfaraday/g_faraday/releases/download/0.4.2/example.app.zip)
> [模拟器安装app](doc/ios-simulator-install.md) -->

## Design Principles

- avoid dependency platform implementation
- avoid modify existing code
- follow platform api design guidance

## Requirements

- Flutter 2.5.0 • channel stable
- iOS 10.0+ Xcode 12.0+ Swift 5.1+
- Android minSdkVersion 16 Kotlin 1.4.10+

## Faraday VS. Flutter versions

| g_faraday           | flutter                                                                   | cocoapods | remark        |
| ------------------- | ------------------------------------------------------------------------- | --------- | ------------- |
| ^0.7.2              | Flutter 2.5.0 • channel stable • `https://github.com/flutter/flutter.git` | any       | recommend     |
| ^0.7.0              | Flutter 2.0.0 • channel stable                                            | any       | not recommend |
| ^0.5.1-nullsafety.0 | Flutter 1.24.0-10.2.pre • channel beta                                    | any       | not recommend |
| ^0.5.0-nullsafety.0 | Flutter 1.24.0-10.2.pre • channel beta                                    | any       | not recommend |
| ^4.0.0              | Flutter 1.24.0-10.2.pre • channel beta                                    | any       | not recommend |

## Quick Start

[Browse Example Source Code](example/)

### add dependencies

``` yaml
dependencies:
  # please confirm flutter channel >> supported: flutter channel beta, 1.25.0-8.1.pre
  g_faraday: ^0.5.1-nullsafety.0
```

### Flutter

Register route which will be open from native.

``` dart

// 0x00 define route
final route = faraday.wrapper((settings) {
    switch (settings.name) {
    case 'first_page':
        return CupertinoPageRoute(builder: (context) => Text('First Page'));
    case 'second_page':
        return CupertinoPageRoute(builder: (context) => Text('Second Page'));
    }
    return CupertinoPageRoute(builder: (context) => Text(settings.name));
});

// 0x01 set route to your `App` widget
CupertinoApp(onGenerateRoute: (_) => route);

```

### iOS

Provider a navigator to open `flutter` page.

``` swift

// 0x00 implement `FaradayNavigationDelegate`
extension AppDelegate: FaradayNavigationDelegate {

    func push(_ name: String, arguments: Any?, options: [String : Any]?, callback token: CallbackToken) {

        let isFlutter = options?["flutter"] as? Bool ?? false
        let isPresent = options?["present"] as? Bool ?? false

        let vc = isFlutter ? FaradayFlutterViewController(name, arguments: arguments) : FirstViewController(name, arguments: arguments)

        let topMost = UIViewController.fa.topMost
        if (isPresent) {
            topMost?.present(vc, animated: true, completion: nil)
        } else {
            topMost?.navigationController?.pushViewController(vc, animated: true)
        }

        // IMPORTANT
        vc.fa.enableCallback(with: token)
    }
}

// 0x01 start flutter Engine in `application: didFinishLaunchingWithOptions`
Faraday.default.startFlutterEngine(navigatorDelegate: self)


// 0x02 open flutter page
let vc = FaradayFlutterViewController("first_page", arguments: nil)
navigationController?.pushViewController(vc, animated: true)

```

### Android

Provider a navigator to open `flutter` page.

``` kotlin

// 0x00 implement `FaradayNavigator`
class SimpleFlutterNavigator : FaradayNavigator {

    companion object {
        const val KEY_ARGS = "_args"
    }

    override fun create(name: String, arguments: Serializable?, options: HashMap<String, *>?): Intent? {
        val context = Faraday.getCurrentActivity() ?: return null

        val isFlutterRoute = options?.get("flutter") == true

        if (isFlutterRoute) {
            // singleTask mode
            val builder = FaradayActivity.builder(name, arguments)

            builder.backgroundColor = Color.WHITE
            builder.activityClass = SingleTaskFlutterActivity::class.java

            return builder.build(context);
        }

        when (name) {
            "flutter2native" -> {
                return Intent(context, FlutterToNativeActivity::class.java)
            }
            "native2flutter" -> {
                return Intent(context, Native2FlutterActivity::class.java)
            }
            "tabContainer" -> {
                return Intent(context, TabContainerActivity::class.java)
            }
            else -> {
                val intent = Intent(Intent.ACTION_VIEW)
                intent.data = Uri.parse(name)
                intent.putExtra(KEY_ARGS, arguments)
                return intent
            }
        }

    }

    override fun pop(result: Serializable?) {
        val activity = Faraday.getCurrentActivity() ?: return
        if (result != null) {
            activity.setResult(Activity.RESULT_OK, Intent().apply { putExtra(KEY_ARGS, result) })
        }
        activity.finish()
    }

    override fun enableSwipeBack(enable: Boolean) {

    }

}

// 0x01 start flutter engine in Application.onCrate
if (!Faraday.startFlutterEngine(this, SimpleFlutterNavigator())) {
    GeneratedPluginRegistrant.registerWith(Faraday.engine)
}

// 0x02 open flutter page
val intent = FaradayActivity.build(context, routeName, params)
context.startActivity(intent)

```

## faraday tools (Recommend)

- [Route](doc/route.md)
- [Bridge Native Methods](doc/bridge.md)
- [Net](doc/net.md)
- [JSON](doc/json.md)
- [vscode Extension](https://github.com/gfaraday/faraday_extension)

## FAQ

## Communication

## Contributing

If you wish to contribute a change to any of the existing plugins in this repo, please review our [contribution](CONTRIBUTING.md) guide and open a pull request.

## License

g_faraday is released under the MIT license. [See LICENSE](LICENSE) for details.


================================================
FILE: analysis_options.yaml
================================================
# This file configures the analyzer, which statically analyzes Dart code to
# check for errors, warnings, and lints.
#
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
# invoked from the command line by running `flutter analyze`.

# The following line activates a set of recommended lints for Flutter apps,
# packages, and plugins designed to encourage good coding practices.
include: package:flutter_lints/flutter.yaml

linter:
  # The lint rules applied to this project can be customized in the
  # section below to disable rules from the `package:flutter_lints/flutter.yaml`
  # included above or to enable additional rules. A list of all available lints
  # and their documentation is published at
  # https://dart-lang.github.io/linter/lints/index.html.
  #
  # Instead of disabling a lint rule for the entire project in the
  # section below, it can also be suppressed for a single line of code
  # or a specific dart file by using the `// ignore: name_of_lint` and
  # `// ignore_for_file: name_of_lint` syntax on the line or in the file
  # producing the lint.
  rules:
    # avoid_print: false  # Uncomment to disable the `avoid_print` rule
    # prefer_single_quotes: true  # Uncomment to enable the `prefer_single_quotes` rule

# Additional information about this file can be found at
# https://dart.dev/guides/language/analysis-options


================================================
FILE: android/.gitignore
================================================
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures


================================================
FILE: android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
================================================
package io.flutter.plugins;

import io.flutter.plugin.common.PluginRegistry;
import com.yuxiaor.flutter.g_faraday.GFaradayPlugin;

/**
 * Generated file. Do not edit.
 */
public final class GeneratedPluginRegistrant {
  public static void registerWith(PluginRegistry registry) {
    if (alreadyRegisteredWith(registry)) {
      return;
    }
    GFaradayPlugin.registerWith(registry.registrarFor("com.yuxiaor.flutter.g_faraday.GFaradayPlugin"));
  }

  private static boolean alreadyRegisteredWith(PluginRegistry registry) {
    final String key = GeneratedPluginRegistrant.class.getCanonicalName();
    if (registry.hasPlugin(key)) {
      return true;
    }
    registry.registrarFor(key);
    return false;
  }
}


================================================
FILE: android/build.gradle
================================================
group 'com.yuxiaor.flutter.g_faraday'
version '1.0-SNAPSHOT'

buildscript {
    ext.kotlin_version = '1.6.21'
    repositories {
        google()
        jcenter()
    }

    dependencies {
        //noinspection GradleDependency
        classpath 'com.android.tools.build:gradle:3.5.4'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

rootProject.allprojects {
    repositories {
        google()
    }
}

apply plugin: 'com.android.library'
apply plugin: 'kotlin-android'

android {
    compileSdkVersion 33
//    buildToolsVersion "29.0.3"
    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }
    defaultConfig {
        minSdkVersion 16
    }
    lintOptions {
        disable 'InvalidPackage'
    }
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0'
    implementation "androidx.activity:activity-ktx:1.6.0-alpha05"
}


================================================
FILE: android/gradle/wrapper/gradle-wrapper.properties
================================================
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip


================================================
FILE: android/gradle.properties
================================================
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true


================================================
FILE: android/settings.gradle
================================================
rootProject.name = 'g_faraday'


================================================
FILE: android/src/main/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.yuxiaor.flutter.g_faraday">

    <application tools:node="merge">

        <activity
            android:name=".FaradayActivity"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize" />

        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />

    </application>
</manifest>


================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/Faraday.kt
================================================
package com.yuxiaor.flutter.g_faraday

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.util.Log
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import com.yuxiaor.flutter.g_faraday.channels.*
import com.yuxiaor.flutter.g_faraday.channels.CommonChannel
import com.yuxiaor.flutter.g_faraday.channels.NetChannel
import io.flutter.FlutterInjector
import io.flutter.embedding.android.FlutterFragment
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.dart.DartExecutor.DartEntrypoint
import io.flutter.plugin.common.MethodChannel
import java.lang.ref.WeakReference
import java.util.concurrent.atomic.AtomicInteger

interface FaradayContainer {

    // detach from engine
    fun performDetach()

    //
    fun rebuildFlutterPage()
}

/**
 * Author: Edward
 * Date: 2020-08-31
 * Description:
 */
object Faraday {

    lateinit var engine: FlutterEngine
        private set

    private val nextCode = AtomicInteger()

    // router manager
    internal lateinit var navigator: FaradayNavigator

    /**
     *  init engine
     *
     *  @param context Application Context
     *  @param navigator handle native route
     *  @param netHandler handle net request
     *  @param commonHandler common method invoke
     *  @param automaticallyRegisterPlugins If plugins are automatically
     * registered, then they are registered during the execution of this constructor
     *
     *  @return true if plugins registered otherwise return false.
     *
     *  @sample
     *  if (!Faraday.startFlutterEngine(this, MyFlutterNavigator())) {
     *       GeneratedPluginRegister.registerGeneratedPlugins(Faraday.engine)
     *   }
     *
     */
    @JvmStatic
    fun startFlutterEngine(context: Context,
                           navigator: FaradayNavigator,
                           netHandler: NetHandler? = null,
                           commonHandler: MethodChannel.MethodCallHandler? = null,
                           automaticallyRegisterPlugins: Boolean = true,
                           dartEntrypointFunctionName: String = "main"): Boolean {
        // 这个navigator 必须先初始化 不能动
        this.navigator = navigator

        engine = FlutterEngine(context, arrayOf(), automaticallyRegisterPlugins)

        val flutterLoader = FlutterInjector.instance().flutterLoader()

        if (!flutterLoader.initialized()) {
            throw AssertionError(
                    "DartEntrypoints can only be created once a FlutterEngine is created.")
        }
        val entrypoint = DartEntrypoint(flutterLoader.findAppBundlePath(), dartEntrypointFunctionName)

        engine.dartExecutor.executeDartEntrypoint(entrypoint)

        if (netHandler != null) {
            NetChannel(engine.dartExecutor, netHandler)
        }

        if (commonHandler != null) {
            CommonChannel(engine.dartExecutor, commonHandler)
        }

        FaradayNotice.setup(engine.dartExecutor)

        return  false
    }

    internal fun genPageId(): Int {
        return nextCode.getAndIncrement()
    }

    /**
     * The current flutter container Activity
     */
    @JvmStatic
    fun getCurrentContainer(): FaradayContainer? {
        val activity = getCurrentActivity()
        if (activity is FaradayContainer) {
            return activity
        }

        if (activity is FragmentActivity) {
            var frag = activity.supportFragmentManager.fragments.find { it.isVisible }
            if (frag == null) {
                frag = activity.supportFragmentManager.fragments.find { it is FaradayContainer }
            }
            if (frag is FaradayContainer) {
                return frag
            }
        }

        return  null
    }

    fun getCurrentActivity(): Activity? {
        return  engine.gFaradayPlugin()?.binding?.activity
    }
    /**
     * start native Activity,and request for Activity result
     */
    internal fun startNativeForResult(intent: Intent, callback: (result: HashMap<String, Any?>?) -> Unit) {
        val code = nextCode.getAndIncrement()
        startNativeForResult(intent, code) { requestCode, resultCode, data ->
            if (requestCode == code) {
                if (resultCode == Activity.RESULT_OK) {
                    val map = hashMapOf<String, Any?>()
                    data?.extras?.keySet()?.forEach {
                        map[it] = data.extras?.get(it)
                    }
                    callback.invoke(map)
                } else {
                    callback.invoke(null)
                }
            }
        }
    }

    private fun startNativeForResult(intent: Intent, requestCode: Int, callback: ResultListener) {
        val activity = getCurrentContainer()

        if (activity is ResultProvider) {
            activity.addResultListener(callback)
            if (activity is Activity) {
                activity.startScheme(intent, requestCode)
            }
            return
        }

        if (activity is FragmentActivity) {
            val frag = activity.supportFragmentManager.fragments.first { it.isVisible }
            if (frag is ResultProvider) {
                frag.addResultListener(callback)
                frag.startScheme(intent, requestCode)
            }
        }
    }

    private fun Activity.startScheme(intent: Intent, requestCode: Int){
        try {
            startActivityForResult(intent, requestCode)
        }catch (e:Exception){
            Log.e("Faraday", "Route Not Found: '${intent.data}'")
        }
    }

    private fun Fragment.startScheme(intent: Intent, requestCode: Int){
        try {
            startActivityForResult(intent, requestCode)
        }catch (e:Exception){
            Log.e("Faraday", "Route Not Found: '${intent.data}'")
        }
    }
}


================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.graphics.Color
import android.os.Build
import android.os.Bundle
import android.os.PersistableBundle
import android.util.Log
import android.view.View
import android.view.ViewGroup
import com.yuxiaor.flutter.g_faraday.channels.CommonChannel
import com.yuxiaor.flutter.g_faraday.channels.FaradayNotice
import com.yuxiaor.flutter.g_faraday.channels.NetChannel
import io.flutter.embedding.android.ExclusiveAppComponent
import io.flutter.embedding.android.FlutterActivity
import io.flutter.embedding.android.FlutterActivityLaunchConfigs.BackgroundMode
import io.flutter.embedding.android.FlutterView
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.platform.PlatformPlugin
import java.io.Serializable
import java.lang.ref.WeakReference


fun View.flutterView(): FlutterView? {
    if (this is FlutterView) {
        return this
    }
    if (this is ViewGroup) {
        for (i in 0..childCount) {
            val child = getChildAt(i)
            val fv = child.flutterView()
            if (fv != null) {
                return fv
            }
        }
    }
    return  null
}
/**
 * Author: Edward
 * Date: 2020-09-01
 * Description:
 */
open class FaradayActivity : FlutterActivity(), ResultProvider, ExclusiveAppComponent<Activity>, FaradayContainer {

    companion object {


        private const val TAG = "FaradayActivity"

        fun builder(routeName: String, params: Serializable? = null, opaque: Boolean = true) = builder<FaradayActivity>(routeName, params, opaque)

        // opaque: Boolean = false 效率会差一些
        // 除非你有 非常非常非常 明确的理由,否则不要动他
        //
        //
        // 目前只有一种特定情况 opaque 需要设置为false
        //
        // 假如有一个`FaradayActivity`(假设为A)会使用新的容器打开flutter页面(假设为B)
        // 那么在 build A activity 的intent时 需要设置 `opaque = false` 否则在跳转时 页面会闪烁
        //
        inline fun <reified T : FaradayActivity> builder(
            routeName: String,
            params: Serializable? = null,
            opaque: Boolean = false,
            backgroundColor: Int? = null,
        ) = SingleEngineIntentBuilder(routeName, params, T::class.java, opaque, backgroundColor)
    }

    // 后续考虑支持更多参数, 然后再放开访问权限
    data class SingleEngineIntentBuilder(val routeName: String,
                                         val params: Serializable?,
                                         var activityClass: Class<out FaradayActivity>,
                                         var opaque: Boolean,
                                         var backgroundColor: Int?) {

        // 真正开始Build的时候再生成id
        fun build(context: Context): Intent {

            val bm = (if (opaque) BackgroundMode.opaque else BackgroundMode.transparent).name

            val pageId = Faraday.genPageId()

            return Intent(context, activityClass).apply {
                putExtra(FaradayConstants.ID, pageId)
                putExtra(FaradayConstants.ARGS, params)
                putExtra(FaradayConstants.ROUTE, routeName)
                putExtra(FaradayConstants.SPLASH_SCREEN_BACKGROUND_COLOR, backgroundColor)
                putExtra(FaradayConstants.BACKGROUND_MODE, bm)
            }
        }

    }

    private val pageId: Int
        get() = intent.getIntExtra(FaradayConstants.ID, 0)

    private val routeName: String
        get() = intent.getStringExtra(FaradayConstants.ROUTE) ?: ""

    private val params: Serializable?
        get() = intent.getSerializableExtra(FaradayConstants.ARGS);

    private val backgroundModeName: String
        get() = intent.getStringExtra(FaradayConstants.BACKGROUND_MODE)?: BackgroundMode.opaque.name

    private var resultListener: ResultListener? = null

    private var isAttached = false
    private var platformPlugin: PlatformPlugin? = null
    private val gFaradayPlugin: GFaradayPlugin?
        get() = Faraday.engine.gFaradayPlugin()
    private var flutterViewRef = WeakReference<FlutterView?>(null)

    override fun onNewIntent(intent: Intent) {
        // 只有在intent 发生实质性变化时才考虑更新flutter页面
        if (intent.getIntExtra(FaradayConstants.ID, -1) != -1) {
            this.intent = intent
        }
        super.onNewIntent(this.intent)
    }

    override fun onCreate(savedInstanceState: Bundle?) {

        if (Faraday.getCurrentActivity() != this) {
            Faraday.getCurrentContainer()?.performDetach()
        }

        super.onCreate(savedInstanceState)

        flutterViewRef = WeakReference(window.decorView.flutterView())

        //
        // dart 侧创建页面
        gFaradayPlugin?.onPageCreate(routeName, params, pageId, backgroundModeName)

        Log.d(TAG, "onCreate: $this")
    }

    override fun detachFromFlutterEngine() {
        // 如果不重写这个方法,delegate会被释放掉
    }

    override fun shouldDestroyEngineWithHost(): Boolean {
        return false
    }

    override fun providePlatformPlugin(
        activity: Activity?,
        flutterEngine: FlutterEngine
    ): PlatformPlugin? {
        // 自己托管 platformPlugin
        return null
    }

    override fun shouldAttachEngineToActivity(): Boolean {
        // 自己管理
        return false;
    }

    override fun shouldDispatchAppLifecycleState(): Boolean {
        return false;
    }

    override fun rebuildFlutterPage() {
        gFaradayPlugin?.onPageCreate(routeName, params, pageId, backgroundModeName)
        gFaradayPlugin?.onPageShow(pageId)
    }

    override fun provideFlutterEngine(context: Context): FlutterEngine? {
        return Faraday.engine
    }

    override fun onResume() {
        super.onResume()

        if (Faraday.getCurrentActivity() != this) {
            Faraday.getCurrentContainer()?.performDetach()
        }

        performAttach()

        //
        flutterEngine?.lifecycleChannel?.appIsResumed()

        //
        gFaradayPlugin?.onPageShow(pageId)

        //
        platformPlugin?.updateSystemUiOverlays()
    }

    override fun onDestroy() {
        gFaradayPlugin?.onPageDealloc(pageId)
        performDetach()
        super.onDestroy()
    }

//    override fun provideSplashScreen(): SplashScreen? {
//        val splashScreen = super.provideSplashScreen()
//        if (splashScreen != null) return splashScreen
//        return FaradayColorBaseSplashScreen(intent?.getIntExtra(FaradayConstants.SPLASH_SCREEN_BACKGROUND_COLOR, Color.WHITE))
//    }

    override fun addResultListener(resultListener: ResultListener) {
        this.resultListener = resultListener
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        resultListener?.invoke(requestCode, resultCode, data)
        resultListener = null
    }

    override fun getAppComponent(): Activity {
        return super.getExclusiveAppComponent().appComponent
    }

    private fun performAttach() {
        Log.d(TAG, "attach: $this")
        if (!isAttached) {
            assert(flutterEngine != null)
            assert(flutterViewRef.get() != null)

            // 0x01
            flutterEngine?.activityControlSurface?.attachToActivity(this, lifecycle)

            flutterViewRef = WeakReference(window.decorView.flutterView())

            // 0x02
            if (platformPlugin == null) {
                platformPlugin = PlatformPlugin(activity, flutterEngine!!.platformChannel, this)
            }

            // 0x03
            flutterViewRef.get()?.attachToFlutterEngine(flutterEngine!!)

            //
            isAttached = true
        }
    }

    override fun performDetach() {
        Log.d(TAG, "detach: $this")
        if (isAttached) {

            // 0x01
            assert(flutterEngine != null)

            //
            platformPlugin?.destroy()
            platformPlugin = null

            if (Faraday.getCurrentActivity() == this) {
                //
                flutterEngine?.activityControlSurface?.detachFromActivity()

                //
                flutterViewRef.get()?.detachFromFlutterEngine()

            }

            isAttached = false
        }
    }
}


================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayColorBaseSplashScreen.kt
================================================
//package com.yuxiaor.flutter.g_faraday
//
//import android.animation.Animator
//import android.animation.Animator.AnimatorListener
//import android.content.Context
//import android.graphics.Color
//import android.os.Bundle
//import android.view.View
//import io.flutter.embedding.android.SplashScreen
//
//class FaradayColorBaseSplashScreen(private val color: Int?) : SplashScreen {
//
//    private var splashView: View? = null
//
//    override fun createSplashView(context: Context, savedInstanceState: Bundle?): View? {
//        //不能重用
//        // if (splashView != null) {
//        //     return splashView
//        // }
//        splashView = View(context)
//        splashView?.setBackgroundColor(color ?: Color.WHITE)
//        return splashView
//    }
//
//    override fun transitionToFlutter(onTransitionComplete: Runnable) {
//        if (splashView == null) {
//            onTransitionComplete.run()
//            return
//        }
//        splashView!!
//                .animate()
//                .alpha(0.0f)
//                .setDuration(500)
//                .setListener(
//                        object : AnimatorListener {
//                            override fun onAnimationStart(animation: Animator) {}
//                            override fun onAnimationEnd(animation: Animator) {
//                                onTransitionComplete.run()
//                            }
//
//                            override fun onAnimationCancel(animation: Animator) {
//                                onTransitionComplete.run()
//                            }
//
//                            override fun onAnimationRepeat(animation: Animator) {}
//                        })
//    }
//}

================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayConstants.kt
================================================
package com.yuxiaor.flutter.g_faraday

class FaradayConstants {

    companion object {
        //TODO: 这些key的定义,需要重构
        const val ID = "_flutter_id"
        const val ARGS = "_flutter_args"
        const val ROUTE = "_flutter_route"

        // 注意这个key 不能修改, flutter 内部有使用
        const val BACKGROUND_MODE = "background_mode"

        const val SPLASH_SCREEN_BACKGROUND_COLOR = "_flutter_splash_screen_background_color"
    }
}

================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayFragment.kt
================================================


package com.yuxiaor.flutter.g_faraday

import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import io.flutter.embedding.android.*
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.plugin.platform.PlatformPlugin
import java.io.Serializable
import java.lang.ref.WeakReference


/**
 * Author: Edward
 * Date: 2020-09-07
 * Description:
 */
class FaradayFragment : FlutterFragment(), ResultProvider, FaradayContainer, ExclusiveAppComponent<Activity> {

    private val pageId by lazy { arguments?.getInt(FaradayConstants.ID) ?: 0 }
    private val routeName by lazy { arguments?.getString(FaradayConstants.ROUTE) ?: "/" }
    private val args by lazy { arguments?.get(FaradayConstants.ARGS) }
    private val backgroundModeName by lazy {
       arguments?.getString(FaradayConstants.BACKGROUND_MODE) ?: FlutterActivityLaunchConfigs.BackgroundMode.opaque.name }

    private var resultListener: ResultListener? = null

    private val gFaradayPlugin: GFaradayPlugin?
        get() = Faraday.engine.gFaradayPlugin()
    private var flutterViewRef = WeakReference<FlutterView?>(null)

    private var isAttached = false
    private var platformPlugin: PlatformPlugin? = null

    companion object {

        const val TAG = "FaradayFragment"
        ///
        /// 1. 注意 fragment 有一个小限制,如果打算使用
        /// FragmentTransaction.add 然后 show/hide 的方式来切换 fragment 那么opaque必须为false
        ///
        /// ❌否则在动画过程中会出现 白屏/黑屏❌
        ///
        @JvmStatic
        fun newInstance(
                routeName: String,
                params: HashMap<String, Any>? = null,
                opaque: Boolean = true,
                backgroundColor: Int? = null,
        ): FaradayFragment {
            val pageId = Faraday.genPageId()
            val bm = (if (opaque) TransparencyMode.opaque else TransparencyMode.transparent).name
            val bundle = Bundle().apply {
                putInt(FaradayConstants.ID, pageId)
                putString(FaradayConstants.ROUTE, routeName)
                putSerializable(FaradayConstants.ARGS, params)
                putString(ARG_FLUTTERVIEW_TRANSPARENCY_MODE, bm)
                if (backgroundColor != null) {
                    putInt(FaradayConstants.SPLASH_SCREEN_BACKGROUND_COLOR, backgroundColor)
                }
            }
            return FaradayFragment().apply { arguments = bundle }
        }
    }

    override fun detachFromFlutterEngine() {
        //
    }

    override fun providePlatformPlugin(
        activity: Activity?,
        flutterEngine: FlutterEngine
    ): PlatformPlugin? {
        return null
    }

    override fun onDestroy() {
        gFaradayPlugin?.onPageDealloc(pageId)
        performDetach()
        super.onDestroy()
    }

    override fun shouldDestroyEngineWithHost(): Boolean {
        return false
    }

    override fun getRenderMode(): RenderMode {
        return RenderMode.texture
    }

    override fun getTransparencyMode(): TransparencyMode {
        return TransparencyMode.transparent
    }

//    override fun provideSplashScreen(): SplashScreen? {
//        val splashScreen = super.provideSplashScreen()
//        if (splashScreen != null) return splashScreen
//        return FaradayColorBaseSplashScreen(arguments?.getInt(FaradayConstants.SPLASH_SCREEN_BACKGROUND_COLOR, Color.WHITE))
//    }

    override fun onCreateView(
        inflater: LayoutInflater,
        container: ViewGroup?,
        savedInstanceState: Bundle?
    ): View? {
        val view = super.onCreateView(inflater, container, savedInstanceState)

        flutterViewRef = WeakReference(view?.flutterView())
        flutterViewRef.get()?.detachFromFlutterEngine()

        return view
    }

    override fun onStart() {
        super.onStart()
        if (!isHidden) {
            showFragment()
        }
    }

    override fun onHiddenChanged(hidden: Boolean) {
        super.onHiddenChanged(hidden)
        if (flutterViewRef.get() == null) return

        if (!hidden) {
            showFragment()
        }
    }

    override fun onPause() {
        super.onPause()
        flutterEngine?.lifecycleChannel?.appIsResumed()
    }

    override fun onResume() {
        super.onResume()
        if (!isHidden) {
            showFragment()
        }
        flutterEngine?.lifecycleChannel?.appIsResumed()
    }

    override fun onStop() {
        super.onStop()
        flutterEngine?.lifecycleChannel?.appIsResumed()
    }

    override fun onDetach() {
        super.onDetach()
        gFaradayPlugin?.onPageDealloc(pageId)
    }

    override fun provideFlutterEngine(context: Context): FlutterEngine? {
        return Faraday.engine
    }

    override fun shouldAttachEngineToActivity(): Boolean {
        return false
    }

    override fun shouldDispatchAppLifecycleState(): Boolean {
        return false
    }

    override fun addResultListener(resultListener: ResultListener) {
        this.resultListener = resultListener

    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        resultListener?.invoke(requestCode, resultCode, data)
        resultListener = null
    }

    private fun showFragment() {
        if (Faraday.getCurrentContainer() != this) {
            Faraday.getCurrentContainer()?.performDetach()
        }
        performAttach()
        gFaradayPlugin?.onPageShow(pageId)
    }

    private fun performAttach() {
        Log.d(TAG, "attach: $this")
        if (!isAttached) {
            assert(flutterEngine != null)
            assert(flutterViewRef.get() != null)

            gFaradayPlugin?.onPageCreate(routeName, args as? Serializable, pageId, backgroundModeName)

            // 0x01
            flutterEngine?.activityControlSurface?.attachToActivity(this, lifecycle)

            // 0x02
            if (platformPlugin == null) {
                platformPlugin = PlatformPlugin(requireActivity(), flutterEngine!!.platformChannel, this)
            }

            // 0x03
            flutterViewRef.get()?.attachToFlutterEngine(flutterEngine!!)

            //
            isAttached = true
        }
    }

    override fun performDetach() {
        Log.d(TAG, "detach: $this")
        if (isAttached) {

            // 0x01
            assert(flutterEngine != null)

            //
            platformPlugin?.destroy()
            platformPlugin = null

            if (Faraday.getCurrentContainer() == this) {
                //
                flutterEngine?.activityControlSurface?.detachFromActivity()

                //
                flutterViewRef.get()?.detachFromFlutterEngine()

            }

            isAttached = false
        }
    }

    override fun rebuildFlutterPage() {
        gFaradayPlugin?.onPageCreate(routeName, args as? Serializable, pageId, backgroundModeName)
        gFaradayPlugin?.onPageShow(pageId)
    }

    override fun getAppComponent(): Activity {
       return requireActivity()
    }
}

================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayNavigator.kt
================================================
package com.yuxiaor.flutter.g_faraday

import android.content.Intent
import java.io.Serializable

/**
 * Author: Edward
 * Date: 2020-09-02
 * Description:
 */

data class Options(val raw: HashMap<String, *>?) {

    val animated: Boolean
        get() = get("_faraday.animated", true)

    val present: Boolean
        get() = get("_faraday.present", false)

    val isFlutterRoute: Boolean
        get() = get("_faraday.flutter", false)

    inline fun <reified T> get(key: String, defaultValue: T): T {
        if (raw == null) return defaultValue
        val value = raw[key]
        if (value is T) return value;
        return defaultValue
    }
}

interface FaradayNavigator {

    /**
     * create native Intent
     */
    fun create(name: String, arguments: Serializable?, options: Options): Intent?

    /**
     * finish flutter container Activity
     */
    fun pop(result: Serializable?)

    /**
     * 是否允许滑动返回
     */
    fun enableSwipeBack(enable: Boolean)
}


================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/GFaradayPlugin.kt
================================================
package com.yuxiaor.flutter.g_faraday

import android.util.Log
import androidx.annotation.NonNull
import androidx.fragment.app.FragmentActivity
import io.flutter.embedding.engine.FlutterEngine
import io.flutter.embedding.engine.plugins.FlutterPlugin
import io.flutter.embedding.engine.plugins.activity.ActivityAware
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import io.flutter.plugin.common.MethodChannel.MethodCallHandler
import io.flutter.plugin.common.MethodChannel.Result
import java.io.Serializable
import java.lang.ref.WeakReference

fun FlutterEngine.gFaradayPlugin(): GFaradayPlugin? {
    return plugins.get(GFaradayPlugin::class.java) as? GFaradayPlugin
}

/** GFaradayPlugin */
class GFaradayPlugin : FlutterPlugin, MethodCallHandler, ActivityAware {

    companion object {
        private const val TAG = "GFaradayPlugin"
    }

    private lateinit var channel: MethodChannel

    private val navigator: FaradayNavigator
        get() = Faraday.navigator

    internal var binding: ActivityPluginBinding? = null

    override fun onMethodCall(@NonNull call: MethodCall, @NonNull result: Result) {
        Log.d(TAG, "onMethodCall: ${call.method}")
        //
        when (call.method) {
            "pushNativePage" -> {
                val name = call.argument<String>("name")
                require(name != null) { "page route name should not be null" }
                val arguments = call.argument<Serializable>("arguments")
                val options = call.argument<HashMap<String, *>>("options")
                navigator.create(name, arguments, Options(options))?.let {
                    Faraday.startNativeForResult(it) { nativeResult ->
                        result.success(nativeResult)
                    }
                }
            }
            "popContainer" -> {
                val arg = call.arguments
                navigator.pop(arg as? Serializable)
                if (arg != null && arg !is Serializable) {
                    print("=========返回值丢失,返回值类型 $arg")
                }
                result.success(null)
            }
            "disableHorizontalSwipePopGesture" -> {
                val disable = call.arguments as? Boolean ?: false
                print(if (!disable) "enable" else "disable" + " Horizontal Swipe PopGesture")
                navigator.enableSwipeBack(!disable)
                result.success(null)
            }
            "reCreateLastPage" -> {
                Faraday.getCurrentContainer()?.rebuildFlutterPage()
                result.success(true)
            }
            else -> result.notImplemented()
        }
    }

    internal fun onPageCreate(route: String, args: Serializable?, id: Int, backgroundMode: String) {
        val data = hashMapOf<String, Any>()
        data["name"] = route
        if (args != null) {
            data["args"] = args
        }
        data["id"] = id
        data["background_mode"] = backgroundMode
        channel.invokeMethod("pageCreate", data, object: Result {
            override fun success(result: Any?) {
                print(result)
            }

            override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) {
                print(errorMessage)
            }

            override fun notImplemented() {
                print("notImplemented")
            }

        })
    }

    internal fun onPageShow(seqId: Int) {
        channel.invokeMethod("pageShow", seqId)
    }

    internal fun onPageDealloc(seqId: Int) {
        channel.invokeMethod("pageDealloc", seqId)
    }

    override fun onDetachedFromEngine(@NonNull binding: FlutterPlugin.FlutterPluginBinding) {
        channel.setMethodCallHandler(null)
    }

    override fun onAttachedToActivity(binding: ActivityPluginBinding) {
        this.binding = binding
    }

    override fun onAttachedToEngine(binding: FlutterPlugin.FlutterPluginBinding) {
        channel = MethodChannel(binding.binaryMessenger, "g_faraday")
        channel.resizeChannelBuffer(2)
        channel.setMethodCallHandler(this)
    }

    override fun onReattachedToActivityForConfigChanges(binding: ActivityPluginBinding) {
    }

    override fun onDetachedFromActivity() {
        this.binding = null
    }

    override fun onDetachedFromActivityForConfigChanges() {
    }
}

================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/ResultProvider.kt
================================================
package com.yuxiaor.flutter.g_faraday

import android.content.Intent

/**
 * Author: Edward
 * Date: 2020-10-22
 * Description:
 */
typealias ResultListener = (requestCode: Int, resultCode: Int, data: Intent?) -> Unit

interface ResultProvider {
    fun addResultListener(resultListener: ResultListener)
}

================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/CommonChannel.kt
================================================
package com.yuxiaor.flutter.g_faraday.channels

import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodChannel

/**
 * Author: Edward
 * Date: 2020-09-28
 * Description:桥接通道
 */
internal class CommonChannel(messenger: BinaryMessenger, handler: MethodChannel.MethodCallHandler) {

    private val channel by lazy { MethodChannel(messenger, "g_faraday/common") }

    init {
        channel.setMethodCallHandler(handler)
    }

}

================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/NavigatorAnchor.kt
================================================
//package com.yuxiaor.flutter.g_faraday.channels
//
//import android.app.Activity
//import android.content.Intent
//import com.yuxiaor.flutter.g_faraday.Faraday
//import io.flutter.plugin.common.MethodCall
//import io.flutter.plugin.common.MethodChannel
//
//internal object NavigatorAnchor: MethodChannel.MethodCallHandler {
//
//    private val channel = MethodChannel(Faraday.engine.dartExecutor, "g_faraday/anchor")
//
//    lateinit var anchors: MutableMap<String, Class<Activity>>
//        private set
//
//    init {
//        channel.setMethodCallHandler(this)
//    }
//
//    fun setup() {
//        anchors = mutableMapOf()
//    }
//
//    fun popToAnchor(identifier: String) {
//        channel.invokeMethod("popToAnchor", identifier)
//    }
//
//    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
//        when(call.method) {
//            "addAnchor" -> {
//                val key = call.arguments as String
//                Faraday.getCurrentActivity()?.let {
//                    anchors[key] = it.javaClass
//                }
//            }
//            "removeAnchor" -> {
//                val key = call.arguments as String
//                anchors.remove(key)
//            }
//            "replaceAnchor" -> {
//                val args = call.arguments as Map<*, *>
//                val key = args["id"] as String
//                val oldKey = args["oldID"] as String
//                anchors[oldKey]?.let {
//                    anchors.remove(oldKey)
//                    anchors[key] = it
//                }
//            }
//            "popToAnchor" -> {
//                val context = Faraday.getCurrentActivity() ?: return
//                val key = call.arguments as String
//                val intent = Intent(context, anchors[key])
//                intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_SINGLE_TOP
//                context.startActivity(intent)
//            }
//        }
//    }
//}
//
//// 跳转到指定锚点
//fun Faraday.popToAnchor(identifier: String) {
//    if (hasAnchor(identifier)) {
//        NavigatorAnchor.popToAnchor(identifier)
//    }
//}
//
//// 是否存在某个锚点
//fun Faraday.hasAnchor(identifier: String): Boolean {
//    return NavigatorAnchor.anchors.keys.contains(identifier)
//}
//


================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/NetChannel.kt
================================================
package com.yuxiaor.flutter.g_faraday.channels

import io.flutter.plugin.common.BinaryMessenger
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel
import java.util.*

/**
 * Author: Edward
 * Date: 2020-10-15
 * Description:网络桥接
 */
internal class NetChannel(messenger: BinaryMessenger, private val handler: NetHandler) : MethodChannel.MethodCallHandler {

    private val channel = MethodChannel(messenger, "g_faraday/net")

    init {
        channel.setMethodCallHandler(this)
    }


    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        val url = call.argument<String>("url") ?: return
        val params = call.argument<HashMap<String, Any>>("parameters")
        val headers = call.argument<HashMap<String, String>>("headers")
        handler.request(call.method, url, params, headers) {
            result.success(it)
        }
    }
}


interface NetHandler {

    /**
     * @param method GET POST PUT DELETE ...
     * @param url
     * @param params request params
     * @param headers request headers
     * @param onComplete callback the request response
     */
    fun request(method: String, url: String, params: HashMap<String, Any>?, headers: HashMap<String, String>?, onComplete: (result: Any?) -> Unit)

}

================================================
FILE: android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/NoticeChannel.kt
================================================
package com.yuxiaor.flutter.g_faraday.channels

import com.yuxiaor.flutter.g_faraday.Faraday
import io.flutter.embedding.engine.dart.DartExecutor
import io.flutter.plugin.common.MethodCall
import io.flutter.plugin.common.MethodChannel

/**
 * Author: Edward
 * Date: 2020-09-28
 * Description:通知
 */
internal object FaradayNotice : MethodChannel.MethodCallHandler {

    private val notifications = hashMapOf<String, NotificationCallback>()
    private var channel: MethodChannel? = null

    fun setup(dartExecutor: DartExecutor) {
        channel = MethodChannel(dartExecutor, "g_faraday/notification")
        channel?.setMethodCallHandler(this)
    }


    /**
     * 发送通知  native -> flutter
     */
    fun post(key: String, arguments: Any?) {
        channel?.invokeMethod(key, arguments)
    }

    /**
     * 注册接收通知  flutter -> native
     */
    fun register(key: String, callback: (arguments: Any?) -> Unit) {
        notifications[key] = object : NotificationCallback {
            override fun onReceiveNotification(arguments: Any?) {
                callback.invoke(arguments)
            }
        }
    }

    /**
     * for java
     */
    fun register(key: String, callback: NotificationCallback) {
        notifications[key] = callback
    }

    /**
     * 解除注册
     */
    fun unregister(key: String) {
        notifications.remove(key)
    }


    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        val key = call.method
        val args = call.arguments
        notifications[key]?.onReceiveNotification(args)

        result.success(notifications.containsKey(key))
    }
}


interface NotificationCallback {

    fun onReceiveNotification(arguments: Any?)
}



/**
 * post notification  form native to flutter
 */
fun Faraday.postNotification(key: String, arguments: Any?) {
    FaradayNotice.post(key, arguments)
}

/**
 * receive notification from flutter
 */
fun Faraday.registerNotification(key: String, callback: (arguments: Any?) -> Unit) {
    FaradayNotice.register(key, callback)
}

fun Faraday.unregisterNotification(key: String) {
    FaradayNotice.unregister(key)
}

================================================
FILE: doc/bridge.md
================================================
# 桥接原生方法

作为一个原生为主的混合应用,原生代码层肯定已经有了大量的基础设施例如加解密,或者本机缓存等等。想要调用这些本地`服务`有两种方式:

## FaradayCommon

faraday定义了一个特定的[channel](https://flutter.dev/docs/development/platform-integration/platform-channels)用于处理类似的需求。首先iOS/Android 需要实现指定接口

> 针对FaradayCommon我们提供了相应的[cli](https://github.com/gfaraday/cli)用来自动解析参数生成对应的接口文件

### flutter

``` dart
FaradayCommon.invokeMethod('method', 'arguments');
```

### ios

``` swift

// 0x00 定义一个用来处理 flutter端调用的处理函数,然后在Faraday初始化时传递给engine
func handle(_ name: String, _ arguments: Any?, _ completion: @escaping (_ result: Any?) -> Void) -> Void {
    // doSomething
}

// 0x01
Faraday.default.startFlutterEngine(navigatorDelegate: navigator, commonHandler: handle(_:_:_:))

```

### android

``` kotlin

// 0x00 首先需要实现这个接口 MethodChannel.MethodCallHandler
class CommonHandler: MethodChannel.MethodCallHandler {
    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
        print("Faraday-> ${call.method} not handle. argument: ${call.arguments}")
    }
}

// 0x01 Faraday 初始化以后,设置Handler给faraday即可
Faraday.setCommonHandler(CommonHandler())

```

## 自定义channel

你也可以完全自定义一个channel,用来处相应的逻辑

``` dart
const _channel = MethodChannel('g_faraday_custom/common');

//
_channel.invokeMethod('method', 'arguments');
```

然后在ios/android端注册对应的channel 然后处理即可


================================================
FILE: doc/callback.md
================================================
# 页面间传值

## Flutter侧

在`flutter`这边传值比较容易,不管是`flutter->flutter`还是`flutter->native`或者`native-flutter`都和`纯flutter`写法无任何差异例如:

``` dart

// push 路由以后等待 被push的路由 pop时的result
final result = await Navigator.of(context).push(route);

// 关闭当前flutter页面,并将result传递到上一个页面
Navigator.of(context).pop({'id': 1});

```

## iOS

> 需要在 applicationDidFinish 中调用 `UIViewController.fa.automaticallyCallbackNullToFlutter()`

一共有两种情况需要处理

- native 打开一个flutter页面然后等待返回值

``` swift

// 初始化一个 FaradayFlutterViewController 的对象
let vc = FaradayFlutterViewController(page.name, arguments: page.arguments) { result in
    /**
        这里的 result 即flutter侧关闭页面时的回调

        ``` dart
        // 关闭并且传值
        Navigator.of(context).pop({'id': 1});
        ```
    **/
    debugPrint(result.toString() ?? '') // print {'id': 1}
}
```

- 从flutter侧打开一个native页面, 然后等待native页面返回值

``` dart

// 从flutter打开native页面只需要调用
final result = await Navigator.of(context).nativePushNamed('native_page_name');

```

flutter侧调用`nativePushNamed(:)`以后,native侧的`FaradayNavigationDelegate` `push`方法会被调用,只需要在此方法中 `push`一个对应页面的控制器即可,那么这个控制器如何回调给flutter层呢

``` swift

// flutter打开native,native回调值给flutter一共有3种情况

// 假设被打开的控制器为:vc

// 1.控制器是被 push的
vc.navigatorController?.fa.popViewController(withResult: result, animation: true)

// 2. 控制器是被 present的
vc.fa.dismiss(withResult: result, animation: true)

// 3. 控制器是被 `addChild` 等其他方式加载到当前堆栈的
//    那么需要在 vc 移除堆栈时调用
vc.fa.callback(result: result)

```

## Android

- 从`native`打开一个`flutter`页面,然后等待`flutter`返回值,与打开原生页面无异

``` kotlin

   //以 startActivityForResult方式打开flutter页面,FaradayActivity为flutter页面容器
val intent = FaradayActivity.build(context, route,arguments)
startActivityForResult(intent, requestCode)

...
   //重写onActivityResult方法获得返回值
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
    super.onActivityResult(requestCode, resultCode, data)
    val value = data?.getStringExtra("key")
    //TODO ...
}

```

- 从`flutter`打开一个`native`页面, 然后等待`native`页面返回值

打开`native`页面,并等待返回值

```dart
Navigator.of(context).nativePushNamed('native route').then((result) {
      print('返回值:$result')
});
```

`native`页面返回值给`flutter`,只能传递flutter支持的数据类型

```kotlin
//传递基础数据类型
setResult(RESULT_OK, Intent().apply {
    putExtra("result", "data form native")
}
//传递HashMap,map泛型须为基础类型
setResult(RESULT_OK, Intent().apply {
    putExtra("result", hashMapOf("data" to 123))
}
//传递ArrayList,ArrayList中只能是String或Int
setResult(RESULT_OK, Intent().apply {
    putStringArrayListExtra("result", ArrayList())
})

//复杂数据建议转换成json字符串传递
});
```

## 其他特殊场景路由处理

### 在`flutter`中打开一个新的native页面用来`push` `flutter`路由

``` dart

// 在原生`ios|android`的`FaradayNavigationDelegate`中根据对应的`name`和`arguments`返回`FaradayFlutterViewController`即可
Navigator.of(context).nativePushNamed('native_page_name', options: {'flutter': true});

```

### 关闭当前`flutter`容器

``` dart

Navigator.of(context).nativePop(result);

```


================================================
FILE: doc/ci.md
================================================
# TODO 后面写详细文档


================================================
FILE: doc/ios-simulator-install.md
================================================

# ios 模拟器安装app

``` shell

# 启动模拟器
xcrun instruments -w 'iPhone 12'

# 安装
xcrun simctl install booted path/to/example.app

```


================================================
FILE: doc/ios_navigation_bar.md
================================================
# iOS Navigation Bar

`FlutterViewController` 需要隐藏`navigation bar`,因此我们需要在这个vc显示隐藏的时候对应的处理`navigation bar`的隐藏显示逻辑。这里我们提供了一个扩展用来自动处理显示隐藏逻辑

``` swift
// 自动处理 Navigation bar逻辑,内部由method_swizzle实现, 请保证此方法只会调用一次
UINavigationController.fa.automaticallyHandleNavigationBarHidden()

```

如果你原生的页面也需要隐藏`navigation bar`,那么你只需要实现此协议即可

``` swift

extension SomeViewController: FaradayNavigationBarHiddenProtocol { }

```


================================================
FILE: doc/json.md
================================================
# JSON

json在我们日常开发中已经变的非常重要了,用来传递数据可读性非常的好。我们将对json的处理单独剥离出来成为一个独立的`package`:

[https://pub.dev/packages/g_json](https://pub.dev/packages/g_json)

同时我们在`faraday`中也提供了以下扩展方法

``` dart

extension RouteSettingsFaraday on RouteSettings {
  ///
  /// eg:
  /// final arg = settings.toJson;
  /// final id = arg.id;
  /// final name = arg.name;
  /// final types = arg.types;
  ///
  dynamic get toJson => JSON(arguments);
}
```

在使用`RouteSettings`来创建页面的时候可以很方便的读取参数


================================================
FILE: doc/net.md
================================================
# Net

`g_faraday`默认现有的`ios`&`android`已经存在大量的网络基础设施(包括但不限于登录验证,加解密等等)

> 如果没有没有你可以跳过此部分内容

## Flutter

`flutter`侧我们提供了`FaradayNet`用来进行网络请求

``` dart

final response = await FaradayNet.request('get', '/user', parameters: {'id': 1}, headers: {'ua': 'g_faraday'});

```

## Native

native侧需要实现`flutter`侧的方法,在ios和android中定义如下

### ios

``` swift

// 接口定义
public protocol FaradayHttpProvider: AnyObject {

    func request(method: String, url: String, parameters: [String: Any]?, headers: [String: String]?, completion: @escaping (_ result: Any?) -> Void) -> Void
}

// implementation example
extension AppDelegate: FaradayHttpProvider {

    func request(method: String, url: String, parameters: [String : Any]?, headers: [String : String]?, completion: @escaping (Any?) -> Void) {
        let afHeaders = headers.map { HTTPHeaders($0) }
        // 假设使用 Alamofire实现网络请求
        let dataRequest = AF.request(url, method: HTTPMethod(rawValue: method.uppercased()), parameters: parameters, headers: afHeaders)
        dataRequest.responseJSON { response in
            switch response.result {
                case .success(let data):
                    completion(["data": data, "errorCode": 0])
                case .failure(let error):
                    completion(["message": error.localizedDescription, "errorCode": error.responseCode ?? 1])
            }
        }
    }

}

// 使用
Faraday.default.startFlutterEngine(navigatorDelegate: self, httpProvider: self, commonHandler: self.handle(_:_:_:), automaticallyRegisterPlugins: true)

```

### android

``` kotlin

// 定义
interface NetHandler {

    /**
     * @param method GET POST PUT DELETE ...
     * @param url
     * @param params request params
     * @param headers request headers
     * @param onComplete callback the request response
     */
    fun request(method: String, url: String, params: HashMap<String, Any>?, headers: HashMap<String, String>?, onComplete: (result: Any?) -> Unit)

}

//
class FaradayNet : NetHandler {
    private val api = Net.create<FaradayFutureApi>()

    interface FaradayFutureApi {

        @GET
        fun get(@Url url: String, @QueryMap params: HashMap<String, Any>?): Call<JsonElement>

        @POST
        fun post(@Url url: String, @Body body: HashMap<String, Any>?): Call<JsonElement>

        @PUT
        fun put(@Url url: String, @Body body: HashMap<String, Any>?): Call<JsonElement>

        @DELETE
        fun delete(@Url url: String, @QueryMap map: HashMap<String, Any>?): Call<JsonElement>
    }

    override fun request(method: String, url: String, params: HashMap<String, Any>?, headers: HashMap<String, String>?, onComplete: (result: Any?) -> Unit) {
        val args = params ?: hashMapOf()
        val netCall = when (method.toUpperCase(Locale.getDefault())) {
            "GET" -> api.get(url, args)
            "POST" -> api.post(url, args)
            "PUT" -> api.put(url, args)
            "DELETE" -> api.delete(url, args)
            else -> throw RuntimeException("Unsupported method $method")
        }

        MainScope().launch(NetErrorHandler) {
            val response = netCall.call()
            if (response.code() !in 200..300) {
                throw HttpException(response)
            }
            onComplete.invoke(succeed(response.body()))
        }.onError { code, message ->
            onComplete.invoke(failed(code, message))
        }
    }

    private suspend fun <T> Call<T>.call() = suspendCoroutine<Response<T>> { continuation ->
        GlobalScope.launch(Dispatchers.IO) {
            try {
                val response = execute()
                continuation.resume(response)
            } catch (t: Throwable) {
                continuation.resumeWithException(t)
            }
        }
    }

    private fun succeed(json: JsonElement?): Map<String, Any?> {
        return mapOf("code" to 200, "data" to json?.toString(), "fromAndroid" to true)
    }

    private fun failed(code: String, message: String): Map<String, Any?> {
        return mapOf("code" to code, "msg" to message)
    }
}

//
Faraday.setNetHandler(FaradayNet())

```


================================================
FILE: doc/notification.md
================================================
# 通知

通过全局的通知来传递数据,或者驱动业务不是一个很好的软件模式,但是在某些特定的场景却可以节省大量的时间。我们对混合app通知做了部分封装方便大家开发业务时使用。

## flutter

``` dart

// 构造相应的通知对象
final notification = FaradayNotification('NotificationKey', {'id': 1234});

// 发送 (会同时发送到flutter和native)
notification.dispatchToGlobal(deliverToNative: true);

// 接收 (可以同时接收到native和flutter通知)
FaradayNotificationListener(
      ['NotificationKey'],
      onNotification: (n) => debugPrint('$n'),
      child: xxx,
    );
```

## ios

``` swift

// 发送 (只会发送到flutter,如需发送到native请自行广播)
NotificationCenter.fa.post(name: "NotificationKey", object: ["id": 1234])

// 接收 (可以同时接收到native和flutter通知)
let center = NSNotificationCenter.defaultCenter()
let mainQueue = NSOperationQueue.mainQueue()
var token: NSObjectProtocol?
token = center.addObserverForName("NotificationKey", object: nil, queue: mainQueue) { (note) in
    print("Received the notification! \(note)")
    center.removeObserver(token!)
}

```

## android

``` kotlin

// 发送 (只会发送到flutter,如需发送到native请自行广播)
Faraday.postNotification("NotificationKey", mapOf("id" to 1234))

// 接收 (只能接收flutter侧通知)
Faraday.registerNotification("NotificationKey") { params ->
    //解除注册
    Faraday.unregisterNotification("NotificationKey")
}

```


================================================
FILE: doc/route.md
================================================
# 路由

`g_faraday`是作为一个解决混合路由栈的框架而开发的,因此对路由的支持特别完备。`g_faraday`采用最小入侵的设计原则,不管是在`native`侧还是`flutter`侧,只需要在程序入口处做少量的注册即可完成集成。
同时页面跳转,页面间传值也不需要做任何自定义,也就是说一个纯flutter应用做很小量的改动即可无缝集成自现有应用。

## flutter 侧路由

在flutter侧我们只需要注册所有需要从原生打开的路由即可,其他不需要从原生直接进入的页面,不需要做任何改动。

### 打开页面

``` dart
    Navigator.of(context).push('/home' {'id': 1234});
```

### 关闭页面

``` dart
    Navigator.of(context).pop({'succeed': true});
```

### 关闭所有flutter页面

``` dart
    Navigator.of(context).nativePop('result');
```

以上只是部分`Navigator`方法示例,理论上`g_faraday`支持所有原生的路由方法。

## ios

ios端也特别类似只需要使用页面名称`name`和页面参数`arguments`来生成一个普通的`ViewController`即可,你可以使用`push`、`present`、`addChild`等任意方式将`ViewController`对象加入到页面栈即可

``` swift

    /// push
    let vc = FaradayFlutterViewController(name, arguments: arguments)
    navigatorController?.pushViewController(vc, animated: true)

    // add to Tab bar Controller
    let vc = FaradayFlutterViewController(name, arguments: arguments)
    vc.willMove(toParent: self)
    addChild(vc)
    view.addSubview(vc.view)
    vc.didMove(toParent: self)
```

## android

同理android也可以作为一个独立的activity或者一个嵌入的fragment来使用

``` kotlin
    // 创建intent 然后start 即可
    val intent = FaradayActivity.build(context, routeName, params)
    context.startActivity(intent)

    //
    val fragment = FaradayFragment.newInstance(name, arguments)
    // add fragment to fragment manager
```


================================================
FILE: example/.gitignore
================================================
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/

# IntelliJ related
*.iml
*.ipr
*.iws
.idea/

# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/

# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/

# Web related
lib/generated_plugin_registrant.dart

# Symbolication related
app.*.symbols

# Obfuscation related
app.*.map.json

# Exceptions to above rules.
!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages

lib/src/debug

================================================
FILE: example/.metadata
================================================
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.

version:
  revision: bbfbf1770cca2da7c82e887e4e4af910034800b6
  channel: stable

project_type: app


================================================
FILE: example/.vscode/launch.json
================================================
{
    "configurations": [
        {
            "name": "g_faraday demo fluro",
            "type": "dart",
            "request": "launch",
            "program": "lib/main_fluro.dart",
            "args": [
                "--no-sound-null-safety"
            ]
        },
        {
            "name": "g_faraday get fluro",
            "type": "dart",
            "request": "launch",
            "program": "lib/main_get.dart",
            "args": [
                "--no-sound-null-safety"
            ]
        },
    ]
}

================================================
FILE: example/.vscode/settings.json
================================================
{
    "cSpell.words": [
        "ARGB",
        "Scrollable"
    ]
}

================================================
FILE: example/README.md
================================================
# g_faraday_example

## 主要包含一下功能点 (TODO)

### Basic

* native -> flutter (ios: push/present android: activity/fragment)
* flutter -> native (ios: handle navigation bar android: back button)
* native -> flutter -> native ()
* ios addChildViewController
* android ViewPager Fragment

### others

* notification
* getPlatformVersions


================================================
FILE: example/analysis_options.yaml
================================================
include: package:flutter_lints/flutter.yaml

linter:
  rules:
    public_member_api_docs: false
    library_private_types_in_public_api: false

================================================
FILE: example/android/.gitignore
================================================
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java

# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties


================================================
FILE: example/android/app/build.gradle
================================================
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
    localPropertiesFile.withReader('UTF-8') { reader ->
        localProperties.load(reader)
    }
}

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: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"

def keystoreProperties = new Properties()
def keystorePropertiesFile = rootProject.file('key.properties')
if (keystorePropertiesFile.exists()) {
    keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
}

android {
    compileSdkVersion 33

    sourceSets {
        main.java.srcDirs += 'src/main/kotlin'
    }

    lintOptions {
        disable 'InvalidPackage'
    }

    defaultConfig {
        applicationId "com.yuxiaor.flutter.g_faraday_example"
        minSdkVersion 23
        targetSdkVersion 33
        versionCode 2
        versionName "1.0.0"
    }

    signingConfigs {
//       release {
//           keyAlias keystoreProperties['keyAlias']
//           keyPassword keystoreProperties['keyPassword']
//           storeFile file(keystoreProperties['storeFile'])
//           storePassword keystoreProperties['storePassword']
//       }
    }

    buildTypes {
//       release {
//           signingConfig signingConfigs.release
//       }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    kotlinOptions {
        jvmTarget = '1.8'
    }
}

flutter {
    source '../..'
}

dependencies {
    implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
    implementation 'androidx.appcompat:appcompat:1.4.2'
    implementation 'androidx.core:core-ktx:1.9.0-alpha05'
    implementation 'com.google.android.material:material:1.6.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
    implementation 'androidx.navigation:navigation-fragment-ktx:2.4.2'
    implementation 'androidx.navigation:navigation-ui-ktx:2.4.2'
}


================================================
FILE: example/android/app/release/output-metadata.json
================================================
{
  "version": 2,
  "artifactType": {
    "type": "APK",
    "kind": "Directory"
  },
  "applicationId": "com.yuxiaor.flutter.g_faraday_example",
  "variantName": "processReleaseResources",
  "elements": [
    {
      "type": "SINGLE",
      "filters": [],
      "versionCode": 1,
      "versionName": "1.0",
      "outputFile": "app-release.apk"
    }
  ]
}

================================================
FILE: example/android/app/src/main/AndroidManifest.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yuxiaor.flutter.g_faraday_example">

    <uses-permission android:name="android.permission.INTERNET" />

    <application
        android:name=".App"
        android:allowBackup="false"
        android:icon="@mipmap/ic_launcher"
        android:label="Faraday"
        android:theme="@style/AppTheme">

        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />

        <activity
            android:name=".activity.SingleTopFlutterActivity"
            android:launchMode="singleTop" />
        <activity
            android:name=".activity.SingleTaskFlutterActivity"
            android:launchMode="singleTask" />

        <activity android:name=".activity.splash.FirstFlutterActivity">

            <!-- 在这里你可以自定义 启动画面动画 -->
<!--            <meta-data-->
<!--                android:name="io.flutter.embedding.android.SplashScreenDrawable"-->
<!--                android:resource="@drawable/launch_background" />-->
            <meta-data
                android:name="io.flutter.embedding.android.NormalTheme"
                android:resource="@style/SplashTheme"
                />

        </activity>

        <activity android:name=".basic.FlutterToNativeActivity" />
        <activity android:name=".basic.Native2FlutterActivity" />
        <activity android:name=".basic.TabContainerActivity" />

        <activity android:name=".activity.MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <activity android:name=".basic.TransparentBackgroundFlutterActivity" android:theme="@style/TransparentActivityTheme"/>
    </application>

</manifest>

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/App.kt
================================================
package com.yuxiaor.flutter.g_faraday_example

import android.app.Application
import com.yuxiaor.flutter.g_faraday.Faraday
import com.yuxiaor.flutter.g_faraday_example.faraday.CustomNavigator

/**
 * Author: Edward
 * Date: 2020-09-02
 * Description:
 */
class App : Application() {
    override fun onCreate() {
        super.onCreate()
        Faraday.startFlutterEngine(this, CustomNavigator)
    }
}


================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/MainActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.activity

import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import com.yuxiaor.flutter.g_faraday_example.R
import com.yuxiaor.flutter.g_faraday_example.activity.splash.FirstFlutterActivity

class MainActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
    }

    override fun onStart() {
        super.onStart()

        // 跳转到 flutter `home` 路由
        val intent = FirstFlutterActivity.build(this)

        // 直接打开flutter 页面
        startActivity(intent)

        //
        finish()

        // 阻止动画
        overridePendingTransition(0, 0)

    }
}


================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/SingleTaskFlutterActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.activity

import com.yuxiaor.flutter.g_faraday.FaradayActivity

// https://hit-alibaba.github.io/interview/Android/basic/Android-LaunchMode.html
class SingleTaskFlutterActivity: FaradayActivity()

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/SingleTopFlutterActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.activity

import com.yuxiaor.flutter.g_faraday.FaradayActivity

// https://hit-alibaba.github.io/interview/Android/basic/Android-LaunchMode.html
class SingleTopFlutterActivity: FaradayActivity()

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/splash/FirstFlutterActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.activity.splash

import android.content.Context
import android.os.Build
import android.os.Bundle
import android.window.SplashScreenView
import com.yuxiaor.flutter.g_faraday.Faraday
import com.yuxiaor.flutter.g_faraday.FaradayActivity
import com.yuxiaor.flutter.g_faraday.channels.postNotification
import com.yuxiaor.flutter.g_faraday.channels.registerNotification
import com.yuxiaor.flutter.g_faraday.channels.unregisterNotification
import com.yuxiaor.flutter.g_faraday_example.widget.NotificationDialog


class FirstFlutterActivity : FaradayActivity() {

    companion object {
        fun build(context: Context) = builder<FirstFlutterActivity>("home", null, true).build(context)
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        Faraday.registerNotification("GlobalNotification") {
            showNotification()
        }

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            // Disable the Android splash screen fade out animation to avoid
            // a flicker before the similar frame is drawn in Flutter.
            splashScreen
                .setOnExitAnimationListener { splashScreenView: SplashScreenView -> splashScreenView.remove() }
        }
    }

    private fun showNotification() {
        NotificationDialog(this, "Notification from Flutter").apply {
            setOnDismissListener {
                Faraday.postNotification("NotificationFromNative", "Hi, Android ${Build.VERSION.RELEASE}")
            }
        }.show()
    }

    override fun onDestroy() {
        super.onDestroy()
        Faraday.unregisterNotification("GlobalNotification")
    }
}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/FlutterToNativeActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.basic

import android.content.Intent
import android.os.Bundle
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import com.yuxiaor.flutter.g_faraday_example.R
import java.util.*

/**
 * Author: Edward
 * Date: 2020-11-26
 * Description:
 */
class FlutterToNativeActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_flutter2native)
        findViewById<Button>(R.id.btn).setOnClickListener {
            val intent = Intent()
            intent.putExtra("date", Date().toString())
            setResult(RESULT_OK, intent)
            finish()
        }
        actionBar?.title = "Flutter2Native"
    }

}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/Native2FlutterActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.basic

import android.content.Intent
import android.graphics.Color
import android.os.Bundle
import android.widget.Button
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import com.yuxiaor.flutter.g_faraday.FaradayActivity
import com.yuxiaor.flutter.g_faraday_example.R
import com.yuxiaor.flutter.g_faraday_example.faraday.KEY_ARGS
import java.util.*

class Native2FlutterActivity: AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_native2flutter)

        findViewById<Button>(R.id.button).setOnClickListener {
            val intent = FaradayActivity.builder(routeName = "native2flutter", Date().toString()).build(this)
            startActivityForResult(intent, 1)
        }

        findViewById<Button>(R.id.transparentButton).setOnClickListener {
            val intent = TransparentBackgroundFlutterActivity.build(this)
            startActivity(intent)
            // 阻止动画
            overridePendingTransition(0, 0)
        }

        actionBar?.title = "Native2Flutter"
    }

    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        super.onActivityResult(requestCode, resultCode, data)
        data?.extras.let {
            val textView = findViewById<TextView>(R.id.result)
            if (it != null) {
                textView.text = it.get(KEY_ARGS)?.toString()
                textView.setTextColor(Color.RED)
            } else {
                textView.text = null
            }
        }
    }
}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/TabContainerActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.basic

import android.content.Intent
import android.os.Bundle
import android.widget.RadioButton
import androidx.appcompat.app.AppCompatActivity
import androidx.fragment.app.Fragment
import com.yuxiaor.flutter.g_faraday.FaradayFragment
import com.yuxiaor.flutter.g_faraday_example.R
import com.yuxiaor.flutter.g_faraday_example.fragment.TestFragment

class TabContainerActivity : AppCompatActivity() {

    private var tempFragment: Fragment? = null
    private val flutterFrag1 = FaradayFragment.newInstance("tab1")
    private val flutterFrag2 = FaradayFragment.newInstance("home")
    private val nativeFrag1 = TestFragment.newInstance("native fragment 1")
    private val nativeFrag2 = TestFragment.newInstance("native fragment 2")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_tab_container)

        val tab1 = findViewById<RadioButton>(R.id.tab1)
        val tab2 = findViewById<RadioButton>(R.id.tab2)
        val tab3 = findViewById<RadioButton>(R.id.tab3)
        val tab4 = findViewById<RadioButton>(R.id.tab4)

        tab1.setOnClickListener { switchFragment(flutterFrag1, "F1") }
        tab2.setOnClickListener { switchFragment(nativeFrag1, "N1") }
        tab3.setOnClickListener { switchFragment(flutterFrag2, "F2") }
        tab4.setOnClickListener { switchFragment(nativeFrag2, "N2") }

        switchFragment(flutterFrag1, "F1")
    }

    private fun switchFragment(fragment: Fragment, tag: String) {
        if (tempFragment == fragment) return
        if (tag == "F2") {
            supportActionBar?.hide()
        } else {
            supportActionBar?.show()
        }
        val transaction = supportFragmentManager.beginTransaction()
        if (!fragment.isAdded) {
            transaction.add(R.id.fragment_container, fragment, tag)
        }
        transaction.show(fragment)
        tempFragment?.let { transaction.hide(it) }
//        transaction.replace(R.id.frag, fragment)
//        transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN)
//        transaction.addToBackStack(null)
        tempFragment = fragment
        transaction.commitNow()
    }

    override fun onTrimMemory(level: Int) {
        super.onTrimMemory(level)
        if (tempFragment is FaradayFragment) {
            (tempFragment as FaradayFragment).onTrimMemory(level)
        }
    }

    override fun onUserLeaveHint() {
        super.onUserLeaveHint()
        if (tempFragment is FaradayFragment) {
            (tempFragment as FaradayFragment).onUserLeaveHint()
        }
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)
        if (tempFragment is FaradayFragment && intent != null) {
            (tempFragment as FaradayFragment).onNewIntent(intent)
        }
    }

    override fun onPostResume() {
        super.onPostResume()
        if (tempFragment is FaradayFragment) {
            (tempFragment as FaradayFragment).onPostResume()
        }
    }

    override fun onBackPressed() {
        if (tempFragment is FaradayFragment) {
            (tempFragment as FaradayFragment).onBackPressed()
        } else {
            super.onBackPressed()
        }
    }

    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (tempFragment is FaradayFragment) {
            (tempFragment as FaradayFragment).onRequestPermissionsResult(requestCode, permissions, grantResults)
        }
    }
}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/TransparentBackgroundFlutterActivity.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.basic

import android.content.Context
import android.graphics.Color
import com.yuxiaor.flutter.g_faraday.FaradayActivity

class TransparentBackgroundFlutterActivity: FaradayActivity() {
    companion object {
        fun build(context: Context) = builder<TransparentBackgroundFlutterActivity>("transparent_flutter",
                backgroundColor = Color.TRANSPARENT).build(context)
    }
}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/fragments/NativeFragment.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.basic.fragments

import androidx.fragment.app.Fragment

class NativeFragment: Fragment() {
}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/faraday/CustomNavigator.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.faraday

import android.app.Activity
import android.content.Intent
import android.graphics.Color
import android.net.Uri
import com.yuxiaor.flutter.g_faraday.Faraday
import com.yuxiaor.flutter.g_faraday.FaradayActivity
import com.yuxiaor.flutter.g_faraday.FaradayNavigator
import com.yuxiaor.flutter.g_faraday.Options
import com.yuxiaor.flutter.g_faraday_example.activity.SingleTaskFlutterActivity
import com.yuxiaor.flutter.g_faraday_example.activity.SingleTopFlutterActivity
import com.yuxiaor.flutter.g_faraday_example.basic.FlutterToNativeActivity
import com.yuxiaor.flutter.g_faraday_example.basic.Native2FlutterActivity
import com.yuxiaor.flutter.g_faraday_example.basic.TabContainerActivity
import com.yuxiaor.flutter.g_faraday_example.basic.TransparentBackgroundFlutterActivity
import java.io.Serializable

const val KEY_ARGS = "_args"

object CustomNavigator : FaradayNavigator {

    override fun create(name: String, arguments: Serializable?, options: Options): Intent? {
        val context = Faraday.getCurrentActivity() ?: return null

        if (options.isFlutterRoute) {

            // singleTask 模式
            val builder = FaradayActivity.builder(name, arguments, false)

            // 你看到的绿色的闪屏就是这个
            builder.backgroundColor = Color.WHITE
            builder.activityClass = SingleTopFlutterActivity::class.java

            return builder.build(context);
        }


        when (name) {
            "flutter2native" -> {
                return Intent(context, FlutterToNativeActivity::class.java)
            }
            "native2flutter" -> {
                return Intent(context, Native2FlutterActivity::class.java)
            }
            "tabContainer" -> {
                return Intent(context, TabContainerActivity::class.java)
            }
            else -> {
                val intent = Intent(Intent.ACTION_VIEW)
                intent.data = Uri.parse(name)
                intent.putExtra(KEY_ARGS, arguments)
                return intent
            }
        }

    }

    override fun pop(result: Serializable?) {
        val activity = Faraday.getCurrentActivity() ?: return
        if (result != null) {
            activity.setResult(Activity.RESULT_OK, Intent().apply { putExtra(KEY_ARGS, result) })
        }
        activity.finish()

        if (activity is TransparentBackgroundFlutterActivity) {
            activity.overridePendingTransition(0, 0)
        }
    }

    override fun enableSwipeBack(enable: Boolean) {

    }
}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/fragment/TestFragment.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.fragment

import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.fragment.app.Fragment
import com.yuxiaor.flutter.g_faraday_example.R

/**
 * Author: Edward
 * Date: 2020-09-07
 * Description:
 */
class TestFragment : Fragment() {


    companion object {

        fun newInstance(text: String): TestFragment {
            return TestFragment().apply {
                arguments = Bundle().apply {
                    putString("text", text)
                }
            }
        }
    }

    override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
        return inflater.inflate(R.layout.frag_test, container, false)
    }

    override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
        super.onViewCreated(view, savedInstanceState)
        val textView = view.findViewById<TextView>(R.id.fragText)
        textView.text = arguments?.getString("text")
    }

}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/utils/ViewExt.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.utils

import android.content.res.Resources
import android.graphics.Outline
import android.util.TypedValue
import android.view.View
import android.view.ViewOutlineProvider

/**
 * Author: Edward
 * Date: 2020-11-27
 * Description:
 */
val Float.dp
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this, Resources.getSystem().displayMetrics)
val Int.dp
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, this.toFloat(), Resources.getSystem().displayMetrics).toInt()
val Float.sp
    get() = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, this, Resources.getSystem().displayMetrics)

fun View.setCorner(corner: Float) {
    clipToOutline = true
    outlineProvider = object : ViewOutlineProvider() {
        override fun getOutline(view: View, outline: Outline) {
            outline.setRoundRect(0, 0, view.measuredWidth, view.measuredHeight, corner.dp)
        }
    }
}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/widget/BaseDialog.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.widget

import android.content.Context
import android.os.Bundle
import android.view.Gravity
import android.view.WindowManager
import androidx.appcompat.app.AlertDialog
import com.yuxiaor.flutter.g_faraday_example.R

/**
 * @Author Edward
 * @Date 2019/5/11 0011
 * @Description:
 */
abstract class BaseDialog(context: Context) : AlertDialog(context, R.style.DialogTheme) {


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setWindow()
    }

    private fun setWindow() {
        val params = window?.attributes
        params?.width = WindowManager.LayoutParams.MATCH_PARENT
        params?.height = WindowManager.LayoutParams.WRAP_CONTENT
        params?.gravity = gravity()
        params?.dimAmount = alpha()
        window?.attributes = params
        if (anim() != -1) {
            window?.setWindowAnimations(anim())
        }
    }

    /**
     * 位置
     */
    open fun gravity(): Int {
        return Gravity.CENTER
    }

    /**
     * 动画
     */
    open fun anim(): Int {
        return -1
    }

    /**
     * 背景透明度
     */
    open fun alpha(): Float {
        return 0.5f
    }

}

================================================
FILE: example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/widget/NotificationDialog.kt
================================================
package com.yuxiaor.flutter.g_faraday_example.widget

import android.annotation.SuppressLint
import android.content.Context
import android.os.Bundle
import android.os.Handler
import android.os.Looper
import android.widget.RelativeLayout
import android.widget.TextView
import com.yuxiaor.flutter.g_faraday_example.R
import com.yuxiaor.flutter.g_faraday_example.utils.setCorner

/**
 * Author: Edward
 * Date: 2020-11-27
 * Description:
 */
class NotificationDialog(context: Context, private val msg: String) : BaseDialog(context), Runnable {

    private val view by lazy { findViewById<RelativeLayout>(R.id.contentView) }
    private val titleTxt by lazy { findViewById<TextView>(R.id.titleTxt) }
    private val msgTxt by lazy { findViewById<TextView>(R.id.msgTxt) }
    private val handler by lazy { Handler(Looper.getMainLooper()) }
    private var time = 3


    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setCancelable(false)
        setContentView(R.layout.dialog_notification)
        view?.setCorner(8f)
        msgTxt?.text = msg
        handler.post(this)
    }

    @SuppressLint("SetTextI18n")
    override fun run() {
        titleTxt?.text = "Notification (${time})"
        time--
        if (time >= 0) {
            handler.postDelayed(this, 1000)
        } else {
            handler.removeCallbacks(this)
            dismiss()
        }
    }
}

================================================
FILE: example/android/app/src/main/res/anim/in_from_left.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="-100%p"
    android:fromYDelta="0"
    android:toXDelta="0"
    android:toYDelta="0" >

</translate>

================================================
FILE: example/android/app/src/main/res/anim/in_from_right.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="100%p"
    android:fromYDelta="0"
    android:toXDelta="0"
    android:toYDelta="0" >

</translate>

================================================
FILE: example/android/app/src/main/res/anim/out_from_left.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="-100%p"
    android:toYDelta="0" >

</translate>

================================================
FILE: example/android/app/src/main/res/anim/out_from_right.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="300"
    android:fromXDelta="0"
    android:fromYDelta="0"
    android:toXDelta="100%p"
    android:toYDelta="0" >

</translate>

================================================
FILE: example/android/app/src/main/res/color/check_primary_light.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:color="@color/colorPrimary" android:state_checked="true" />
    <item android:color="@color/light" android:state_checked="false" />
</selector>

================================================
FILE: example/android/app/src/main/res/drawable/launch_background.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:drawable="@android:color/white" />

    <item>
        <bitmap
            android:gravity="center"
            android:src="@mipmap/ic_launcher" />
    </item>
</layer-list>


================================================
FILE: example/android/app/src/main/res/drawable/tab_file.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="1024"
    android:viewportHeight="1024">
    <path
        android:fillColor="@color/check_primary_light"
        android:pathData="M365.71,128l41.87,91.43h208.82L658.29,128h91.43a109.71,109.71 0,0 1,109.71 109.71v548.57a109.71,109.71 0,0 1,-109.71 109.71L274.29,896a109.71,109.71 0,0 1,-109.71 -109.71L164.57,237.71a109.71,109.71 0,0 1,109.71 -109.71zM676.57,603.43L347.43,603.43a36.57,36.57 0,0 0,0 73.14h329.14a36.57,36.57 0,0 0,0 -73.14zM676.57,438.86L347.43,438.86a36.57,36.57 0,0 0,0 73.14h329.14a36.57,36.57 0,0 0,0 -73.14z" />
</vector>


================================================
FILE: example/android/app/src/main/res/drawable/tab_home.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="1024"
    android:viewportHeight="1024">
    <path
        android:fillColor="@color/check_primary_light"
        android:pathData="M528.46,126.54l333.71,254.72A49.55,49.55 0,0 1,881.37 420.57v432.64a49.01,49.01 0,0 1,-49.01 49.19L184.14,902.4a49.01,49.01 0,0 1,-49.01 -49.19L135.13,420.57a49.19,49.19 0,0 1,18.29 -38.22L467.75,128a49.19,49.19 0,0 1,60.71 -1.46zM699.98,506.51a29.26,29.26 0,0 0,-41.14 6.4c-47.36,64.91 -97.65,96 -151.77,96S402.29,577.83 352.73,512l-1.83,-2.19A29.44,29.44 0,0 0,305.55 548.57c59.43,78.81 126.72,119.77 201.14,119.77s142.08,-41.69 199.86,-119.77l1.46,-2.38a29.26,29.26 0,0 0,-8.05 -39.68z" />
</vector>


================================================
FILE: example/android/app/src/main/res/drawable/tab_house.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="1024"
    android:viewportHeight="1024">
    <path
        android:fillColor="@color/check_primary_light"
        android:pathData="M603.43,138.97a54.86,54.86 0,0 1,54.86 54.86v694.86L199.31,888.69A57.23,57.23 0,0 1,146.29 828.34L146.29,193.83a54.86,54.86 0,0 1,54.86 -54.86zM841.14,413.26a36.57,36.57 0,0 1,36.57 36.57v402.29a36.57,36.57 0,0 1,-36.57 36.57h-128v-438.86a36.57,36.57 0,0 1,36.57 -36.57zM316.34,416.91a32,32 0,0 0,-31.09 31.09v54.86a29.81,29.81 0,0 0,31.09 31.09,32 32,0 0,0 31.09,-31.09v-54.86a32,32 0,0 0,-31.09 -31.09zM491.89,416.91a32,32 0,0 0,-31.09 31.09v54.86a28.89,28.89 0,0 0,31.09 31.09,32 32,0 0,0 31.09,-31.09v-54.86a32,32 0,0 0,-31.09 -31.09z" />
</vector>


================================================
FILE: example/android/app/src/main/res/drawable/tab_msg.xml
================================================
<vector xmlns:android="http://schemas.android.com/apk/res/android"
    android:width="24dp"
    android:height="24dp"
    android:viewportWidth="1024"
    android:viewportHeight="1024">
    <path
        android:fillColor="@color/check_primary_light"
        android:pathData="M841.14,171.7A66.01,66.01 0,0 1,907.15 237.71v472.32A66.01,66.01 0,0 1,841.14 776.05L629.58,776.05l-84.11,98.01a47.73,47.73 0,0 1,-67.29 5.3l-4.94,-5.12 -85.21,-98.19L182.86,776.05a66.01,66.01 0,0 1,-66.01 -66.01L116.85,237.71A66.01,66.01 0,0 1,182.86 171.7zM329.14,420.57a54.86,54.86 0,1 0,54.86 54.86,54.86 54.86,0 0,0 -54.86,-54.86zM512,420.57a54.86,54.86 0,1 0,54.86 54.86,54.86 54.86,0 0,0 -54.86,-54.86zM694.86,420.57a54.86,54.86 0,1 0,54.86 54.86,54.86 54.86,0 0,0 -54.86,-54.86z" />
</vector>


================================================
FILE: example/android/app/src/main/res/layout/activity_flutter2native.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">


    <Button
        android:id="@+id/btn"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="带参数返回"
        tools:ignore="HardcodedText" />
</LinearLayout>

================================================
FILE: example/android/app/src/main/res/layout/activity_fragment.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />


    <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/tab1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="true"
            android:drawableTop="@drawable/tab_home"
            android:gravity="center" />

        <RadioButton
            android:id="@+id/tab2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/tab_house"
            android:gravity="center" />

        <RadioButton
            android:id="@+id/tab3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/tab_file"
            android:gravity="center" />

        <RadioButton
            android:id="@+id/tab4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/tab_msg"
            android:gravity="center" />


    </RadioGroup>

</LinearLayout>

================================================
FILE: example/android/app/src/main/res/layout/activity_main.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:padding="24dp"/>

================================================
FILE: example/android/app/src/main/res/layout/activity_native2flutter.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:gravity="center"
    android:orientation="vertical">

    <TextView
        android:id="@+id/textView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="16.0dp"
        android:paddingTop="16dp"
        android:paddingEnd="16dp"
        android:paddingBottom="16dp"
        android:text="@string/native2flutter_tip" />

    <TextView
        android:id="@+id/result"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:paddingStart="16dp"
        tools:ignore="RtlSymmetry" />

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="@string/open_flutter" />

    <Button
        android:id="@+id/transparentButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Open Transparent Flutter Page" />
</LinearLayout>

================================================
FILE: example/android/app/src/main/res/layout/activity_tab_container.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <FrameLayout
        android:id="@+id/fragment_container"
        android:layout_width="match_parent"
        android:layout_height="0dp"
        android:layout_weight="1" />


    <RadioGroup
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="horizontal">

        <RadioButton
            android:id="@+id/tab1"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:checked="true"
            android:drawableTop="@drawable/tab_home"
            android:gravity="center" />

        <RadioButton
            android:id="@+id/tab2"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/tab_house"
            android:gravity="center" />

        <RadioButton
            android:id="@+id/tab3"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/tab_file"
            android:gravity="center" />

        <RadioButton
            android:id="@+id/tab4"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:button="@null"
            android:drawableTop="@drawable/tab_msg"
            android:gravity="center" />


    </RadioGroup>

</LinearLayout>

================================================
FILE: example/android/app/src/main/res/layout/dialog_notification.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/contentView"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_margin="24dp"
    android:background="@color/white"
    android:minHeight="200dp">

    <TextView
        android:id="@+id/titleTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="@color/colorPrimary"
        android:gravity="center"
        android:padding="12dp"
        android:textColor="@color/white"
        android:textSize="16sp"
        android:textStyle="bold"
        tools:text="Title" />

    <TextView
        android:id="@+id/msgTxt"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_centerInParent="true"
        android:gravity="center"
        android:textColor="@color/dark"
        tools:text="Notification form Flutter" />

</RelativeLayout>

================================================
FILE: example/android/app/src/main/res/layout/frag_test.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">


    <TextView
        android:id="@+id/fragText"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:gravity="center"
        android:text="native fragment"
        tools:ignore="HardcodedText" />


</LinearLayout>

================================================
FILE: example/android/app/src/main/res/navigation/nav_graph.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/nav_graph"
    app:startDestination="@id/FirstFragment">

    <fragment
        android:id="@+id/FirstFragment"
        android:name="com.yuxiaor.flutter.g_faraday_example.FirstFragment"
        android:label="@string/first_fragment_label"
        tools:layout="@layout/fragment_first">

        <action
            android:id="@+id/action_FirstFragment_to_SecondFragment"
            app:destination="@id/SecondFragment" />
    </fragment>
    <fragment
        android:id="@+id/SecondFragment"
        android:name="com.yuxiaor.flutter.g_faraday_example.SecondFragment"
        android:label="@string/second_fragment_label"
        tools:layout="@layout/fragment_second">

        <action
            android:id="@+id/action_SecondFragment_to_FirstFragment"
            app:destination="@id/FirstFragment" />
    </fragment>
</navigation>

================================================
FILE: example/android/app/src/main/res/values/colors.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#6200EE</color>
    <color name="colorPrimaryDark">#3700B3</color>
    <color name="colorAccent">#D6E1E0</color>
    <color name="light">#CCCCCC</color>
    <color name="dark">#333333</color>
    <color name="white">#FFFFFF</color>
    <color name="transparent_background">#50000000</color>
</resources>

================================================
FILE: example/android/app/src/main/res/values/strings.xml
================================================
<resources>
    <string name="back_button_title">带参数返回</string>
    <string name="native2flutter_tip">从原生打开flutter只需要使用 FaradayActivity.builder 构造相应的Intent,然后startActivityForResult\n\n 注意\n打开的路由必须在flutter入口处注册</string>
    <string name="open_flutter">Open Flutter</string>
    <string name="title_activity_transparent_background">TransparentBackgroundActivity</string>
    <!-- Strings used for fragments for navigation -->
    <string name="first_fragment_label">First Fragment</string>
    <string name="second_fragment_label">Second Fragment</string>
    <string name="next">Next</string>
    <string name="previous">Previous</string>

    <string name="hello_first_fragment">Hello first fragment</string>
    <string name="hello_second_fragment">Hello second fragment. Arg: %1$s</string>
</resources>

================================================
FILE: example/android/app/src/main/res/values/styles.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="AppTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowAnimationStyle">@style/WindowAnimTheme</item>
    </style>

    <style name="SplashTheme"  parent="@android:style/Theme.Black.NoTitleBar">
        <item name="android:windowBackground">@drawable/launch_background</item>
    </style>

    <style name="TransparentActivityTheme">
        <item name="android:windowBackground">@color/transparent_background</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowAnimationStyle">@android:style/Animation.Translucent</item>
    </style>

    <style name="WindowAnimTheme">
        <item name="android:activityOpenEnterAnimation">@anim/in_from_right</item>
        <item name="android:activityOpenExitAnimation">@anim/out_from_left</item>
        <item name="android:activityCloseEnterAnimation">@anim/in_from_left</item>
        <item name="android:activityCloseExitAnimation">@anim/out_from_right</item>
    </style>

    <style name="FragTheme" parent="Theme.AppCompat.Light.NoActionBar">
        <!-- Customize your theme here. -->
        <item name="colorPrimary">@color/colorPrimary</item>
        <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
        <item name="colorAccent">@color/colorAccent</item>
        <item name="android:windowAnimationStyle">@style/WindowAnimTheme</item>
    </style>

    <style name="DialogTheme" parent="@android:style/Theme.Dialog">
        <item name="android:windowFrame">@null</item>
        <item name="android:windowIsFloating">true</item>
        <item name="android:windowIsTranslucent">true</item>
        <item name="android:windowNoTitle">true</item>
        <item name="android:background">@android:color/transparent</item>
        <item name="android:windowBackground">@android:color/transparent</item>
        <item name="android:backgroundDimEnabled">true</item>
        <item name="android:backgroundDimAmount">0.5</item>
        <item name="android:windowSoftInputMode">adjustResize</item>
    </style>

</resources>


================================================
FILE: example/android/app/src/main/res/values-v31/styles.xml
================================================
<?xml version="1.0" encoding="utf-8"?>
<resources>

    <style name="SplashTheme" parent="@android:style/Theme.Black.NoTitleBar">
        <item name="android:windowSplashScreenBackground">@color/colorPrimary</item>
        <item name="android:windowSplashScreenAnimatedIcon">@drawable/launch_background</item>
    </style>
</resources>

================================================
FILE: example/android/app/src/profile/AndroidManifest.xml
================================================
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yuxiaor.flutter.g_faraday_example">
    <!-- Flutter needs it to communicate with the running application
         to allow setting breakpoints, to provide hot reload, etc.
    -->
    <uses-permission android:name="android.permission.INTERNET"/>
</manifest>


================================================
FILE: example/android/build.gradle
================================================
buildscript {
    ext.kotlin_version = '1.6.21'
    repositories {
        maven { url 'https://maven.aliyun.com/repository/google/'}
        maven { url 'https://maven.aliyun.com/repository/jcenter/'}
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:4.1.1'
        classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
    }
}

allprojects {
    repositories {
        maven { url 'https://maven.aliyun.com/repository/google/'}
        maven { url 'https://maven.aliyun.com/repository/jcenter/'}
    }
}

rootProject.buildDir = '../build'
subprojects {
    project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
    project.evaluationDependsOn(':app')
}

tasks.register("clean", Delete) {
    delete rootProject.buildDir
}


================================================
FILE: example/android/gradle/wrapper/gradle-wrapper.properties
================================================
#Wed Sep 02 15:37:58 CST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3-all.zip


================================================
FILE: example/android/gradle.properties
================================================
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true


================================================
FILE: example/android/settings.gradle
================================================
include ':app'

def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()

assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }

def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"


================================================
FILE: example/ios/.gitignore
================================================
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json

# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3


================================================
FILE: example/ios/Flutter/AppFrameworkInfo.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>CFBundleDevelopmentRegion</key>
  <string>$(DEVELOPMENT_LANGUAGE)</string>
  <key>CFBundleExecutable</key>
  <string>App</string>
  <key>CFBundleIdentifier</key>
  <string>io.flutter.flutter.app</string>
  <key>CFBundleInfoDictionaryVersion</key>
  <string>6.0</string>
  <key>CFBundleName</key>
  <string>App</string>
  <key>CFBundlePackageType</key>
  <string>FMWK</string>
  <key>CFBundleShortVersionString</key>
  <string>1.0</string>
  <key>CFBundleSignature</key>
  <string>????</string>
  <key>CFBundleVersion</key>
  <string>1.0</string>
  <key>MinimumOSVersion</key>
  <string>9.0</string>
</dict>
</plist>


================================================
FILE: example/ios/Flutter/Debug.xcconfig
================================================
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"


================================================
FILE: example/ios/Flutter/Release.xcconfig
================================================
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"


================================================
FILE: example/ios/Podfile
================================================
# Uncomment this line to define a global platform for your project
 platform :ios, '12.0'

# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'

project 'Runner', {
  'Debug' => :debug,
  'Profile' => :release,
  'Release' => :release,
}

def flutter_root
  generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
  unless File.exist?(generated_xcode_build_settings_path)
    raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
  end

  File.foreach(generated_xcode_build_settings_path) do |line|
    matches = line.match(/FLUTTER_ROOT\=(.*)/)
    return matches[1].strip if matches
  end
  raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end

require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)

flutter_ios_podfile_setup

target 'Runner' do
  use_frameworks!
  use_modular_headers!
  
  flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end

post_install do |installer|
  installer.pods_project.targets.each do |target|
    flutter_additional_ios_build_settings(target)
  end
end


================================================
FILE: example/ios/Runner/AppDelegate.swift
================================================
import UIKit
import g_faraday

@UIApplicationMain
@objc class AppDelegate: UIResponder, UIApplicationDelegate {
    
    var window: UIWindow?
    
    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        // 自动处理导航栏
        UINavigationController.fa.automaticallyHandleNavigationBarHidden()
        // 自动回调空值到flutter侧,避免flutter侧 await 一直不返回
        UIViewController.fa.automaticallyCallbackNullToFlutter()
        
        Faraday.default.startFlutterEngine(navigatorDelegate: self, httpProvider: nil, commonHandler: nil, automaticallyRegisterPlugins: true)
        
        return true
    }
}

extension AppDelegate: FaradayNavigationDelegate {
    
    func push(_ name: String, arguments: Any?, options: Options, callback token: CallbackToken) {
        var vc: UIViewController!
        
        switch name {
            case "flutter2native":
                vc = Flutter2NativeViewController()
            case "native2flutter":
                vc = Native2FlutterViewController()
            case "tabContainer":
                vc = UIStoryboard(name: "TabContainer", bundle: nil).instantiateInitialViewController()
            case "navigationBar":
                vc = UIStoryboard(name: "Other", bundle: nil).instantiateInitialViewController()
            default:
                vc = options.isFlutterRoute ? FaradayFlutterViewController(name, arguments: arguments) : Flutter2NativeViewController()
        }
        
        let topMost = UIViewController.fa.topMost
        if (options.present) {
            topMost?.present(vc, animated: options.animated, completion: nil)
        } else {
            topMost?.navigationController?.pushViewController(vc, animated: options.animated)
        }
        
        // 非常重要
        // 如果此处不调用 `enableCallback` 那么flutter侧`await Navigator`则永远不会返回
        vc.fa.enableCallback(with: token)
    }   

}


================================================
FILE: example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "Icon-40.png",
      "idiom" : "iphone",
      "scale" : "2x",
      "size" : "20x20"
    },
    {
      "filename" : "Icon-60.png",
      "idiom" : "iphone",
      "scale" : "3x",
      "size" : "20x20"
    },
    {
      "filename" : "Icon-29.png",
      "idiom" : "iphone",
      "scale" : "1x",
      "size" : "29x29"
    },
    {
      "filename" : "Icon-58.png",
      "idiom" : "iphone",
      "scale" : "2x",
      "size" : "29x29"
    },
    {
      "filename" : "Icon-87.png",
      "idiom" : "iphone",
      "scale" : "3x",
      "size" : "29x29"
    },
    {
      "filename" : "Icon-80.png",
      "idiom" : "iphone",
      "scale" : "2x",
      "size" : "40x40"
    },
    {
      "filename" : "Icon-120.png",
      "idiom" : "iphone",
      "scale" : "3x",
      "size" : "40x40"
    },
    {
      "filename" : "Icon-121.png",
      "idiom" : "iphone",
      "scale" : "2x",
      "size" : "60x60"
    },
    {
      "filename" : "Icon-180.png",
      "idiom" : "iphone",
      "scale" : "3x",
      "size" : "60x60"
    },
    {
      "filename" : "Icon-20.png",
      "idiom" : "ipad",
      "scale" : "1x",
      "size" : "20x20"
    },
    {
      "filename" : "Icon-41.png",
      "idiom" : "ipad",
      "scale" : "2x",
      "size" : "20x20"
    },
    {
      "filename" : "Icon-30.png",
      "idiom" : "ipad",
      "scale" : "1x",
      "size" : "29x29"
    },
    {
      "filename" : "Icon-59.png",
      "idiom" : "ipad",
      "scale" : "2x",
      "size" : "29x29"
    },
    {
      "filename" : "Icon-42.png",
      "idiom" : "ipad",
      "scale" : "1x",
      "size" : "40x40"
    },
    {
      "filename" : "Icon-81.png",
      "idiom" : "ipad",
      "scale" : "2x",
      "size" : "40x40"
    },
    {
      "filename" : "Icon-76.png",
      "idiom" : "ipad",
      "scale" : "1x",
      "size" : "76x76"
    },
    {
      "filename" : "Icon-152.png",
      "idiom" : "ipad",
      "scale" : "2x",
      "size" : "76x76"
    },
    {
      "filename" : "Icon-167.png",
      "idiom" : "ipad",
      "scale" : "2x",
      "size" : "83.5x83.5"
    },
    {
      "filename" : "Icon-1024.png",
      "idiom" : "ios-marketing",
      "scale" : "1x",
      "size" : "1024x1024"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: example/ios/Runner/Assets.xcassets/Contents.json
================================================
{
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "Icon-20.png",
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "Icon-40.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "filename" : "Icon-60.png",
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: example/ios/Runner/Assets.xcassets/logo.imageset/Contents.json
================================================
{
  "images" : [
    {
      "filename" : "Icon-60.png",
      "idiom" : "universal",
      "scale" : "1x"
    },
    {
      "filename" : "Icon-120.png",
      "idiom" : "universal",
      "scale" : "2x"
    },
    {
      "filename" : "Icon-180.png",
      "idiom" : "universal",
      "scale" : "3x"
    }
  ],
  "info" : {
    "author" : "xcode",
    "version" : 1
  }
}


================================================
FILE: example/ios/Runner/Base.lproj/LaunchScreen.storyboard
================================================
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="12121" systemVersion="16G29" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" colorMatched="YES" initialViewController="01J-lp-oVM">
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="12089"/>
    </dependencies>
    <scenes>
        <!--View Controller-->
        <scene sceneID="EHf-IW-A2E">
            <objects>
                <viewController id="01J-lp-oVM" sceneMemberID="viewController">
                    <layoutGuides>
                        <viewControllerLayoutGuide type="top" id="Ydg-fD-yQy"/>
                        <viewControllerLayoutGuide type="bottom" id="xbc-2k-c8Z"/>
                    </layoutGuides>
                    <view key="view" contentMode="scaleToFill" id="Ze5-6b-2t3">
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <imageView opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" image="LaunchImage" translatesAutoresizingMaskIntoConstraints="NO" id="YRO-k0-Ey4">
                            </imageView>
                        </subviews>
                        <color key="backgroundColor" red="1" green="1" blue="1" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
                        <constraints>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerX" secondItem="Ze5-6b-2t3" secondAttribute="centerX" id="1a2-6s-vTC"/>
                            <constraint firstItem="YRO-k0-Ey4" firstAttribute="centerY" secondItem="Ze5-6b-2t3" secondAttribute="centerY" id="4X2-HB-R7a"/>
                        </constraints>
                    </view>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="iYj-Kq-Ea1" userLabel="First Responder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="53" y="375"/>
        </scene>
    </scenes>
    <resources>
        <image name="LaunchImage" width="168" height="185"/>
    </resources>
</document>


================================================
FILE: example/ios/Runner/Base.lproj/Main.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" colorMatched="YES" initialViewController="ABh-kg-K8H">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Mainavigation View Controller-->
        <scene sceneID="4B2-ma-vOf">
            <objects>
                <navigationController id="ABh-kg-K8H" customClass="MainavigationViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="cPZ-PW-CcB">
                        <rect key="frame" x="0.0" y="44" width="414" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="uWf-v2-u4P" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-1823" y="114"/>
        </scene>
    </scenes>
</document>


================================================
FILE: example/ios/Runner/Faraday/FaradayCommon.swift
================================================
//import Foundation
//
//  Created by faraday_cli on 2020-09-24 09:48:07.370618.
//
//    ___                   _
//   / __\_ _ _ __ __ _  __| | __ _ _   _
//  / _\/ _` | '__/ _` |/ _` |/ _` | | | |
// / / | (_| | | | (_| | (_| | (_| | |_| |
// \/   \__,_|_|  \__,_|\__,_|\__,_|\__, |
//                                  |___/
//
// GENERATED CODE BY FARADAY CLI - DO NOT MODIFY BY HAND
//
//
//protocol FaradayCommonHandler {
//
//    // ---> protocol
//
//    func handle(_ name: String, _ arguments: Any?, _ completion: @escaping (_ result: Any?) -> Void) -> Void
//}
//
//extension FaradayCommonHandler {
//
//    func handle(_ name: String, _ arguments: Any?, _ completion: @escaping (_ result: Any?) -> Void) -> Void {
//        if (!defaultHandle(name,arguments,completion)) {
//            debugPrint("Faraday->Warning \(name) not handle. argument: \(arguments ?? "")")
//        }
//    }
//
//    func defaultHandle(_ name: String, _ arguments: Any?, _ completion: @escaping (_ result: Any?) -> Void) -> Bool {
////        let args = arguments as? Dictionary<String, Any>
//        // ---> impl
//        return false
//    }
//
//}
//


================================================
FILE: example/ios/Runner/Faraday/FaradayNet.swift
================================================
import Foundation

//  Created by faraday_cli on 2020-09-24 09:48:07.370618.
//
//    ___                   _
//   / __\_ _ _ __ __ _  __| | __ _ _   _
//  / _\/ _` | '__/ _` |/ _` |/ _` | | | |
// / / | (_| | | | (_| | (_| | (_| | |_| |
// \/   \__,_|_|  \__,_|\__,_|\__,_|\__, |
//                                  |___/
//
// GENERATED CODE BY FARADAY CLI - DO NOT MODIFY BY HAND


//func flutterNetBridge(_ name: String, _ arguments: Any?, _ completion: @escaping (_ result: Any?) -> Void) -> Void {
//    
//    let args = arguments as? [String: Any]
//    
//    let method = name.uppercased(); // REQUEST/GET/PUT/POST/DELETE
//    let query = args?["query"] as? [String: Any]
//    let body = args?["body"] as? [String: Any]
//    let additions = args?["additions"]
//  
//    completion(FlutterMethodNotImplemented);
//}


================================================
FILE: example/ios/Runner/Faraday/FaradayRoute.swift
================================================
//import Foundation
//import g_faraday

//  Created by faraday_cli on 2020-09-24 09:48:07.370618.
//
//    ___                   _
//   / __\_ _ _ __ __ _  __| | __ _ _   _
//  / _\/ _` | '__/ _` |/ _` |/ _` | | | |
// / / | (_| | | | (_| | (_| | (_| | |_| |
// \/   \__,_|_|  \__,_|\__,_|\__,_|\__, |
//                                  |___/
//
// GENERATED CODE BY FARADAY CLI - DO NOT MODIFY BY HAND


//enum FaradayRoute {
//    // ---> enum
//
//    var page: (name: String, arguments: Any?) {
//        switch self {
//            // ---> enum_page
//        }
//    }
//}
//
//extension Faraday {
//    
//    static func createFlutterViewController(route: FaradayRoute, callback:  @escaping (Any?) -> () = { r in debugPrint("result don't be used (String(describing: r))")}) -> FaradayFlutterViewController {
//        let page = route.page
//        let vc = FaradayFlutterViewController(page.name, arguments: page.arguments, callback: callback)
//        return vc
//    }
//}



================================================
FILE: example/ios/Runner/GeneratedPluginRegistrant.h
================================================
//
//  Generated file. Do not edit.
//

// clang-format off

#ifndef GeneratedPluginRegistrant_h
#define GeneratedPluginRegistrant_h

#import <Flutter/Flutter.h>

NS_ASSUME_NONNULL_BEGIN

@interface GeneratedPluginRegistrant : NSObject
+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry;
@end

NS_ASSUME_NONNULL_END
#endif /* GeneratedPluginRegistrant_h */


================================================
FILE: example/ios/Runner/GeneratedPluginRegistrant.m
================================================
//
//  Generated file. Do not edit.
//

// clang-format off

#import "GeneratedPluginRegistrant.h"

#if __has_include(<g_faraday/GFaradayPlugin.h>)
#import <g_faraday/GFaradayPlugin.h>
#else
@import g_faraday;
#endif

@implementation GeneratedPluginRegistrant

+ (void)registerWithRegistry:(NSObject<FlutterPluginRegistry>*)registry {
  [GFaradayPlugin registerWithRegistrar:[registry registrarForPlugin:@"GFaradayPlugin"]];
}

@end


================================================
FILE: example/ios/Runner/Info.plist
================================================
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>CFBundleDevelopmentRegion</key>
	<string>$(DEVELOPMENT_LANGUAGE)</string>
	<key>CFBundleDisplayName</key>
	<string>Faraday</string>
	<key>CFBundleExecutable</key>
	<string>$(EXECUTABLE_NAME)</string>
	<key>CFBundleIdentifier</key>
	<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
	<key>CFBundleInfoDictionaryVersion</key>
	<string>6.0</string>
	<key>CFBundleName</key>
	<string>g_faraday_example</string>
	<key>CFBundlePackageType</key>
	<string>APPL</string>
	<key>CFBundleShortVersionString</key>
	<string>1.0.0</string>
	<key>CFBundleSignature</key>
	<string>????</string>
	<key>CFBundleVersion</key>
	<string>100</string>
	<key>LSRequiresIPhoneOS</key>
	<true/>
	<key>UILaunchStoryboardName</key>
	<string>LaunchScreen</string>
	<key>UIMainStoryboardFile</key>
	<string>Main</string>
	<key>UISupportedInterfaceOrientations</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UISupportedInterfaceOrientations~ipad</key>
	<array>
		<string>UIInterfaceOrientationPortrait</string>
		<string>UIInterfaceOrientationPortraitUpsideDown</string>
		<string>UIInterfaceOrientationLandscapeLeft</string>
		<string>UIInterfaceOrientationLandscapeRight</string>
	</array>
	<key>UIViewControllerBasedStatusBarAppearance</key>
	<false/>
	<key>CADisableMinimumFrameDurationOnPhone</key>
	<true/>
</dict>
</plist>


================================================
FILE: example/ios/Runner/Runner-Bridging-Header.h
================================================
#import "GeneratedPluginRegistrant.h"


================================================
FILE: example/ios/Runner/ViewControllers/BaseViewController.swift
================================================
//
//  BaseViewController.swift
//  Runner
//
//  Created by gix on 2020/12/8.
//

import UIKit

class BaseViewController: UIViewController {
  
    deinit {
        debugPrint("\(self) deinit")
    }

}


================================================
FILE: example/ios/Runner/ViewControllers/Basic/Flutter2NativeViewController.swift
================================================
//
//  Flutter2NativeViewController.swift
//  Runner
//
//  Created by gix on 2020/11/26.
//

import UIKit
import g_faraday

class Flutter2NativeViewController: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "iOS Native (F2N)"
    }
    
    @IBAction func touchPop(sender: UIButton) {
        
        let r = ["date": Date().description]
        
        if (fa.isModal) {
            fa.dismiss(withResult: r, animated: true)
        } else {
            navigationController?.fa.popViewController(withResult: r, animated: true)
        }
    }
}


================================================
FILE: example/ios/Runner/ViewControllers/Basic/Flutter2NativeViewController.xib
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="Flutter2NativeViewController" customModule="Runner" customModuleProvider="target">
            <connections>
                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
            </connections>
        </placeholder>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
            <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
                <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="S9B-LS-8Vs">
                    <rect key="frame" x="168.5" y="433" width="77" height="30"/>
                    <state key="normal" title="带参数返回"/>
                    <connections>
                        <action selector="touchPopWithSender:" destination="-1" eventType="touchUpInside" id="8ln-H1-MWU"/>
                    </connections>
                </button>
            </subviews>
            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
            <constraints>
                <constraint firstItem="S9B-LS-8Vs" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="50v-r3-Jkf"/>
                <constraint firstItem="S9B-LS-8Vs" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="feU-cE-Ezt"/>
            </constraints>
            <point key="canvasLocation" x="139" y="151"/>
        </view>
    </objects>
    <resources>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>


================================================
FILE: example/ios/Runner/ViewControllers/Basic/Native2FlutterViewController.swift
================================================
//
//  Native2FlutterViewController.swift
//  Runner
//
//  Created by gix on 2020/11/26.
//

import UIKit
import g_faraday

class Native2FlutterViewController: BaseViewController {

    
    @IBOutlet var label: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Do any additional setup after loading the view.
    }

    @IBAction func onTap(sender: UIButton) {
        
        let vc = FaradayFlutterViewController("native2flutter") { [weak self] r in
            self?.label.text = r.debugDescription
        }
        
        navigationController?.pushViewController(vc, animated: true)
    }

    @IBAction func onTap1(sedner: UIButton) {
        
        let vc = FaradayFlutterViewController("transparent_flutter", backgroundClear: true)
        
        navigationController?.present(vc, animated: false, completion: nil)
    }
}


================================================
FILE: example/ios/Runner/ViewControllers/Basic/Native2FlutterViewController.xib
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <objects>
        <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="Native2FlutterViewController" customModule="Runner" customModuleProvider="target">
            <connections>
                <outlet property="label" destination="qdK-Hv-HY3" id="CHd-3r-QBL"/>
                <outlet property="view" destination="i5M-Pr-FkT" id="sfx-zR-JGt"/>
            </connections>
        </placeholder>
        <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
        <view clearsContextBeforeDrawing="NO" contentMode="scaleToFill" id="i5M-Pr-FkT">
            <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
            <subviews>
                <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" translatesAutoresizingMaskIntoConstraints="NO" id="OtI-19-LQR">
                    <rect key="frame" x="16" y="368" width="382" height="160.5"/>
                    <subviews>
                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" lineBreakMode="tailTruncation" numberOfLines="0" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="fG4-Qw-ED8">
                            <rect key="frame" x="0.0" y="0.0" width="382" height="50.5"/>
                            <string key="text">使用Route构造一个FaradayViewController 然后push或者present即可
route需要在flutter入口处注册</string>
                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
                            <nil key="textColor"/>
                            <nil key="highlightedColor"/>
                        </label>
                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="4KC-gW-rLS">
                            <rect key="frame" x="0.0" y="50.5" width="382" height="30"/>
                            <state key="normal" title="Open Flutter"/>
                            <connections>
                                <action selector="onTapWithSender:" destination="-1" eventType="touchUpInside" id="vg5-ge-xR4"/>
                            </connections>
                        </button>
                        <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="qdK-Hv-HY3">
                            <rect key="frame" x="0.0" y="80.5" width="382" height="50"/>
                            <fontDescription key="fontDescription" type="system" pointSize="14"/>
                            <color key="textColor" systemColor="systemRedColor"/>
                            <nil key="highlightedColor"/>
                        </label>
                        <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="DZc-xX-WNq">
                            <rect key="frame" x="0.0" y="130.5" width="382" height="30"/>
                            <state key="normal" title="Open Transparent Flutter Page"/>
                            <connections>
                                <action selector="onTap1WithSedner:" destination="-1" eventType="touchUpInside" id="dH6-cl-ft5"/>
                            </connections>
                        </button>
                    </subviews>
                </stackView>
            </subviews>
            <viewLayoutGuide key="safeArea" id="fnl-2z-Ty3"/>
            <color key="backgroundColor" systemColor="systemBackgroundColor"/>
            <constraints>
                <constraint firstItem="OtI-19-LQR" firstAttribute="centerX" secondItem="i5M-Pr-FkT" secondAttribute="centerX" id="01N-GL-RRo"/>
                <constraint firstAttribute="trailing" secondItem="OtI-19-LQR" secondAttribute="trailing" constant="16" id="E4J-P0-vRq"/>
                <constraint firstItem="OtI-19-LQR" firstAttribute="centerY" secondItem="i5M-Pr-FkT" secondAttribute="centerY" id="Qoj-hy-0W4"/>
                <constraint firstItem="OtI-19-LQR" firstAttribute="leading" secondItem="i5M-Pr-FkT" secondAttribute="leading" constant="16" id="Uy0-aV-FiE"/>
            </constraints>
            <point key="canvasLocation" x="139" y="151"/>
        </view>
    </objects>
    <resources>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
        <systemColor name="systemRedColor">
            <color red="1" green="0.23137254901960785" blue="0.18823529411764706" alpha="1" colorSpace="custom" customColorSpace="sRGB"/>
        </systemColor>
    </resources>
</document>


================================================
FILE: example/ios/Runner/ViewControllers/Basic/TabContainer/Tab1ViewController.swift
================================================
//
//  Tab1ViewController.swift
//  Runner
//
//  Created by gix on 2020/11/27.
//

import UIKit
import g_faraday

class Tab1ViewController: BaseViewController, FaradayNavigationBarHiddenProtocol {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationController?.setNavigationBarHidden(true, animated: true)

        let vc = FaradayFlutterViewController("tab1")
        
        vc.willMove(toParent: self)
        addChild(vc)
        view.addSubview(vc.view)
        vc.didMove(toParent: self)
        
        vc.view.frame = view.frame;
        vc.view.autoresizingMask = [.flexibleWidth, .flexibleWidth]
    }
    
}


================================================
FILE: example/ios/Runner/ViewControllers/Basic/TabContainer/Tab2ViewController.swift
================================================
//
//  Tab2ViewController.swift
//  Runner
//
//  Created by gix on 2020/11/27.
//

import UIKit
import g_faraday

class Tab2ViewController: BaseViewController, FaradayNavigationBarHiddenProtocol {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationController?.setNavigationBarHidden(true, animated: true)
        
        let vc = FaradayFlutterViewController("home")
        
        vc.willMove(toParent: self)
        addChild(vc)
        view.addSubview(vc.view)
        vc.didMove(toParent: self)
        
        vc.view.frame = view.frame;
        vc.view.autoresizingMask = [.flexibleWidth, .flexibleWidth]
    }
}


================================================
FILE: example/ios/Runner/ViewControllers/Basic/TabContainer/TabContainer.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="Eqs-I6-01B">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Tab1-->
        <scene sceneID="Dko-vg-2mt">
            <objects>
                <viewController id="F2W-W8-1fC" customClass="Tab1ViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="js5-Dp-eFw">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <viewLayoutGuide key="safeArea" id="lc9-5Y-y3c"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                    </view>
                    <tabBarItem key="tabBarItem" title="Tab1" id="Qfw-q5-ik7"/>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="00L-90-5dy" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="341" y="-388"/>
        </scene>
        <!--Item-->
        <scene sceneID="oMR-Mc-lkX">
            <objects>
                <navigationController id="AEI-hP-wP8" sceneMemberID="viewController">
                    <tabBarItem key="tabBarItem" title="Item" id="aEr-Rb-mhl"/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="Tp7-jF-xEO">
                        <rect key="frame" x="0.0" y="44" width="414" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <connections>
                        <segue destination="V2p-fx-wjC" kind="relationship" relationship="rootViewController" id="Jen-0Q-9cn"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="r0j-Rm-ZuI" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-520" y="1246"/>
        </scene>
        <!--Tab2-->
        <scene sceneID="G9m-ZO-etY">
            <objects>
                <viewController id="AcI-HD-kIa" customClass="Tab2ViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="75N-dT-Kjj">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <viewLayoutGuide key="safeArea" id="cJ6-4C-UJX"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                    </view>
                    <tabBarItem key="tabBarItem" title="Tab2" id="kcV-C8-foV"/>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="4bC-QN-eab" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="342" y="306"/>
        </scene>
        <!--NativeContainer-->
        <scene sceneID="5V5-1V-6ud">
            <objects>
                <tableViewController title="NativeContainer" id="V2p-fx-wjC" sceneMemberID="viewController">
                    <tableView key="view" clipsSubviews="YES" contentMode="scaleToFill" alwaysBounceVertical="YES" dataMode="static" style="plain" separatorStyle="default" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" id="hKb-mn-U7C">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <sections>
                            <tableViewSection id="ia2-4l-ev2">
                                <cells>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="PMj-mT-jKD" style="IBUITableViewCellStyleDefault" id="aJj-p9-Lf6">
                                        <rect key="frame" x="0.0" y="28" width="414" height="43.5"/>
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="aJj-p9-Lf6" id="iT4-Vy-P5O">
                                            <rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="This" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="PMj-mT-jKD">
                                                    <rect key="frame" x="20" y="0.0" width="374" height="43.5"/>
                                                    <autoresizingMask key="autoresizingMask"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                        </tableViewCellContentView>
                                    </tableViewCell>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="Jhi-li-aKG" style="IBUITableViewCellStyleDefault" id="lQv-qQ-FlI">
                                        <rect key="frame" x="0.0" y="71.5" width="414" height="43.5"/>
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="lQv-qQ-FlI" id="gQl-M4-OGB">
                                            <rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="is" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="Jhi-li-aKG">
                                                    <rect key="frame" x="20" y="0.0" width="374" height="43.5"/>
                                                    <autoresizingMask key="autoresizingMask"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                        </tableViewCellContentView>
                                    </tableViewCell>
                                    <tableViewCell clipsSubviews="YES" contentMode="scaleToFill" preservesSuperviewLayoutMargins="YES" selectionStyle="default" indentationWidth="10" textLabel="dgt-nt-dsU" style="IBUITableViewCellStyleDefault" id="fot-4O-9K5">
                                        <rect key="frame" x="0.0" y="115" width="414" height="43.5"/>
                                        <autoresizingMask key="autoresizingMask"/>
                                        <tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" preservesSuperviewLayoutMargins="YES" insetsLayoutMarginsFromSafeArea="NO" tableViewCell="fot-4O-9K5" id="eB1-oe-CxG">
                                            <rect key="frame" x="0.0" y="0.0" width="414" height="43.5"/>
                                            <autoresizingMask key="autoresizingMask"/>
                                            <subviews>
                                                <label opaque="NO" multipleTouchEnabled="YES" contentMode="left" insetsLayoutMarginsFromSafeArea="NO" text="Native ViewController" textAlignment="natural" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="dgt-nt-dsU">
                                                    <rect key="frame" x="20" y="0.0" width="374" height="43.5"/>
                                                    <autoresizingMask key="autoresizingMask"/>
                                                    <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                                    <nil key="textColor"/>
                                                    <nil key="highlightedColor"/>
                                                </label>
                                            </subviews>
                                        </tableViewCellContentView>
                                    </tableViewCell>
                                </cells>
                            </tableViewSection>
                        </sections>
                        <connections>
                            <outlet property="dataSource" destination="V2p-fx-wjC" id="aRR-ap-zCf"/>
                            <outlet property="delegate" destination="V2p-fx-wjC" id="YIC-Wr-n7V"/>
                        </connections>
                    </tableView>
                    <navigationItem key="navigationItem" title="Native Container" id="hD3-nS-usF"/>
                </tableViewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="cRq-aI-ebM" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="168" y="1246"/>
        </scene>
        <!--Tab Bar Controller-->
        <scene sceneID="LhB-01-bnO">
            <objects>
                <tabBarController id="Eqs-I6-01B" sceneMemberID="viewController">
                    <tabBar key="tabBar" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" id="tPB-bz-8M3">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="49"/>
                        <autoresizingMask key="autoresizingMask"/>
                        <color key="backgroundColor" white="0.0" alpha="0.0" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
                    </tabBar>
                    <connections>
                        <segue destination="F2W-W8-1fC" kind="relationship" relationship="viewControllers" id="y6M-nH-fCQ"/>
                        <segue destination="AEI-hP-wP8" kind="relationship" relationship="viewControllers" id="wGX-co-KaJ"/>
                        <segue destination="AcI-HD-kIa" kind="relationship" relationship="viewControllers" id="AMZ-eN-jAR"/>
                        <segue destination="a1s-VC-uIo" kind="relationship" relationship="viewControllers" id="ehz-JC-CUO"/>
                    </connections>
                </tabBarController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="Avq-kx-wAQ" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-520" y="225"/>
        </scene>
        <!--View Controller-->
        <scene sceneID="lw1-x6-yGo">
            <objects>
                <viewController id="98n-h0-2sL" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="5Br-hb-83L">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <stackView opaque="NO" contentMode="scaleToFill" axis="vertical" distribution="fillEqually" translatesAutoresizingMaskIntoConstraints="NO" id="KT3-Fk-a2q">
                                <rect key="frame" x="0.0" y="88" width="414" height="725"/>
                                <subviews>
                                    <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="jsD-UQ-b3a">
                                        <rect key="frame" x="0.0" y="0.0" width="414" height="362.5"/>
                                        <connections>
                                            <segue destination="keq-y0-8uV" kind="embed" id="8Cf-YB-ObU"/>
                                        </connections>
                                    </containerView>
                                    <containerView opaque="NO" contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="iM4-Cg-TkV">
                                        <rect key="frame" x="0.0" y="362.5" width="414" height="362.5"/>
                                        <connections>
                                            <segue destination="wd2-dH-UL5" kind="embed" id="Knx-SY-gVe"/>
                                        </connections>
                                    </containerView>
                                </subviews>
                            </stackView>
                        </subviews>
                        <viewLayoutGuide key="safeArea" id="Q9v-hL-Oos"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <constraints>
                            <constraint firstItem="KT3-Fk-a2q" firstAttribute="leading" secondItem="Q9v-hL-Oos" secondAttribute="leading" id="2wn-eS-c09"/>
                            <constraint firstItem="KT3-Fk-a2q" firstAttribute="top" secondItem="Q9v-hL-Oos" secondAttribute="top" id="FgK-nm-Di6"/>
                            <constraint firstItem="Q9v-hL-Oos" firstAttribute="trailing" secondItem="KT3-Fk-a2q" secondAttribute="trailing" id="QRV-wp-NLo"/>
                            <constraint firstItem="Q9v-hL-Oos" firstAttribute="bottom" secondItem="KT3-Fk-a2q" secondAttribute="bottom" id="nME-zr-LZG"/>
                        </constraints>
                    </view>
                    <navigationItem key="navigationItem" id="PvR-du-cNf"/>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="OmC-b8-55D" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1922" y="99"/>
        </scene>
        <!--Tab Split View Controller-->
        <scene sceneID="tKJ-sN-k8y">
            <objects>
                <placeholder placeholderIdentifier="IBFirstResponder" id="VMJ-P2-592" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
                <viewController id="keq-y0-8uV" customClass="TabSplitViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="5R4-1u-RPM">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="362.5"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <viewLayoutGuide key="safeArea" id="3CI-Kl-CH3"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                    </view>
                </viewController>
            </objects>
            <point key="canvasLocation" x="2739" y="-207"/>
        </scene>
        <!--Tab Split View Controller-->
        <scene sceneID="hWn-2r-CQ0">
            <objects>
                <placeholder placeholderIdentifier="IBFirstResponder" id="sWn-gZ-YJU" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
                <viewController id="wd2-dH-UL5" customClass="TabSplitViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="7Gg-UC-cbg">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="362.5"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <viewLayoutGuide key="safeArea" id="3s5-fq-554"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                    </view>
                </viewController>
            </objects>
            <point key="canvasLocation" x="2739" y="336"/>
        </scene>
        <!--Item-->
        <scene sceneID="p1i-Po-T0f">
            <objects>
                <navigationController id="a1s-VC-uIo" sceneMemberID="viewController">
                    <tabBarItem key="tabBarItem" title="Item" id="E01-3H-bgA"/>
                    <navigationBar key="navigationBar" contentMode="scaleToFill" id="AcF-Pd-ee7">
                        <rect key="frame" x="0.0" y="44" width="414" height="44"/>
                        <autoresizingMask key="autoresizingMask"/>
                    </navigationBar>
                    <connections>
                        <segue destination="98n-h0-2sL" kind="relationship" relationship="rootViewController" id="Bmk-qg-L7C"/>
                    </connections>
                </navigationController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="LBk-mi-acu" userLabel="First Responder" customClass="UIResponder" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="1091" y="98"/>
        </scene>
    </scenes>
    <resources>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>


================================================
FILE: example/ios/Runner/ViewControllers/Basic/TabContainer/TabSplitViewController.swift
================================================
//
//  TabSplitViewController.swift
//  Runner
//
//  Created by gix on 2020/12/25.
//

import Foundation
import g_faraday

class TabSplitViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        navigationController?.setNavigationBarHidden(true, animated: true)
        
        let vc = FaradayFlutterViewController("home")
        
        vc.willMove(toParent: self)
        addChild(vc)
        view.addSubview(vc.view)
        vc.didMove(toParent: self)
        
        vc.view.frame = view.frame;
        vc.view.autoresizingMask = [.flexibleWidth, .flexibleWidth]
    }
    
    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        if let index = parent?.children.firstIndex(of: self), index == 0 {
            if let vc = children.first as? FaradayFlutterViewController {
                Faraday.refreshViewController(vc)
            }
        }
    }
    
}




================================================
FILE: example/ios/Runner/ViewControllers/MainavigationViewController.swift
================================================
//
//  MainavigationViewController.swift
//  Runner
//
//  Created by gix on 2020/11/26.
//

import UIKit
import g_faraday

class MainavigationViewController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        setNavigationBarHidden(true, animated: false)
        setViewControllers([HomeFlutterViewController()], animated: false)
        
        //
        
        NotificationCenter.default.addObserver(forName: .init(rawValue: "GlobalNotification"), object: nil, queue: OperationQueue.main) { [weak self] _ in
            
            let vc = UIAlertController(title: "收到 GlobalNotification", message: "点击确定5s后发送通知到Flutter <这是一个Native的UIAlertController>", preferredStyle: .alert)
            
            vc.addAction(UIAlertAction(title: "取消", style: .destructive, handler: nil))
            
            vc.addAction(UIAlertAction(title: "确定", style: .default, handler: { _ in
                DispatchQueue.main.asyncAfter(deadline: .now() + 1) {
                    NotificationCenter.fa.post(name: "NotificationFromNative", object: "from ios native systemVersion: \(UIDevice.current.systemVersion)")
                }
            }))
            
            self?.present(vc, animated: true, completion: nil)
        }
    }
}


================================================
FILE: example/ios/Runner/ViewControllers/Others/NeedNavigationBarViewController.swift
================================================
//
//  NeedNavigationBarViewController.swift
//  Runner
//
//  Created by gix on 2020/11/27.
//

import UIKit

class NeedNavigationBarViewController: BaseViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationController?.setNavigationBarHidden(false, animated: true)
    }

}


================================================
FILE: example/ios/Runner/ViewControllers/Others/NoNavigationBarViewController.swift
================================================
//
//  NoNavigationBarViewController.swift
//  Runner
//
//  Created by gix on 2020/11/27.
//

import UIKit
import g_faraday

class NoNavigationBarViewController: BaseViewController, FaradayNavigationBarHiddenProtocol {

    override func viewDidLoad() {
        super.viewDidLoad()

        navigationController?.setNavigationBarHidden(true, animated: false)
    }
    
    
    @IBAction func onTabBack(sender: UIButton) {
        
        navigationController?.popViewController(animated: true)
    }
}


================================================
FILE: example/ios/Runner/ViewControllers/Others/Other.storyboard
================================================
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17506" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="lei-SI-Q7E">
    <device id="retina6_1" orientation="portrait" appearance="light"/>
    <dependencies>
        <deployment identifier="iOS"/>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17505"/>
        <capability name="Safe area layout guides" minToolsVersion="9.0"/>
        <capability name="System colors in document resources" minToolsVersion="11.0"/>
        <capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
    </dependencies>
    <scenes>
        <!--Need Navigation Bar View Controller-->
        <scene sceneID="um8-5F-asF">
            <objects>
                <viewController id="lei-SI-Q7E" customClass="NeedNavigationBarViewController" customModule="Runner" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="sPk-ex-hmx">
                        <rect key="frame" x="0.0" y="0.0" width="414" height="896"/>
                        <auto
Download .txt
gitextract_t4tm_p0m/

├── .fvm/
│   └── fvm_config.json
├── .gitattributes
├── .github/
│   ├── labeler.yml
│   └── workflows/
│       ├── greetings.yml
│       ├── label.yml
│       └── publish.yml
├── .gitignore
├── .metadata
├── .vscode/
│   ├── launch.json
│   └── settings.json
├── CHANGELOG.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── README_EN.md
├── analysis_options.yaml
├── android/
│   ├── .gitignore
│   ├── app/
│   │   └── src/
│   │       └── main/
│   │           └── java/
│   │               └── io/
│   │                   └── flutter/
│   │                       └── plugins/
│   │                           └── GeneratedPluginRegistrant.java
│   ├── build.gradle
│   ├── gradle/
│   │   └── wrapper/
│   │       └── gradle-wrapper.properties
│   ├── gradle.properties
│   ├── settings.gradle
│   └── src/
│       └── main/
│           ├── AndroidManifest.xml
│           └── kotlin/
│               └── com/
│                   └── yuxiaor/
│                       └── flutter/
│                           └── g_faraday/
│                               ├── Faraday.kt
│                               ├── FaradayActivity.kt
│                               ├── FaradayColorBaseSplashScreen.kt
│                               ├── FaradayConstants.kt
│                               ├── FaradayFragment.kt
│                               ├── FaradayNavigator.kt
│                               ├── GFaradayPlugin.kt
│                               ├── ResultProvider.kt
│                               └── channels/
│                                   ├── CommonChannel.kt
│                                   ├── NavigatorAnchor.kt
│                                   ├── NetChannel.kt
│                                   └── NoticeChannel.kt
├── doc/
│   ├── bridge.md
│   ├── callback.md
│   ├── ci.md
│   ├── ios-simulator-install.md
│   ├── ios_navigation_bar.md
│   ├── json.md
│   ├── net.md
│   ├── notification.md
│   └── route.md
├── example/
│   ├── .gitignore
│   ├── .metadata
│   ├── .vscode/
│   │   ├── launch.json
│   │   └── settings.json
│   ├── README.md
│   ├── analysis_options.yaml
│   ├── android/
│   │   ├── .gitignore
│   │   ├── app/
│   │   │   ├── build.gradle
│   │   │   ├── release/
│   │   │   │   └── output-metadata.json
│   │   │   └── src/
│   │   │       ├── main/
│   │   │       │   ├── AndroidManifest.xml
│   │   │       │   ├── kotlin/
│   │   │       │   │   └── com/
│   │   │       │   │       └── yuxiaor/
│   │   │       │   │           └── flutter/
│   │   │       │   │               └── g_faraday_example/
│   │   │       │   │                   ├── App.kt
│   │   │       │   │                   ├── activity/
│   │   │       │   │                   │   ├── MainActivity.kt
│   │   │       │   │                   │   ├── SingleTaskFlutterActivity.kt
│   │   │       │   │                   │   ├── SingleTopFlutterActivity.kt
│   │   │       │   │                   │   └── splash/
│   │   │       │   │                   │       └── FirstFlutterActivity.kt
│   │   │       │   │                   ├── basic/
│   │   │       │   │                   │   ├── FlutterToNativeActivity.kt
│   │   │       │   │                   │   ├── Native2FlutterActivity.kt
│   │   │       │   │                   │   ├── TabContainerActivity.kt
│   │   │       │   │                   │   ├── TransparentBackgroundFlutterActivity.kt
│   │   │       │   │                   │   └── fragments/
│   │   │       │   │                   │       └── NativeFragment.kt
│   │   │       │   │                   ├── faraday/
│   │   │       │   │                   │   └── CustomNavigator.kt
│   │   │       │   │                   ├── fragment/
│   │   │       │   │                   │   └── TestFragment.kt
│   │   │       │   │                   ├── utils/
│   │   │       │   │                   │   └── ViewExt.kt
│   │   │       │   │                   └── widget/
│   │   │       │   │                       ├── BaseDialog.kt
│   │   │       │   │                       └── NotificationDialog.kt
│   │   │       │   └── res/
│   │   │       │       ├── anim/
│   │   │       │       │   ├── in_from_left.xml
│   │   │       │       │   ├── in_from_right.xml
│   │   │       │       │   ├── out_from_left.xml
│   │   │       │       │   └── out_from_right.xml
│   │   │       │       ├── color/
│   │   │       │       │   └── check_primary_light.xml
│   │   │       │       ├── drawable/
│   │   │       │       │   ├── launch_background.xml
│   │   │       │       │   ├── tab_file.xml
│   │   │       │       │   ├── tab_home.xml
│   │   │       │       │   ├── tab_house.xml
│   │   │       │       │   └── tab_msg.xml
│   │   │       │       ├── layout/
│   │   │       │       │   ├── activity_flutter2native.xml
│   │   │       │       │   ├── activity_fragment.xml
│   │   │       │       │   ├── activity_main.xml
│   │   │       │       │   ├── activity_native2flutter.xml
│   │   │       │       │   ├── activity_tab_container.xml
│   │   │       │       │   ├── dialog_notification.xml
│   │   │       │       │   └── frag_test.xml
│   │   │       │       ├── navigation/
│   │   │       │       │   └── nav_graph.xml
│   │   │       │       ├── values/
│   │   │       │       │   ├── colors.xml
│   │   │       │       │   ├── strings.xml
│   │   │       │       │   └── styles.xml
│   │   │       │       └── values-v31/
│   │   │       │           └── styles.xml
│   │   │       └── profile/
│   │   │           └── AndroidManifest.xml
│   │   ├── build.gradle
│   │   ├── gradle/
│   │   │   └── wrapper/
│   │   │       └── gradle-wrapper.properties
│   │   ├── gradle.properties
│   │   └── settings.gradle
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.swift
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   ├── Contents.json
│   │   │   │   ├── LaunchImage.imageset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── logo.imageset/
│   │   │   │       └── Contents.json
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── Faraday/
│   │   │   │   ├── FaradayCommon.swift
│   │   │   │   ├── FaradayNet.swift
│   │   │   │   └── FaradayRoute.swift
│   │   │   ├── GeneratedPluginRegistrant.h
│   │   │   ├── GeneratedPluginRegistrant.m
│   │   │   ├── Info.plist
│   │   │   ├── Runner-Bridging-Header.h
│   │   │   └── ViewControllers/
│   │   │       ├── BaseViewController.swift
│   │   │       ├── Basic/
│   │   │       │   ├── Flutter2NativeViewController.swift
│   │   │       │   ├── Flutter2NativeViewController.xib
│   │   │       │   ├── Native2FlutterViewController.swift
│   │   │       │   ├── Native2FlutterViewController.xib
│   │   │       │   └── TabContainer/
│   │   │       │       ├── Tab1ViewController.swift
│   │   │       │       ├── Tab2ViewController.swift
│   │   │       │       ├── TabContainer.storyboard
│   │   │       │       └── TabSplitViewController.swift
│   │   │       ├── MainavigationViewController.swift
│   │   │       ├── Others/
│   │   │       │   ├── NeedNavigationBarViewController.swift
│   │   │       │   ├── NoNavigationBarViewController.swift
│   │   │       │   └── Other.storyboard
│   │   │       ├── Splash/
│   │   │       │   └── HomeFlutterViewController.swift
│   │   │       └── Tab0ViewController.swift
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           ├── IDEWorkspaceChecks.plist
│   │           └── WorkspaceSettings.xcsettings
│   ├── lib/
│   │   ├── fluro_router.dart
│   │   ├── main.dart
│   │   ├── main_fluro.dart
│   │   ├── main_get.dart
│   │   └── src/
│   │       ├── debug/
│   │       │   └── debug.dart
│   │       ├── pages/
│   │       │   ├── example_page_scaffold.dart
│   │       │   ├── features/
│   │       │   │   ├── basic/
│   │       │   │   │   ├── basic.dart
│   │       │   │   │   └── pages/
│   │       │   │   │       ├── flutter_to_flutter.dart
│   │       │   │   │       ├── flutter_to_native.dart
│   │       │   │   │       ├── native_to_flutter.dart
│   │       │   │   │       ├── tab_page.dart
│   │       │   │   │       └── transparent_page.dart
│   │       │   │   ├── notification/
│   │       │   │   │   └── notification.dart
│   │       │   │   ├── other/
│   │       │   │   │   └── other.dart
│   │       │   │   └── splash/
│   │       │   │       └── splash.dart
│   │       │   └── home_page.dart
│   │       ├── utils/
│   │       │   ├── observer.dart
│   │       │   └── simple_localizations.dart
│   │       └── widgets/
│   │           ├── action.dart
│   │           └── section.dart
│   ├── pubspec.yaml
│   └── test/
│       └── widget_test.dart
├── example_objc_only/
│   ├── .gitignore
│   ├── .metadata
│   ├── README.md
│   ├── ios/
│   │   ├── .gitignore
│   │   ├── Flutter/
│   │   │   ├── AppFrameworkInfo.plist
│   │   │   ├── Debug.xcconfig
│   │   │   └── Release.xcconfig
│   │   ├── Podfile
│   │   ├── Runner/
│   │   │   ├── AppDelegate.h
│   │   │   ├── AppDelegate.m
│   │   │   ├── Assets.xcassets/
│   │   │   │   ├── AppIcon.appiconset/
│   │   │   │   │   └── Contents.json
│   │   │   │   └── LaunchImage.imageset/
│   │   │   │       ├── Contents.json
│   │   │   │       └── README.md
│   │   │   ├── Base.lproj/
│   │   │   │   ├── LaunchScreen.storyboard
│   │   │   │   └── Main.storyboard
│   │   │   ├── DemoViewController.h
│   │   │   ├── DemoViewController.m
│   │   │   ├── FaradayHelper.swift
│   │   │   ├── Info.plist
│   │   │   ├── Runner-Bridging-Header.h
│   │   │   └── main.m
│   │   ├── Runner.xcodeproj/
│   │   │   ├── project.pbxproj
│   │   │   ├── project.xcworkspace/
│   │   │   │   ├── contents.xcworkspacedata
│   │   │   │   └── xcshareddata/
│   │   │   │       ├── IDEWorkspaceChecks.plist
│   │   │   │       └── WorkspaceSettings.xcsettings
│   │   │   └── xcshareddata/
│   │   │       └── xcschemes/
│   │   │           └── Runner.xcscheme
│   │   └── Runner.xcworkspace/
│   │       ├── contents.xcworkspacedata
│   │       └── xcshareddata/
│   │           ├── IDEWorkspaceChecks.plist
│   │           └── WorkspaceSettings.xcsettings
│   ├── lib/
│   │   └── main.dart
│   ├── pubspec.yaml
│   └── test/
│       └── widget_test.dart
├── g_faraday.iml
├── ios/
│   ├── .gitignore
│   ├── Assets/
│   │   └── .gitkeep
│   ├── Classes/
│   │   ├── Faraday.swift
│   │   ├── FaradayExtended.swift
│   │   ├── FaradayFlutterViewController.swift
│   │   ├── FlutterEngine+Identifier.swift
│   │   ├── GFaradayPlugin.h
│   │   ├── GFaradayPlugin.m
│   │   ├── NotificationCenter+Faraday.swift
│   │   ├── Options.swift
│   │   ├── SwiftGFaradayPlugin.swift
│   │   ├── UIViewController+Faraday.swift
│   │   ├── UIViewController+Swizzle.swift
│   │   └── UIViewController+TopMost.swift
│   └── g_faraday.podspec
├── lib/
│   ├── g_faraday.dart
│   └── src/
│       ├── common/
│       │   ├── common.dart
│       │   ├── entry.dart
│       │   └── net.dart
│       ├── faraday.dart
│       ├── route/
│       │   ├── arg.dart
│       │   ├── native_bridge.dart
│       │   ├── navigator.dart
│       │   ├── navigator_ext.dart
│       │   ├── observer.dart
│       │   ├── options.dart
│       │   └── route.dart
│       └── widgets/
│           ├── debugger.dart
│           ├── log.dart
│           └── notification_listener.dart
└── pubspec.yaml
Download .txt
SYMBOL INDEX (175 symbols across 31 files)

FILE: android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java
  class GeneratedPluginRegistrant (line 9) | public final class GeneratedPluginRegistrant {
    method registerWith (line 10) | public static void registerWith(PluginRegistry registry) {
    method alreadyRegisteredWith (line 17) | private static boolean alreadyRegisteredWith(PluginRegistry registry) {

FILE: example/lib/main.dart
  function main (line 13) | void main()
  class MyApp (line 17) | class MyApp extends StatefulWidget {
    method createState (line 22) | _MyAppState createState()
  class _MyAppState (line 25) | class _MyAppState extends State<MyApp> {
    method build (line 44) | Widget build(BuildContext context)
    method _buildErrorPage (line 104) | Widget _buildErrorPage(BuildContext context)

FILE: example/lib/src/pages/example_page_scaffold.dart
  class ExamplePageScaffold (line 3) | class ExamplePageScaffold extends StatefulWidget {
    method createState (line 11) | _ExamplePageScaffoldState createState()
  class _ExamplePageScaffoldState (line 14) | class _ExamplePageScaffoldState extends State<ExamplePageScaffold> {
    method build (line 16) | Widget build(BuildContext context)

FILE: example/lib/src/pages/features/basic/basic.dart
  class Basic (line 10) | class Basic extends StatefulWidget {
    method createState (line 14) | _BasicState createState()
  class _BasicState (line 17) | class _BasicState extends State<Basic> {
    method build (line 19) | Widget build(BuildContext context)
  class BasicAllPage (line 36) | class BasicAllPage extends StatelessWidget {
    method build (line 40) | Widget build(BuildContext context)
  function _buildActions (line 69) | List<Widget> _buildActions(BuildContext context, {bool onlyBase = true})
  class _Action (line 113) | class _Action extends StatelessWidget {
    method build (line 134) | Widget build(BuildContext context)

FILE: example/lib/src/pages/features/basic/pages/flutter_to_flutter.dart
  class Flutter2Flutter (line 5) | class Flutter2Flutter extends StatefulWidget {
    method createState (line 11) | _Flutter2FlutterState createState()
  class _Flutter2FlutterState (line 14) | class _Flutter2FlutterState extends State<Flutter2Flutter> {
    method build (line 16) | Widget build(BuildContext context)

FILE: example/lib/src/pages/features/basic/pages/flutter_to_native.dart
  class Flutter2NativePage (line 5) | class Flutter2NativePage extends StatefulWidget {
    method createState (line 9) | _Flutter2NativePageState createState()
  class _Flutter2NativePageState (line 12) | class _Flutter2NativePageState extends State<Flutter2NativePage> {
    method build (line 16) | Widget build(BuildContext context)
    method _showResult (line 69) | void _showResult(BuildContext context, Object? result)

FILE: example/lib/src/pages/features/basic/pages/native_to_flutter.dart
  class Native2FlutterPage (line 4) | class Native2FlutterPage extends StatefulWidget {
    method createState (line 10) | _Native2FlutterPageState createState()
  class _Native2FlutterPageState (line 13) | class _Native2FlutterPageState extends State<Native2FlutterPage> {
    method initState (line 15) | void initState()
    method build (line 20) | Widget build(BuildContext context)
    method deactivate (line 44) | void deactivate()
    method dispose (line 49) | void dispose()

FILE: example/lib/src/pages/features/basic/pages/tab_page.dart
  class TabPage (line 3) | class TabPage extends StatefulWidget {
    method createState (line 7) | _TabPageState createState()
  class _TabPageState (line 10) | class _TabPageState extends State<TabPage> {
    method build (line 12) | Widget build(BuildContext context)

FILE: example/lib/src/pages/features/basic/pages/transparent_page.dart
  class TransparentPage (line 4) | class TransparentPage extends StatefulWidget {
    method createState (line 8) | _TransparentPageState createState()
  class _TransparentPageState (line 11) | class _TransparentPageState extends State<TransparentPage>
    method initState (line 16) | void initState()
    method build (line 27) | Widget build(BuildContext context)

FILE: example/lib/src/pages/features/notification/notification.dart
  class GlobalNotification (line 8) | class GlobalNotification extends StatefulWidget {
    method createState (line 12) | _GlobalNotificationState createState()
  class _GlobalNotificationState (line 15) | class _GlobalNotificationState extends State<GlobalNotification> {
    method build (line 19) | Widget build(BuildContext context)

FILE: example/lib/src/pages/features/other/other.dart
  class Others (line 12) | class Others extends StatefulWidget {
    method createState (line 16) | _OthersState createState()
  class _OthersState (line 19) | class _OthersState extends State<Others> {
    method build (line 21) | Widget build(BuildContext context)
  class _WillPopPage (line 58) | class _WillPopPage extends StatefulWidget {
    method createState (line 60) | __WillPopPageState createState()
  class __WillPopPageState (line 63) | class __WillPopPageState extends State<_WillPopPage> {
    method build (line 65) | Widget build(BuildContext context)

FILE: example/lib/src/pages/features/splash/splash.dart
  class Splash (line 8) | class Splash extends StatefulWidget {
    method createState (line 12) | _SplashState createState()
  type _Platform (line 15) | enum _Platform { ios, android, fluter }
  class _SplashState (line 17) | class _SplashState extends State<Splash> {
    method build (line 19) | Widget build(BuildContext context)
  class SplashTipPage (line 53) | class SplashTipPage extends StatefulWidget {
    method createState (line 60) | _SplashTipPageState createState()
  class _SplashTipPageState (line 63) | class _SplashTipPageState extends State<SplashTipPage> {
    method build (line 65) | Widget build(BuildContext context)
    method _buildIOSTip (line 77) | List<Widget> _buildIOSTip(BuildContext context)
    method _buildAndroidTip (line 89) | List<Widget> _buildAndroidTip(BuildContext context)
    method _buildFlutterTip (line 101) | List<Widget> _buildFlutterTip(BuildContext context)

FILE: example/lib/src/pages/home_page.dart
  class HomePage (line 12) | class HomePage extends StatefulWidget {
    method createState (line 18) | _HomePageState createState()
  class _HomePageState (line 21) | class _HomePageState extends State<HomePage> {
    method initState (line 23) | void initState()
    method build (line 28) | Widget build(BuildContext context)
    method _buildSlivers (line 68) | List<Widget> _buildSlivers(BuildContext context)
  class HomePageBannerDelegate (line 113) | class HomePageBannerDelegate extends SliverPersistentHeaderDelegate {
    method build (line 115) | Widget build(
    method shouldRebuild (line 145) | bool shouldRebuild(covariant SliverPersistentHeaderDelegate oldDelegate)

FILE: example/lib/src/utils/observer.dart
  class DemoObserver (line 3) | class DemoObserver extends NavigatorObserver {
    method didPop (line 9) | void didPop(Route route, Route? previousRoute)
    method didPush (line 17) | void didPush(Route route, Route? previousRoute)

FILE: example/lib/src/utils/simple_localizations.dart
  class S (line 6) | class S {
    method of (line 14) | S of(BuildContext context)
  class SimpleLocalizationsDelegate (line 113) | class SimpleLocalizationsDelegate extends LocalizationsDelegate<S> {
    method isSupported (line 117) | bool isSupported(Locale locale)
    method load (line 120) | Future<S> load(Locale locale)
    method shouldReload (line 125) | bool shouldReload(SimpleLocalizationsDelegate old)

FILE: example/lib/src/widgets/action.dart
  class FaradayAction (line 3) | class FaradayAction extends StatelessWidget {
    method build (line 18) | Widget build(BuildContext context)

FILE: example/lib/src/widgets/section.dart
  class Section (line 5) | class Section extends StatelessWidget {
    method build (line 20) | Widget build(BuildContext context)

FILE: example_objc_only/lib/main.dart
  function main (line 4) | void main()
  class DemoApp (line 8) | class DemoApp extends StatefulWidget {
    method createState (line 12) | DemoAppState createState()
  class DemoAppState (line 15) | class DemoAppState extends State<DemoApp> {
    method build (line 17) | Widget build(BuildContext context)

FILE: lib/src/common/common.dart
  class FaradayCommon (line 7) | class FaradayCommon {
    method invokeMethod (line 10) | Future<T?> invokeMethod<T>(String method, [dynamic arguments])
    method invokeListMethod (line 14) | Future<List<T>?> invokeListMethod<T>(String method,
    method invokeMapMethod (line 19) | Future<Map<K, V>?> invokeMapMethod<K, V>(String method,
  class _FaradayCommonIgnoreMethod (line 28) | class _FaradayCommonIgnoreMethod {

FILE: lib/src/common/entry.dart
  class _FaradayEntry (line 3) | class _FaradayEntry {

FILE: lib/src/common/net.dart
  class FaradayNet (line 6) | class FaradayNet {
    method request (line 8) | Future request(String method, String url,

FILE: lib/src/faraday.dart
  class Faraday (line 8) | class Faraday {
    method refresh (line 23) | void refresh()
    method wrapper (line 53) | Route<dynamic> wrapper(

FILE: lib/src/route/arg.dart
  class FaradayArguments (line 9) | class FaradayArguments {

FILE: lib/src/route/native_bridge.dart
  type TransitionBuilderProvider (line 17) | typedef TransitionBuilderProvider = TransitionBuilder? Function(
  type ColorProvider (line 20) | typedef ColorProvider = Color Function(BuildContext context, {JSON? rout...
  function _defaultBackgroundColor (line 22) | Color _defaultBackgroundColor(BuildContext context, {JSON? route})
  class FaradayNativeBridge (line 45) | class FaradayNativeBridge extends StatefulWidget {
    method of (line 69) | FaradayNativeBridgeState? of(BuildContext context)
    method createState (line 78) | FaradayNativeBridgeState createState()
  class FaradayNativeBridgeState (line 81) | class FaradayNativeBridgeState extends State<FaradayNativeBridge> {
    method initState (line 89) | void initState()
    method recreateLastPage (line 94) | void recreateLastPage()
    method reassemble (line 109) | void reassemble()
    method dispose (line 119) | void dispose()
    method pushNamed (line 124) | Future<T?> pushNamed<T extends Object?>(
    method pop (line 137) | Future<void> pop<T extends Object>(Key key, [T? result])
    method disableHorizontalSwipePopGesture (line 145) | Future<void> disableHorizontalSwipePopGesture({required bool disable})
    method isOnTop (line 150) | bool isOnTop(Key key)
    method build (line 159) | Widget build(BuildContext context)
    method _defaultErrorPage (line 231) | Widget _defaultErrorPage(BuildContext context)
    method _handler (line 240) | Future<bool> _handler(MethodCall call)
    method _findIndexBy (line 306) | int? _findIndexBy({required int id})
    method _updateIndex (line 311) | void _updateIndex(int? index)
    method _buildPage (line 328) | Widget _buildPage(BuildContext context, FaradayArguments arg)

FILE: lib/src/route/navigator.dart
  class FaradayNavigator (line 10) | class FaradayNavigator extends Navigator {
    method createState (line 31) | FaradayNavigatorState createState()
    method of (line 34) | FaradayNavigatorState of(BuildContext context)
  class FaradayNavigatorState (line 45) | class FaradayNavigatorState extends NavigatorState {
    method initState (line 57) | void initState()
    method dispose (line 66) | void dispose()
    method _notifyNativeDisableOrEnableBackGesture (line 77) | void _notifyNativeDisableOrEnableBackGesture()
    method pushNamed (line 83) | Future<T?> pushNamed<T extends Object?>(String routeName,
    method clean (line 99) | void clean()
    method pop (line 105) | void pop<T extends Object?>([T? result])
    method maybePop (line 117) | Future<bool> maybePop<T extends Object?>([T? result])
  class _FaradayWidgetsBindingObserver (line 127) | class _FaradayWidgetsBindingObserver extends WidgetsBindingObserver {
    method didPopRoute (line 133) | Future<bool> didPopRoute()

FILE: lib/src/route/navigator_ext.dart
  function nativePop (line 11) | Future<void> nativePop<T extends Object>([T? result])
  function nativePushNamed (line 21) | Future<T?> nativePushNamed<T extends Object>(String routeName,

FILE: lib/src/route/observer.dart
  class FaradayNavigatorObserver (line 4) | class FaradayNavigatorObserver extends NavigatorObserver {
    method didPush (line 20) | void didPush(Route route, Route? previousRoute)
    method didReplace (line 30) | void didReplace({Route<dynamic>? newRoute, Route<dynamic>? oldRoute})
    method didPop (line 40) | void didPop(Route route, Route? previousRoute)
    method didRemove (line 50) | void didRemove(Route route, Route? previousRoute)
    method _increment (line 59) | void _increment(Route route)
    method _decrement (line 63) | void _decrement(Route? route)
    method _update (line 67) | void _update({required int page, Route? route})

FILE: lib/src/route/options.dart
  class Options (line 4) | class Options {
    method disableAnimation (line 14) | void disableAnimation()
    method present (line 17) | void present()
    method flutterRoute (line 20) | void flutterRoute()
    method add (line 23) | void add({required String key, required dynamic value})

FILE: lib/src/route/route.dart
  class FaradayPageRouteBuilder (line 4) | class FaradayPageRouteBuilder<T> extends PageRouteBuilder<T> {
    method willPop (line 15) | Future<RoutePopDisposition> willPop()

FILE: lib/src/widgets/log.dart
  class Level (line 4) | class Level {
  function log (line 29) | void log(String message,

FILE: lib/src/widgets/notification_listener.dart
  function _observerNativeNotification (line 22) | StreamSubscription _observerNativeNotification(
  function _handler (line 29) | Future<bool> _handler(MethodCall call)
  class FaradayNotification (line 39) | class FaradayNotification {
    method toString (line 52) | String toString()
    method dispatchToGlobal (line 60) | void dispatchToGlobal({bool deliverToNative = true})
  type NotificationReceivedCallback (line 71) | typedef NotificationReceivedCallback = void Function(
  class FaradayNotificationListener (line 75) | class FaradayNotificationListener extends StatefulWidget {
    method createState (line 100) | _FaradayNotificationListenerState createState()
  class _FaradayNotificationListenerState (line 104) | class _FaradayNotificationListenerState
    method initState (line 109) | void initState()
    method dispose (line 121) | void dispose()
    method build (line 127) | Widget build(BuildContext context)
Condensed preview — 224 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (440K chars).
[
  {
    "path": ".fvm/fvm_config.json",
    "chars": 52,
    "preview": "{\n  \"flutterSdkVersion\": \"3.16.9\",\n  \"flavors\": {}\n}"
  },
  {
    "path": ".gitattributes",
    "chars": 117,
    "preview": "*.swift linguist-language=dart\n*.kt linguist-language=dart\n*.java linguist-language=dart\n*.rb linguist-language=dart\n"
  },
  {
    "path": ".github/labeler.yml",
    "chars": 121,
    "preview": "repo:\n  - ./*\n  \nios:\n  - ios/**/*.swift\n\nandroid:\n  - android/**/*.java\n  - android/**/*.kt\n\nflutter:\n  - src/**/*.dart"
  },
  {
    "path": ".github/workflows/greetings.yml",
    "chars": 274,
    "preview": "name: Greetings\n\non: [pull_request, issues]\n\njobs:\n  greeting:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions"
  },
  {
    "path": ".github/workflows/label.yml",
    "chars": 467,
    "preview": "# This workflow will triage pull requests and apply a label based on the\n# paths that are modified in the pull request.\n"
  },
  {
    "path": ".github/workflows/publish.yml",
    "chars": 1693,
    "preview": "# This is a basic workflow to help you get started with Actions\n\nname: Publisher\n\non:\n  push:\n    branches: [master]\n\n  "
  },
  {
    "path": ".gitignore",
    "chars": 116,
    "preview": ".DS_Store\n.dart_tool/\n.idea\n\n.packages\n.pub/\n\nbuild/\n.flutter-plugins\n\nandroid-aar-repo\nios-frameworks\n.faraday.json"
  },
  {
    "path": ".metadata",
    "chars": 308,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": ".vscode/launch.json",
    "chars": 519,
    "preview": "{\n  // Use IntelliSense to learn about possible attributes.\n  // Hover to view descriptions of existing attributes.\n  //"
  },
  {
    "path": ".vscode/settings.json",
    "chars": 284,
    "preview": "{\n  \"cSpell.words\": [\n    \"anothr\",\n    \"ARGB\",\n    \"BUPT\",\n    \"cocoapod\",\n    \"cocoapods\",\n    \"Dealloc\",\n    \"Dealloc"
  },
  {
    "path": "CHANGELOG.md",
    "chars": 3533,
    "preview": "# 1.0.2\n* Fix NPE when platform plugin delegate is null\n\n# 1.0.1\n\n* migrate to flutter 3.16.9\n* ios add FaradayNavigatio"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 915,
    "preview": "# Contributing to g_faraday\n\n## 1. Things you will need\n\n- Linux, Mac OS X, or Windows.\n- [git](https://git-scm.com) (us"
  },
  {
    "path": "LICENSE",
    "chars": 1079,
    "preview": "Copyright (c) 2020 Faraday Team (http://www.faraday.中国)\n\nPermission is hereby granted, free of charge, to any person obt"
  },
  {
    "path": "README.md",
    "chars": 11801,
    "preview": "# ![log](./doc/images/logo.png)  Faraday [English](./README_EN.md)\n\n![Build](https://img.shields.io/github/workflow/stat"
  },
  {
    "path": "README_EN.md",
    "chars": 10093,
    "preview": "# ![log](./doc/images/logo.png)  Faraday [中文文档](./README.md)\n\n![Build](https://img.shields.io/github/workflow/status/gfa"
  },
  {
    "path": "analysis_options.yaml",
    "chars": 1453,
    "preview": "# This file configures the analyzer, which statically analyzes Dart code to\n# check for errors, warnings, and lints.\n#\n#"
  },
  {
    "path": "android/.gitignore",
    "chars": 97,
    "preview": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n"
  },
  {
    "path": "android/app/src/main/java/io/flutter/plugins/GeneratedPluginRegistrant.java",
    "chars": 716,
    "preview": "package io.flutter.plugins;\n\nimport io.flutter.plugin.common.PluginRegistry;\nimport com.yuxiaor.flutter.g_faraday.GFarad"
  },
  {
    "path": "android/build.gradle",
    "chars": 989,
    "preview": "group 'com.yuxiaor.flutter.g_faraday'\nversion '1.0-SNAPSHOT'\n\nbuildscript {\n    ext.kotlin_version = '1.6.21'\n    reposi"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "chars": 202,
    "preview": "distributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dist"
  },
  {
    "path": "android/gradle.properties",
    "chars": 82,
    "preview": "org.gradle.jvmargs=-Xmx1536M\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "android/settings.gradle",
    "chars": 31,
    "preview": "rootProject.name = 'g_faraday'\n"
  },
  {
    "path": "android/src/main/AndroidManifest.xml",
    "chars": 663,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/Faraday.kt",
    "chars": 5830,
    "preview": "package com.yuxiaor.flutter.g_faraday\n\nimport android.app.Activity\nimport android.content.Context\nimport android.content"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayActivity.kt",
    "chars": 8144,
    "preview": "package com.yuxiaor.flutter.g_faraday\n\nimport android.app.Activity\nimport android.content.Context\nimport android.content"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayColorBaseSplashScreen.kt",
    "chars": 1724,
    "preview": "//package com.yuxiaor.flutter.g_faraday\n//\n//import android.animation.Animator\n//import android.animation.Animator.Anima"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayConstants.kt",
    "chars": 434,
    "preview": "package com.yuxiaor.flutter.g_faraday\n\nclass FaradayConstants {\n\n    companion object {\n        //TODO: 这些key的定义,需要重构\n  "
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayFragment.kt",
    "chars": 7162,
    "preview": "\n\npackage com.yuxiaor.flutter.g_faraday\n\nimport android.app.Activity\nimport android.content.Context\nimport android.conte"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/FaradayNavigator.kt",
    "chars": 980,
    "preview": "package com.yuxiaor.flutter.g_faraday\n\nimport android.content.Intent\nimport java.io.Serializable\n\n/**\n * Author: Edward\n"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/GFaradayPlugin.kt",
    "chars": 4411,
    "preview": "package com.yuxiaor.flutter.g_faraday\n\nimport android.util.Log\nimport androidx.annotation.NonNull\nimport androidx.fragme"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/ResultProvider.kt",
    "chars": 305,
    "preview": "package com.yuxiaor.flutter.g_faraday\n\nimport android.content.Intent\n\n/**\n * Author: Edward\n * Date: 2020-10-22\n * Descr"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/CommonChannel.kt",
    "chars": 458,
    "preview": "package com.yuxiaor.flutter.g_faraday.channels\n\nimport io.flutter.plugin.common.BinaryMessenger\nimport io.flutter.plugin"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/NavigatorAnchor.kt",
    "chars": 2303,
    "preview": "//package com.yuxiaor.flutter.g_faraday.channels\n//\n//import android.app.Activity\n//import android.content.Intent\n//impo"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/NetChannel.kt",
    "chars": 1299,
    "preview": "package com.yuxiaor.flutter.g_faraday.channels\n\nimport io.flutter.plugin.common.BinaryMessenger\nimport io.flutter.plugin"
  },
  {
    "path": "android/src/main/kotlin/com/yuxiaor/flutter/g_faraday/channels/NoticeChannel.kt",
    "chars": 2134,
    "preview": "package com.yuxiaor.flutter.g_faraday.channels\n\nimport com.yuxiaor.flutter.g_faraday.Faraday\nimport io.flutter.embedding"
  },
  {
    "path": "doc/bridge.md",
    "chars": 1300,
    "preview": "# 桥接原生方法\n\n作为一个原生为主的混合应用,原生代码层肯定已经有了大量的基础设施例如加解密,或者本机缓存等等。想要调用这些本地`服务`有两种方式:\n\n## FaradayCommon\n\nfaraday定义了一个特定的[channel]("
  },
  {
    "path": "doc/callback.md",
    "chars": 2897,
    "preview": "# 页面间传值\n\n## Flutter侧\n\n在`flutter`这边传值比较容易,不管是`flutter->flutter`还是`flutter->native`或者`native-flutter`都和`纯flutter`写法无任何差异例如"
  },
  {
    "path": "doc/ci.md",
    "chars": 15,
    "preview": "# TODO 后面写详细文档\n"
  },
  {
    "path": "doc/ios-simulator-install.md",
    "chars": 128,
    "preview": "\n# ios 模拟器安装app\n\n``` shell\n\n# 启动模拟器\nxcrun instruments -w 'iPhone 12'\n\n# 安装\nxcrun simctl install booted path/to/example.a"
  },
  {
    "path": "doc/ios_navigation_bar.md",
    "chars": 411,
    "preview": "# iOS Navigation Bar\n\n`FlutterViewController` 需要隐藏`navigation bar`,因此我们需要在这个vc显示隐藏的时候对应的处理`navigation bar`的隐藏显示逻辑。这里我们提供"
  },
  {
    "path": "doc/json.md",
    "chars": 462,
    "preview": "# JSON\n\njson在我们日常开发中已经变的非常重要了,用来传递数据可读性非常的好。我们将对json的处理单独剥离出来成为一个独立的`package`:\n\n[https://pub.dev/packages/g_json](https:"
  },
  {
    "path": "doc/net.md",
    "chars": 4095,
    "preview": "# Net\n\n`g_faraday`默认现有的`ios`&`android`已经存在大量的网络基础设施(包括但不限于登录验证,加解密等等)\n\n> 如果没有没有你可以跳过此部分内容\n\n## Flutter\n\n`flutter`侧我们提供了`F"
  },
  {
    "path": "doc/notification.md",
    "chars": 1205,
    "preview": "# 通知\n\n通过全局的通知来传递数据,或者驱动业务不是一个很好的软件模式,但是在某些特定的场景却可以节省大量的时间。我们对混合app通知做了部分封装方便大家开发业务时使用。\n\n## flutter\n\n``` dart\n\n// 构造相应的通知"
  },
  {
    "path": "doc/route.md",
    "chars": 1369,
    "preview": "# 路由\n\n`g_faraday`是作为一个解决混合路由栈的框架而开发的,因此对路由的支持特别完备。`g_faraday`采用最小入侵的设计原则,不管是在`native`侧还是`flutter`侧,只需要在程序入口处做少量的注册即可完成集成"
  },
  {
    "path": "example/.gitignore",
    "chars": 736,
    "preview": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.i"
  },
  {
    "path": "example/.metadata",
    "chars": 305,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": "example/.vscode/launch.json",
    "chars": 528,
    "preview": "{\n    \"configurations\": [\n        {\n            \"name\": \"g_faraday demo fluro\",\n            \"type\": \"dart\",\n            "
  },
  {
    "path": "example/.vscode/settings.json",
    "chars": 68,
    "preview": "{\n    \"cSpell.words\": [\n        \"ARGB\",\n        \"Scrollable\"\n    ]\n}"
  },
  {
    "path": "example/README.md",
    "chars": 331,
    "preview": "# g_faraday_example\n\n## 主要包含一下功能点 (TODO)\n\n### Basic\n\n* native -> flutter (ios: push/present android: activity/fragment)\n"
  },
  {
    "path": "example/analysis_options.yaml",
    "chars": 142,
    "preview": "include: package:flutter_lints/flutter.yaml\n\nlinter:\n  rules:\n    public_member_api_docs: false\n    library_private_type"
  },
  {
    "path": "example/android/.gitignore",
    "chars": 262,
    "preview": "gradle-wrapper.jar\n/.gradle\n/captures/\n/gradlew\n/gradlew.bat\n/local.properties\nGeneratedPluginRegistrant.java\n\n# Remembe"
  },
  {
    "path": "example/android/app/build.gradle",
    "chars": 2265,
    "preview": "def localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertie"
  },
  {
    "path": "example/android/app/release/output-metadata.json",
    "chars": 358,
    "preview": "{\n  \"version\": 2,\n  \"artifactType\": {\n    \"type\": \"APK\",\n    \"kind\": \"Directory\"\n  },\n  \"applicationId\": \"com.yuxiaor.fl"
  },
  {
    "path": "example/android/app/src/main/AndroidManifest.xml",
    "chars": 1946,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package="
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/App.kt",
    "chars": 404,
    "preview": "package com.yuxiaor.flutter.g_faraday_example\n\nimport android.app.Application\nimport com.yuxiaor.flutter.g_faraday.Farad"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/MainActivity.kt",
    "chars": 750,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.activity\n\nimport android.os.Bundle\nimport androidx.appcompat.app.AppCompat"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/SingleTaskFlutterActivity.kt",
    "chars": 241,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.activity\n\nimport com.yuxiaor.flutter.g_faraday.FaradayActivity\n\n// https:/"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/SingleTopFlutterActivity.kt",
    "chars": 240,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.activity\n\nimport com.yuxiaor.flutter.g_faraday.FaradayActivity\n\n// https:/"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/activity/splash/FirstFlutterActivity.kt",
    "chars": 1715,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.activity.splash\n\nimport android.content.Context\nimport android.os.Build\nim"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/FlutterToNativeActivity.kt",
    "chars": 799,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.basic\n\nimport android.content.Intent\nimport android.os.Bundle\nimport andro"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/Native2FlutterActivity.kt",
    "chars": 1644,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.basic\n\nimport android.content.Intent\nimport android.graphics.Color\nimport "
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/TabContainerActivity.kt",
    "chars": 3658,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.basic\n\nimport android.content.Intent\nimport android.os.Bundle\nimport andro"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/TransparentBackgroundFlutterActivity.kt",
    "chars": 437,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.basic\n\nimport android.content.Context\nimport android.graphics.Color\nimport"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/basic/fragments/NativeFragment.kt",
    "chars": 138,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.basic.fragments\n\nimport androidx.fragment.app.Fragment\n\nclass NativeFragme"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/faraday/CustomNavigator.kt",
    "chars": 2540,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.faraday\n\nimport android.app.Activity\nimport android.content.Intent\nimport "
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/fragment/TestFragment.kt",
    "chars": 1093,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.fragment\n\nimport android.os.Bundle\nimport android.view.LayoutInflater\nimpo"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/utils/ViewExt.kt",
    "chars": 957,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.utils\n\nimport android.content.res.Resources\nimport android.graphics.Outlin"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/widget/BaseDialog.kt",
    "chars": 1206,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.widget\n\nimport android.content.Context\nimport android.os.Bundle\nimport and"
  },
  {
    "path": "example/android/app/src/main/kotlin/com/yuxiaor/flutter/g_faraday_example/widget/NotificationDialog.kt",
    "chars": 1424,
    "preview": "package com.yuxiaor.flutter.g_faraday_example.widget\n\nimport android.annotation.SuppressLint\nimport android.content.Cont"
  },
  {
    "path": "example/android/app/src/main/res/anim/in_from_left.xml",
    "chars": 260,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "example/android/app/src/main/res/anim/in_from_right.xml",
    "chars": 259,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "example/android/app/src/main/res/anim/out_from_left.xml",
    "chars": 260,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "example/android/app/src/main/res/anim/out_from_right.xml",
    "chars": 259,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<translate xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android"
  },
  {
    "path": "example/android/app/src/main/res/color/check_primary_light.xml",
    "chars": 270,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<selector xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item a"
  },
  {
    "path": "example/android/app/src/main/res/drawable/launch_background.xml",
    "chars": 304,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item"
  },
  {
    "path": "example/android/app/src/main/res/drawable/tab_file.xml",
    "chars": 690,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "example/android/app/src/main/res/drawable/tab_home.xml",
    "chars": 780,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "example/android/app/src/main/res/drawable/tab_house.xml",
    "chars": 830,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "example/android/app/src/main/res/drawable/tab_msg.xml",
    "chars": 778,
    "preview": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n  "
  },
  {
    "path": "example/android/app/src/main/res/layout/activity_flutter2native.xml",
    "chars": 526,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmln"
  },
  {
    "path": "example/android/app/src/main/res/layout/activity_fragment.xml",
    "chars": 1873,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    andr"
  },
  {
    "path": "example/android/app/src/main/res/layout/activity_main.xml",
    "chars": 307,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmln"
  },
  {
    "path": "example/android/app/src/main/res/layout/activity_native2flutter.xml",
    "chars": 1255,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmln"
  },
  {
    "path": "example/android/app/src/main/res/layout/activity_tab_container.xml",
    "chars": 1873,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    andr"
  },
  {
    "path": "example/android/app/src/main/res/layout/dialog_notification.xml",
    "chars": 1129,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xm"
  },
  {
    "path": "example/android/app/src/main/res/layout/frag_test.xml",
    "chars": 549,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmln"
  },
  {
    "path": "example/android/app/src/main/res/navigation/nav_graph.xml",
    "chars": 1078,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<navigation xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:"
  },
  {
    "path": "example/android/app/src/main/res/values/colors.xml",
    "chars": 385,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#6200EE</color>\n    <color name=\"color"
  },
  {
    "path": "example/android/app/src/main/res/values/strings.xml",
    "chars": 804,
    "preview": "<resources>\n    <string name=\"back_button_title\">带参数返回</string>\n    <string name=\"native2flutter_tip\">从原生打开flutter只需要使用 "
  },
  {
    "path": "example/android/app/src/main/res/values/styles.xml",
    "chars": 2423,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar"
  },
  {
    "path": "example/android/app/src/main/res/values-v31/styles.xml",
    "chars": 335,
    "preview": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"SplashTheme\" parent=\"@android:style/Theme.Black.NoT"
  },
  {
    "path": "example/android/app/src/profile/AndroidManifest.xml",
    "chars": 345,
    "preview": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.yuxiaor.flutter.g_faraday_example\""
  },
  {
    "path": "example/android/build.gradle",
    "chars": 789,
    "preview": "buildscript {\n    ext.kotlin_version = '1.6.21'\n    repositories {\n        maven { url 'https://maven.aliyun.com/reposit"
  },
  {
    "path": "example/android/gradle/wrapper/gradle-wrapper.properties",
    "chars": 230,
    "preview": "#Wed Sep 02 15:37:58 CST 2020\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_"
  },
  {
    "path": "example/android/gradle.properties",
    "chars": 82,
    "preview": "org.gradle.jvmargs=-Xmx1536M\nandroid.useAndroidX=true\nandroid.enableJetifier=true\n"
  },
  {
    "path": "example/android/settings.gradle",
    "chars": 462,
    "preview": "include ':app'\n\ndef localPropertiesFile = new File(rootProject.projectDir, \"local.properties\")\ndef properties = new Prop"
  },
  {
    "path": "example/ios/.gitignore",
    "chars": 507,
    "preview": "*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/DerivedDat"
  },
  {
    "path": "example/ios/Flutter/AppFrameworkInfo.plist",
    "chars": 794,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Flutter/Debug.xcconfig",
    "chars": 106,
    "preview": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example/ios/Flutter/Release.xcconfig",
    "chars": 108,
    "preview": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example/ios/Podfile",
    "chars": 1356,
    "preview": "# Uncomment this line to define a global platform for your project\n platform :ios, '12.0'\n\n# CocoaPods analytics sends n"
  },
  {
    "path": "example/ios/Runner/AppDelegate.swift",
    "chars": 1991,
    "preview": "import UIKit\nimport g_faraday\n\n@UIApplicationMain\n@objc class AppDelegate: UIResponder, UIApplicationDelegate {\n    \n   "
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 2328,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"Icon-40.png\",\n      \"idiom\" : \"iphone\",\n      \"scale\" : \"2x\",\n      \"size\" : "
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/Contents.json",
    "chars": 63,
    "preview": "{\n  \"info\" : {\n    \"author\" : \"xcode\",\n    \"version\" : 1\n  }\n}\n"
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "chars": 373,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"Icon-20.png\",\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n"
  },
  {
    "path": "example/ios/Runner/Assets.xcassets/logo.imageset/Contents.json",
    "chars": 375,
    "preview": "{\n  \"images\" : [\n    {\n      \"filename\" : \"Icon-60.png\",\n      \"idiom\" : \"universal\",\n      \"scale\" : \"1x\"\n    },\n    {\n"
  },
  {
    "path": "example/ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "chars": 2377,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "example/ios/Runner/Base.lproj/Main.storyboard",
    "chars": 1558,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "example/ios/Runner/Faraday/FaradayCommon.swift",
    "chars": 1146,
    "preview": "//import Foundation\n//\n//  Created by faraday_cli on 2020-09-24 09:48:07.370618.\n//\n//    ___                   _\n//   /"
  },
  {
    "path": "example/ios/Runner/Faraday/FaradayNet.swift",
    "chars": 829,
    "preview": "import Foundation\n\n//  Created by faraday_cli on 2020-09-24 09:48:07.370618.\n//\n//    ___                   _\n//   / __\\"
  },
  {
    "path": "example/ios/Runner/Faraday/FaradayRoute.swift",
    "chars": 988,
    "preview": "//import Foundation\n//import g_faraday\n\n//  Created by faraday_cli on 2020-09-24 09:48:07.370618.\n//\n//    ___          "
  },
  {
    "path": "example/ios/Runner/GeneratedPluginRegistrant.h",
    "chars": 378,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#ifndef GeneratedPluginRegistrant_h\n#define GeneratedPlugin"
  },
  {
    "path": "example/ios/Runner/GeneratedPluginRegistrant.m",
    "chars": 433,
    "preview": "//\n//  Generated file. Do not edit.\n//\n\n// clang-format off\n\n#import \"GeneratedPluginRegistrant.h\"\n\n#if __has_include(<g"
  },
  {
    "path": "example/ios/Runner/Info.plist",
    "chars": 1616,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner/Runner-Bridging-Header.h",
    "chars": 38,
    "preview": "#import \"GeneratedPluginRegistrant.h\"\n"
  },
  {
    "path": "example/ios/Runner/ViewControllers/BaseViewController.swift",
    "chars": 204,
    "preview": "//\n//  BaseViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/12/8.\n//\n\nimport UIKit\n\nclass BaseViewControlle"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/Flutter2NativeViewController.swift",
    "chars": 612,
    "preview": "//\n//  Flutter2NativeViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/26.\n//\n\nimport UIKit\nimport g_fara"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/Flutter2NativeViewController.xib",
    "chars": 2938,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVe"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/Native2FlutterViewController.swift",
    "chars": 878,
    "preview": "//\n//  Native2FlutterViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/26.\n//\n\nimport UIKit\nimport g_fara"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/Native2FlutterViewController.xib",
    "chars": 6071,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.XIB\" version=\"3.0\" toolsVe"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/TabContainer/Tab1ViewController.swift",
    "chars": 660,
    "preview": "//\n//  Tab1ViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/27.\n//\n\nimport UIKit\nimport g_faraday\n\nclass"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/TabContainer/Tab2ViewController.swift",
    "chars": 663,
    "preview": "//\n//  Tab2ViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/27.\n//\n\nimport UIKit\nimport g_faraday\n\nclass"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/TabContainer/TabContainer.storyboard",
    "chars": 19894,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Basic/TabContainer/TabSplitViewController.swift",
    "chars": 973,
    "preview": "//\n//  TabSplitViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/12/25.\n//\n\nimport Foundation\nimport g_farad"
  },
  {
    "path": "example/ios/Runner/ViewControllers/MainavigationViewController.swift",
    "chars": 1292,
    "preview": "//\n//  MainavigationViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/26.\n//\n\nimport UIKit\nimport g_farad"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Others/NeedNavigationBarViewController.swift",
    "chars": 320,
    "preview": "//\n//  NeedNavigationBarViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/27.\n//\n\nimport UIKit\n\nclass Nee"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Others/NoNavigationBarViewController.swift",
    "chars": 506,
    "preview": "//\n//  NoNavigationBarViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/27.\n//\n\nimport UIKit\nimport g_far"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Others/Other.storyboard",
    "chars": 8789,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Splash/HomeFlutterViewController.swift",
    "chars": 1098,
    "preview": "//\n//  HomeFlutterViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/11/27.\n//\n\nimport UIKit\nimport g_faraday"
  },
  {
    "path": "example/ios/Runner/ViewControllers/Tab0ViewController.swift",
    "chars": 749,
    "preview": "//\n//  Tab0ViewController.swift\n//  Runner\n//\n//  Created by gix on 2020/9/4.\n//\n\nimport UIKit\nimport g_faraday\n\nclass F"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.pbxproj",
    "chars": 32636,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 51;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 135,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"self:\">\n   </FileRef"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "chars": 3185,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1300\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "example/ios/Runner.xcworkspace/contents.xcworkspacedata",
    "chars": 224,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "example/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example/lib/fluro_router.dart",
    "chars": 1176,
    "preview": "// // ignore: import_of_legacy_library_into_null_safe\n// import 'package:fluro/fluro.dart';\n// import 'package:g_faraday"
  },
  {
    "path": "example/lib/main.dart",
    "chars": 4283,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter_localizations/flutter_localizations.dart';\nimport 'pack"
  },
  {
    "path": "example/lib/main_fluro.dart",
    "chars": 2178,
    "preview": "// import 'package:flutter/cupertino.dart';\n// import 'package:g_faraday/g_faraday.dart';\n\n// import 'fluro_router.dart'"
  },
  {
    "path": "example/lib/main_get.dart",
    "chars": 3306,
    "preview": "// import 'package:flutter/cupertino.dart';\n// import 'package:flutter/material.dart';\n// import 'package:g_faraday/g_fa"
  },
  {
    "path": "example/lib/src/debug/debug.dart",
    "chars": 405,
    "preview": "//  Created by faraday_cli on 2020-09-24 09:48:07.370618.\n//\n//    ___                   _\n//   / __\\_ _ _ __ __ _  __| "
  },
  {
    "path": "example/lib/src/pages/example_page_scaffold.dart",
    "chars": 845,
    "preview": "import 'package:flutter/cupertino.dart';\n\nclass ExamplePageScaffold extends StatefulWidget {\n  final String? title;\n  fi"
  },
  {
    "path": "example/lib/src/pages/features/basic/basic.dart",
    "chars": 5211,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:g_faraday/g_faraday.dar"
  },
  {
    "path": "example/lib/src/pages/features/basic/pages/flutter_to_flutter.dart",
    "chars": 2004,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:g_faraday/g_faraday.dar"
  },
  {
    "path": "example/lib/src/pages/features/basic/pages/flutter_to_native.dart",
    "chars": 2350,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:g_faraday/g_faraday.dar"
  },
  {
    "path": "example/lib/src/pages/features/basic/pages/native_to_flutter.dart",
    "chars": 1194,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\n\nclass Native2FlutterPage extends State"
  },
  {
    "path": "example/lib/src/pages/features/basic/pages/tab_page.dart",
    "chars": 604,
    "preview": "import 'package:flutter/material.dart';\n\nclass TabPage extends StatefulWidget {\n  const TabPage({Key? key}) : super(key:"
  },
  {
    "path": "example/lib/src/pages/features/basic/pages/transparent_page.dart",
    "chars": 1795,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\n\nclass TransparentPage extends Stateful"
  },
  {
    "path": "example/lib/src/pages/features/notification/notification.dart",
    "chars": 2370,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:g_faraday/g_faraday.dart';\n\nimport '../../../utils/simple_locali"
  },
  {
    "path": "example/lib/src/pages/features/other/other.dart",
    "chars": 3553,
    "preview": "import 'dart:io';\n\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:g_fa"
  },
  {
    "path": "example/lib/src/pages/features/splash/splash.dart",
    "chars": 3411,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\n\nimport '../../../utils/simple_localiza"
  },
  {
    "path": "example/lib/src/pages/home_page.dart",
    "chars": 4464,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';"
  },
  {
    "path": "example/lib/src/utils/observer.dart",
    "chars": 694,
    "preview": "import 'package:flutter/material.dart';\n\nclass DemoObserver extends NavigatorObserver {\n  // 请使用 route.navigator 这个navig"
  },
  {
    "path": "example/lib/src/utils/simple_localizations.dart",
    "chars": 4262,
    "preview": "import 'package:flutter/foundation.dart';\nimport 'package:flutter/widgets.dart';\nimport 'package:g_faraday/g_faraday.dar"
  },
  {
    "path": "example/lib/src/widgets/action.dart",
    "chars": 1140,
    "preview": "import 'package:flutter/material.dart';\n\nclass FaradayAction extends StatelessWidget {\n  final Color? color;\n  final Wid"
  },
  {
    "path": "example/lib/src/widgets/section.dart",
    "chars": 1995,
    "preview": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\n\n// ignore: public_member_api_docs\nclas"
  },
  {
    "path": "example/pubspec.yaml",
    "chars": 2599,
    "preview": "name: g_faraday_example\ndescription: Demonstrates how to use the g_faraday plugin.\nversion: 1.0.0+23\n\n# The following li"
  },
  {
    "path": "example/test/widget_test.dart",
    "chars": 910,
    "preview": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester"
  },
  {
    "path": "example_objc_only/.gitignore",
    "chars": 732,
    "preview": "# Miscellaneous\n*.class\n*.log\n*.pyc\n*.swp\n.DS_Store\n.atom/\n.buildlog/\n.history\n.svn/\n\n# IntelliJ related\n*.iml\n*.ipr\n*.i"
  },
  {
    "path": "example_objc_only/.metadata",
    "chars": 306,
    "preview": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrade"
  },
  {
    "path": "example_objc_only/README.md",
    "chars": 2847,
    "preview": "# g_faraday Objective 集成\n\n## 创建 `FaradayHelper.swift`\n\n``` swift\n@objc class FaradayHelper: NSObject {\n    \n    @objc st"
  },
  {
    "path": "example_objc_only/ios/.gitignore",
    "chars": 542,
    "preview": "*.mode1v3\n*.mode2v3\n*.moved-aside\n*.pbxuser\n*.perspectivev3\n**/*sync/\n.sconsign.dblite\n.tags*\n**/.vagrant/\n**/DerivedDat"
  },
  {
    "path": "example_objc_only/ios/Flutter/AppFrameworkInfo.plist",
    "chars": 794,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example_objc_only/ios/Flutter/Debug.xcconfig",
    "chars": 106,
    "preview": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example_objc_only/ios/Flutter/Release.xcconfig",
    "chars": 108,
    "preview": "#include \"Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig\"\n#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "example_objc_only/ios/Podfile",
    "chars": 1312,
    "preview": "# Uncomment this line to define a global platform for your project\n# platform :ios, '9.0'\n\n# CocoaPods analytics sends n"
  },
  {
    "path": "example_objc_only/ios/Runner/AppDelegate.h",
    "chars": 103,
    "preview": "#import <Flutter/Flutter.h>\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : FlutterAppDelegate\n\n@end\n"
  },
  {
    "path": "example_objc_only/ios/Runner/AppDelegate.m",
    "chars": 1588,
    "preview": "#import \"AppDelegate.h\"\n#import \"Runner-Swift.h\"\n\n@import g_faraday;\n\n@interface AppDelegate (Faraday) <FFNavigationDele"
  },
  {
    "path": "example_objc_only/ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "chars": 2519,
    "preview": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n   "
  },
  {
    "path": "example_objc_only/ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "chars": 391,
    "preview": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n  "
  },
  {
    "path": "example_objc_only/ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "chars": 336,
    "preview": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in"
  },
  {
    "path": "example_objc_only/ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "chars": 2377,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard"
  },
  {
    "path": "example_objc_only/ios/Runner/Base.lproj/Main.storyboard",
    "chars": 2964,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3"
  },
  {
    "path": "example_objc_only/ios/Runner/DemoViewController.h",
    "chars": 207,
    "preview": "//\n//  DemoViewController.h\n//  Runner\n//\n//  Created by gix on 2021/2/26.\n//\n\n#import <UIKit/UIKit.h>\n\nNS_ASSUME_NONNUL"
  },
  {
    "path": "example_objc_only/ios/Runner/DemoViewController.m",
    "chars": 955,
    "preview": "//\n//  DemoViewController.m\n//  Runner\n//\n//  Created by gix on 2021/2/26.\n//\n\n#import \"DemoViewController.h\"\n\n@import g"
  },
  {
    "path": "example_objc_only/ios/Runner/FaradayHelper.swift",
    "chars": 1318,
    "preview": "//\n//  Test.swift\n//  Runner\n//\n//  Created by gix on 2021/2/25.\n//\n\nimport Foundation\nimport g_faraday\n\n@objc class Far"
  },
  {
    "path": "example_objc_only/ios/Runner/Info.plist",
    "chars": 1537,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example_objc_only/ios/Runner/Runner-Bridging-Header.h",
    "chars": 104,
    "preview": "//\n//  Use this file to import your target's public headers that you would like to expose to Swift.\n//\n\n"
  },
  {
    "path": "example_objc_only/ios/Runner/main.m",
    "chars": 226,
    "preview": "#import <Flutter/Flutter.h>\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char* argv[]) {\n  @autor"
  },
  {
    "path": "example_objc_only/ios/Runner.xcodeproj/project.pbxproj",
    "chars": 24967,
    "preview": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 51;\n\tobjects = {\n\n/* Begin PBXBuildFile section *"
  },
  {
    "path": "example_objc_only/ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "chars": 152,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "example_objc_only/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example_objc_only/ios/Runner.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example_objc_only/ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "chars": 3185,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"1240\"\n   version = \"1.3\">\n   <BuildAction\n      "
  },
  {
    "path": "example_objc_only/ios/Runner.xcworkspace/contents.xcworkspacedata",
    "chars": 224,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodepr"
  },
  {
    "path": "example_objc_only/ios/Runner.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist",
    "chars": 238,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example_objc_only/ios/Runner.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings",
    "chars": 226,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/P"
  },
  {
    "path": "example_objc_only/lib/main.dart",
    "chars": 758,
    "preview": "import 'package:flutter/material.dart';\nimport 'package:g_faraday/g_faraday.dart';\n\nvoid main() {\n  runApp(const DemoApp"
  },
  {
    "path": "example_objc_only/pubspec.yaml",
    "chars": 2923,
    "preview": "name: g_faraday_obj_demo\ndescription: A new Flutter project.\n\n# The following line prevents the package from being accid"
  },
  {
    "path": "example_objc_only/test/widget_test.dart",
    "chars": 1,
    "preview": "\n"
  },
  {
    "path": "g_faraday.iml",
    "chars": 949,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<module type=\"JAVA_MODULE\" version=\"4\">\n  <component name=\"NewModuleRootManager\" "
  },
  {
    "path": "ios/.gitignore",
    "chars": 398,
    "preview": ".idea/\n.vagrant/\n.sconsign.dblite\n.svn/\n\n.DS_Store\n*.swp\nprofile\n\nDerivedData/\nbuild/\nGeneratedPluginRegistrant.h\nGenera"
  },
  {
    "path": "ios/Assets/.gitkeep",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "ios/Classes/Faraday.swift",
    "chars": 11354,
    "preview": "//\n//  Faraday.swift\n//  g_faraday\n//\n//  Created by gix on 2020/9/2.\n//\n\nimport Foundation\nimport Flutter\n\n/// Manager "
  },
  {
    "path": "ios/Classes/FaradayExtended.swift",
    "chars": 1250,
    "preview": "//\n//  FaradayExtend.swift\n//  g_faraday\n//\n//  Created by gix on 2020/9/21.\n//\n\nimport Foundation\n\npublic struct Farada"
  },
  {
    "path": "ios/Classes/FaradayFlutterViewController.swift",
    "chars": 5435,
    "preview": "//\n//  FaradayFlutterViewController.swift\n//  g_faraday\n//\n//  Created by gix on 2020/9/2.\n//\n\nimport UIKit\nimport Flutt"
  },
  {
    "path": "ios/Classes/FlutterEngine+Identifier.swift",
    "chars": 826,
    "preview": "//\n//  FlutterEngine+Identifier.swift\n//  g_faraday\n//\n//  Created by gix on 2020/11/19.\n//\n\nimport Flutter\n\nprivate str"
  },
  {
    "path": "ios/Classes/GFaradayPlugin.h",
    "chars": 86,
    "preview": "#import <Flutter/Flutter.h>\n\n@interface GFaradayPlugin : NSObject<FlutterPlugin>\n@end\n"
  }
]

// ... and 24 more files (download for full content)

About this extraction

This page contains the full source code of the gfaraday/g_faraday GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 224 files (384.1 KB), approximately 110.4k tokens, and a symbol index with 175 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!