[
  {
    "path": ".gitignore",
    "content": "# Miscellaneous\n*.class\n*.lock\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*.iws\n.idea/\n\n# Visual Studio Code related\n.vscode/\n\n# Flutter/Dart/Pub related\n**/doc/api/\n.dart_tool/\n.flutter-plugins\n.packages\n.pub-cache/\n.pub/\nbuild/\n\n# Android related\n**/android/**/gradle-wrapper.jar\n**/android/.gradle\n**/android/captures/\n**/android/gradlew\n**/android/gradlew.bat\n**/android/local.properties\n**/android/**/GeneratedPluginRegistrant.java\n\n# iOS/XCode related\n**/ios/**/*.mode1v3\n**/ios/**/*.mode2v3\n**/ios/**/*.moved-aside\n**/ios/**/*.pbxuser\n**/ios/**/*.perspectivev3\n**/ios/**/*sync/\n**/ios/**/.sconsign.dblite\n**/ios/**/.tags*\n**/ios/**/.vagrant/\n**/ios/**/DerivedData/\n**/ios/**/Icon?\n**/ios/**/Pods/\n**/ios/**/.symlinks/\n**/ios/**/profile\n**/ios/**/xcuserdata\n**/ios/.generated/\n**/ios/Flutter/App.framework\n**/ios/Flutter/Flutter.framework\n**/ios/Flutter/Generated.xcconfig\n**/ios/Flutter/app.flx\n**/ios/Flutter/app.zip\n**/ios/Flutter/flutter_assets/\n**/ios/ServiceDefinitions.json\n**/ios/Runner/GeneratedPluginRegistrant.*\n\n# Exceptions to above rules.\n!**/ios/**/default.mode1v3\n!**/ios/**/default.mode2v3\n!**/ios/**/default.pbxuser\n!**/ios/**/default.perspectivev3\n!/packages/flutter_tools/test/data/dart_dependencies_test/**/.packages\n"
  },
  {
    "path": ".metadata",
    "content": "# This file tracks properties of this Flutter project.\n# Used by Flutter tool to assess capabilities and perform upgrades etc.\n#\n# This file should be version controlled and should not be manually edited.\n\nversion:\n  revision: 5391447fae6209bb21a89e6a5a6583cac1af9b4b\n  channel: stable\n\nproject_type: app\n"
  },
  {
    "path": "README.md",
    "content": "## Flutter学习资源汇总持续更新中......\n\n- [Flutter官方网站](https://flutter.dev/)\n- [Flutter中文网](https://flutterchina.club/)\n- wendux的[Flutter实战](https://book.flutterchina.club/)\n- Flutter官方example[flutter_gallery](https://github.com/flutter/flutter/tree/master/examples/flutter_gallery)\n- [阿里巴巴咸鱼团队系列文章](https://www.yuque.com/xytech/flutter)\n- [阿里巴巴flutter-go](https://github.com/alibaba/flutter-go)，flutter 开发者帮助 APP，包含 flutter 常用 140+ 组件的demo 演示与中文文档\n- [awesome-flutter](https://github.com/Solido/awesome-flutter)包含居多优秀的Flutter库，工具，教程，文章等\n- [玩Android跨平台项目](https://www.wanandroid.com/project/list/1?cid=402)\n- 非常有用的[Json转Model插件](https://github.com/neverwoodsS/idea_dart_json_format)\n- [Flutter-Notebook](https://github.com/OpenFlutter/Flutter-Notebook),提供了很多优秀样例和Demo\n- [Flutter-plugins](https://github.com/flutter/plugins),flutter官方插件，提供了众多优秀插件\n- 掘金作者[恋猫de小郭系列文章](https://juejin.im/user/582aca2ba22b9d006b59ae68/posts)\n## 前言\n\n- 这是一款使用Flutter写的WanAndroid客户端应用，在Android和IOS都完美运行\n- ~~可以用来入门Flutter，简单明了，适合初学者~~  \n- [项目完全开源](https://github.com/ngu2008/wanandroid_ngu)，如果本项目确实能够帮助到你学习Flutter，谢谢start一下，有问题请提交Issues,我会及时回复\n\n## 环境搭建\n\n- 根据[Flutter中文网](https://flutterchina.club/get-started/install)搭建开发环境，使用Android Studio安装Flutter插件，点击pubspec.yaml的package get，然后运行\n\n##  APP下载\n\n- Android[点击下载](https://www.pgyer.com/haFL)，或者扫描下方二维码下载\n\n  ![](screenshot/a7.png)\n  \n- 暂不支持IOS版本下载，请自行clone项目代码运行。\n\n## App目录结构\n>- |--lib\n>    - |-- main (入口类)\n>    - |-- loading (启动页)\n>    - |-- splash_screen (引导页)\n>    - |-- util (工具类)\n>    - |-- base (基类，封装基类BaseWidget和BaseWidgetState)\n>    - |-- http (网络请求相关类)\n>    - |-- common (常用类)\n>    - |-- event (事件类)\n>    - |-- model (实体类)\n>    - |-- ui (界面相关)\n>    - |-- util (工具类)\n\n## 功能介绍\n\n#### V1.5版本\n\n- 常用网站增加数据库[sqflite](https://pub.flutter-io.cn/packages/sqflite)功能\n- 修复注册登录按钮颜色与主题色不一致的问题\n\n#### V1.4版本\n\n- 增加切换主题\n- 封装基类BaseWidget和BaseWidgetState\n- 显示隐藏AppBar\n- 增加状态页切换（数据加载中，数据加载失败，空数据）\n\n#### V1.3版本\n\n- 新增搜索和搜索结果列表\n- 新增页面正在加载...\n- 整个界面UI风格修改\n\n#### V1.2版本\n\n- 新增福利，妹子图，使用[photo_view](https://pub.flutter-io.cn/packages/photo_view)，你懂得\n- 新增分享[share](https://pub.flutter-io.cn/packages/share)\n- 新增常用网站\n- 新增关于作者，退出登录\n\n#### V1.1版本\n\n- 新增引导页[flutter-intro-slider](https://github.com/duytq94/flutter-intro-slider)\n- 列表页悬浮FloatingActionButton,点击迅速回到顶部\n- 新增注册、登录、我的收藏，增加侧滑抽屉，详见截图\n\n#### V1.0版本\n- 项目首页、知识体系、公众号、导航、项目、各个页面，和详情页面\n- 主要的UI包括首页轮播图和列表，体系流式布局，公众号导航TabBar,以及下拉刷新和加载更多\n- 轮播图使用的是开源库[flutter_swiper](https://github.com/best-flutter/flutter_swiper)\n- 网络请求使用的是开源库[dio](https://github.com/flutterchina/dio)\n\n## 我的主页\n - [掘金](https://juejin.im/user/5b319afee51d455e2c32fb5b/posts)\n - [CSDN](https://blog.csdn.net/zw2008224044)\n\n## 应用截图\n\n| <img src=\"/screenshot/b6.jpg\" width=\"280\" alt=\"福利，妹子图\"/> | <img src=\"/screenshot/b2.jpg\" width=\"280\" alt=\"导航页\"/> | <img src=\"/screenshot/b1.jpg\" width=\"280\" alt=\"导航页\"/> |\n| :--: | :--: | :--: |\n| 福利，妹子图 | 导航页 | 导航页 |\n\n| <img src=\"/screenshot/a0.png\" width=\"280\" height=\"498\" alt=\"登录\"/> | <img src=\"/screenshot/a01.png\" width=\"280\" height=\"498\" alt=\"注册\"/> | <img src=\"/screenshot/b4.jpg\" width=\"280\" height=\"498\" alt=\"分享\"/> |\n| :--: | :--: | :--: |\n| 登录 | 注册 | 分享 |\n\n| <img src=\"/screenshot/b5.jpg\" width=\"280\" height=\"498\" alt=\"关于作者\"/> | <img src=\"/screenshot/b3.png\" width=\"280\" height=\"498\" alt=\"常用网站\"/> | <img src=\"/screenshot/a02.jpg\" width=\"280\" height=\"498\" alt=\"侧滑抽屉\"/> |\n| :--: | :--: | :--: |\n| 关于作者 | 常用网站 | 侧滑抽屉 |\n\n| <img src=\"/screenshot/a1.jpg\" width=\"280\" height=\"498\" alt=\"首页\"/> | <img src=\"/screenshot/a2.jpg\" width=\"280\" height=\"498\" alt=\"体系\"/> |  <img src=\"/screenshot/a3.jpg\" width=\"280\" height=\"498\" alt=\"公众号\"/> |\n| :--: | :--: | :--: |\n| 首页 | 体系 | 公众号 |\n\n| <img src=\"/screenshot/a4.jpg\" width=\"280\" height=\"498\" alt=\"导航\"/> | <img src=\"/screenshot/a5.jpg\" width=\"280\" height=\"498\" alt=\"项目\"/> | <img src=\"/screenshot/a6.jpg\" width=\"280\" height=\"498\" alt=\"基础知识\"/> |\n| :--: | :--: | :--: |\n| 导航 | 项目 | 基础知识 |\n\n| <img src=\"/screenshot/a8.jpg\" width=\"280\" height=\"498\" alt=\"我的收藏\"/> | <img src=\"/screenshot/a9.jpg\" width=\"280\" height=\"498\" alt=\"详情页\"/> |<img src=\"/screenshot/a10.jpg\" width=\"280\" height=\"498\" alt=\"详情页\"/> |\n| :--: | :--: |:--: |\n| 我的收藏 | 详情页 | 热门搜索 |\n\n| <img src=\"/screenshot/a11.jpg\" width=\"280\" height=\"498\" alt=\"搜索列表\"/> | <img src=\"/screenshot/b7.png\" width=\"280\" height=\"498\" alt=\"正在加载\"/>| <img src=\"/screenshot/b8.png\" width=\"280\" height=\"498\" alt=\"加载错误\"/>|\n| :--: | :--: |:--: |\n| 搜索列表 | 正在加载 |加载错误 |\n\n| <img src=\"/screenshot/b9.png\" width=\"280\" height=\"498\" alt=\"正在加载\"/>| <img src=\"/screenshot/b10.png\" width=\"280\" height=\"498\" alt=\"正在加载\"/> | |\n| :--: | :--: |:--: |\n| 数据为空 | 切换主题 |  |\n\n##  感谢\n\n1. 特别感谢github开源作者[shijiacheng](https://github.com/shijiacheng/wanandroid_flutter)\n2. 感谢鸿洋大神及[玩Android官网](http://www.wanandroid.com/)提供的[开放API](http://www.wanandroid.com/blog/show/2)\n3. 感谢[干货集中营 API](http://gank.io/api)\n\n## 使用开源库\n\n- [shared_preferences](https://pub.dartlang.org/packages/shared_preferences)\n- [fluttertoast](https://pub.dartlang.org/packages/fluttertoast)\n- [share](https://pub.flutter-io.cn/packages/share)\n- [flutter_swiper](https://pub.flutter-io.cn/packages/flutter_swiper)\n- [cupertino_icons](https://pub.flutter-io.cn/packages/cupertino_icons)\n- [flutter_webview_plugin](https://pub.flutter-io.cn/packages/flutter_webview_plugin)\n- [dio](https://pub.flutter-io.cn/packages/dio)\n- [flutter-intro-slider](https://github.com/duytq94/flutter-intro-slider)\n- [photo_view](https://pub.flutter-io.cn/packages/photo_view)\n- [sqflite](https://pub.flutter-io.cn/packages/sqflite)\n- [path_provider ](https://pub.flutter-io.cn/packages/path_provider#-installing-tab-)\n\n## 欢迎关注我的微信公众号\n\n  ![](screenshot/wechat.jpg)"
  },
  {
    "path": "android/app/build.gradle",
    "content": "def localProperties = new Properties()\ndef localPropertiesFile = rootProject.file('local.properties')\nif (localPropertiesFile.exists()) {\n    localPropertiesFile.withReader('UTF-8') { reader ->\n        localProperties.load(reader)\n    }\n}\n\ndef flutterRoot = localProperties.getProperty('flutter.sdk')\nif (flutterRoot == null) {\n    throw new GradleException(\"Flutter SDK not found. Define location with flutter.sdk in the local.properties file.\")\n}\n\ndef flutterVersionCode = localProperties.getProperty('flutter.versionCode')\nif (flutterVersionCode == null) {\n    flutterVersionCode = '1'\n}\n\ndef flutterVersionName = localProperties.getProperty('flutter.versionName')\nif (flutterVersionName == null) {\n    flutterVersionName = '1.0'\n}\n\n\napply plugin: 'com.android.application'\napply from: \"$flutterRoot/packages/flutter_tools/gradle/flutter.gradle\"\n\ndef keystorePropertiesFile = rootProject.file(\"key.properties\")\ndef keystoreProperties = new Properties()\nkeystoreProperties.load(new FileInputStream(keystorePropertiesFile))\n\nandroid {\n    compileSdkVersion 28\n\n    lintOptions {\n        disable 'InvalidPackage'\n    }\n\n    defaultConfig {\n        // TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).\n        applicationId \"com.ngu.wanandroidngu\"\n        minSdkVersion 16\n        targetSdkVersion 28\n        versionCode flutterVersionCode.toInteger()\n        versionName flutterVersionName\n        testInstrumentationRunner \"androidx.test.runner.AndroidJUnitRunner\"\n        multiDexEnabled true\n    }\n\n    signingConfigs {\n        release {\n            keyAlias keystoreProperties['keyAlias']\n            keyPassword keystoreProperties['keyPassword']\n            storeFile file(keystoreProperties['storeFile'])\n            storePassword keystoreProperties['storePassword']\n        }\n    }\n    buildTypes {\n        release {\n            signingConfig signingConfigs.release\n        }\n    }\n}\n\n\nflutter {\n    source '../..'\n}\n\ndependencies {\n    testImplementation 'junit:junit:4.12'\n    androidTestImplementation 'androidx.test:runner:1.1.0'\n    androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0'\n}\n"
  },
  {
    "path": "android/app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.ngu.wanandroidngu\">\n\n    <!-- The INTERNET permission is required for development. Specifically,\n         flutter needs it to communicate with the running application\n         to allow setting breakpoints, to provide hot reload, etc.\n    -->\n    <uses-permission android:name=\"android.permission.INTERNET\"/>\n\n    <!-- io.flutter.app.FlutterApplication is an android.app.Application that\n         calls FlutterMain.startInitialization(this); in its onCreate method.\n         In most cases you can leave this as-is, but you if you want to provide\n         additional functionality it is fine to subclass or reimplement\n         FlutterApplication and put your custom class here. -->\n    <application\n        android:name=\"io.flutter.app.FlutterApplication\"\n        android:label=\"玩安卓ngu\"\n        android:icon=\"@mipmap/sun\">\n        <activity\n            android:name=\".MainActivity\"\n            android:launchMode=\"singleTop\"\n            android:theme=\"@style/LaunchTheme\"\n            android:configChanges=\"orientation|keyboardHidden|keyboard|screenSize|locale|layoutDirection|fontScale|screenLayout|density\"\n            android:hardwareAccelerated=\"true\"\n            android:windowSoftInputMode=\"adjustResize\">\n            <!-- This keeps the window background of the activity showing\n                 until Flutter renders its first frame. It can be removed if\n                 there is no splash screen (such as the default splash screen\n                 defined in @style/LaunchTheme). -->\n            <meta-data\n                android:name=\"io.flutter.app.android.SplashScreenUntilFirstFrame\"\n                android:value=\"true\" />\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\"/>\n                <category android:name=\"android.intent.category.LAUNCHER\"/>\n            </intent-filter>\n        </activity>\n    </application>\n</manifest>\n"
  },
  {
    "path": "android/app/src/main/java/com/ngu/wanandroidngu/MainActivity.java",
    "content": "package com.ngu.wanandroidngu;\n\nimport android.os.Bundle;\nimport io.flutter.app.FlutterActivity;\nimport io.flutter.plugins.GeneratedPluginRegistrant;\n\npublic class MainActivity extends FlutterActivity {\n  @Override\n  protected void onCreate(Bundle savedInstanceState) {\n    super.onCreate(savedInstanceState);\n    GeneratedPluginRegistrant.registerWith(this);\n  }\n}\n"
  },
  {
    "path": "android/app/src/main/res/drawable/launch_background.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<!-- Modify this file to customize your launch splash screen -->\n<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:drawable=\"@android:color/white\" />\n\n    <!-- You can insert your own image assets here -->\n    <!-- <item>\n        <bitmap\n            android:gravity=\"center\"\n            android:src=\"@mipmap/launch_image\" />\n    </item> -->\n</layer-list>\n"
  },
  {
    "path": "android/app/src/main/res/values/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <style name=\"LaunchTheme\" parent=\"@android:style/Theme.Black.NoTitleBar\">\n        <!-- Show a splash screen on the activity. Automatically removed when\n             Flutter draws its first frame -->\n        <item name=\"android:windowBackground\">@drawable/launch_background</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "android/build.gradle",
    "content": "buildscript {\n    repositories {\n        google()\n        jcenter()\n    }\n\n    dependencies {\n        classpath 'com.android.tools.build:gradle:3.2.1'\n    }\n}\n\nallprojects {\n    repositories {\n        google()\n        jcenter()\n    }\n}\n\nrootProject.buildDir = '../build'\nsubprojects {\n    project.buildDir = \"${rootProject.buildDir}/${project.name}\"\n}\nsubprojects {\n    project.evaluationDependsOn(':app')\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "android/gradle/wrapper/gradle-wrapper.properties",
    "content": "#Fri Jun 23 08:50:38 CEST 2017\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-4.10.2-all.zip\n"
  },
  {
    "path": "android/gradle.properties",
    "content": "android.enableJetifier=true\nandroid.useAndroidX=true\norg.gradle.jvmargs=-Xmx1536M\n"
  },
  {
    "path": "android/key.properties",
    "content": "storePassword=wandroid_ngu\nkeyPassword=wandroid_ngu\nkeyAlias=wandroid_ngu\nstoreFile=../wandroid_ngu.jks"
  },
  {
    "path": "android/settings.gradle",
    "content": "include ':app'\n\ndef flutterProjectRoot = rootProject.projectDir.parentFile.toPath()\n\ndef plugins = new Properties()\ndef pluginsFile = new File(flutterProjectRoot.toFile(), '.flutter-plugins')\nif (pluginsFile.exists()) {\n    pluginsFile.withReader('UTF-8') { reader -> plugins.load(reader) }\n}\n\nplugins.each { name, path ->\n    def pluginDirectory = flutterProjectRoot.resolve(path).resolve('android').toFile()\n    include \":$name\"\n    project(\":$name\").projectDir = pluginDirectory\n}\n"
  },
  {
    "path": "interview.md",
    "content": "# 一道面试题\n\n> 分享一道面试题，结果有点出乎意料\n\n代码如下：输出结果是什么？\n\n    public class Test {\n\n    public static void main(String[] args) {\n        Set<Short> stack = new HashSet<>();\n        for (Short i = 0; i < 100; i++) {\n            stack.add(i);\n            stack.remove(i - 1);\n        }\n        System.out.println(stack.size());\n    }\n\n- 答案是100，i-1这里用到了隐式类型转换i-1会转成int型的减法，所以在remove时，根本没有那个对象，所以无论怎么调stack.remove(i-1)都不会有元素移出,所以答案是100."
  },
  {
    "path": "ios/Flutter/AppFrameworkInfo.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n  <key>CFBundleDevelopmentRegion</key>\n  <string>en</string>\n  <key>CFBundleExecutable</key>\n  <string>App</string>\n  <key>CFBundleIdentifier</key>\n  <string>io.flutter.flutter.app</string>\n  <key>CFBundleInfoDictionaryVersion</key>\n  <string>6.0</string>\n  <key>CFBundleName</key>\n  <string>App</string>\n  <key>CFBundlePackageType</key>\n  <string>FMWK</string>\n  <key>CFBundleShortVersionString</key>\n  <string>1.0</string>\n  <key>CFBundleSignature</key>\n  <string>????</string>\n  <key>CFBundleVersion</key>\n  <string>1.0</string>\n  <key>MinimumOSVersion</key>\n  <string>8.0</string>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Flutter/Debug.xcconfig",
    "content": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Flutter/Release.xcconfig",
    "content": "#include \"Generated.xcconfig\"\n"
  },
  {
    "path": "ios/Runner/AppDelegate.h",
    "content": "#import <Flutter/Flutter.h>\n#import <UIKit/UIKit.h>\n\n@interface AppDelegate : FlutterAppDelegate\n\n@end\n"
  },
  {
    "path": "ios/Runner/AppDelegate.m",
    "content": "#include \"AppDelegate.h\"\n#include \"GeneratedPluginRegistrant.h\"\n\n@implementation AppDelegate\n\n- (BOOL)application:(UIApplication *)application\n    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {\n  [GeneratedPluginRegistrant registerWithRegistry:self];\n  // Override point for customization after application launch.\n  return [super application:application didFinishLaunchingWithOptions:launchOptions];\n}\n\n@end\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-20x20@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-29x29@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-40x40@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"60x60\",\n      \"idiom\" : \"iphone\",\n      \"filename\" : \"Icon-App-60x60@3x.png\",\n      \"scale\" : \"3x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"20x20\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-20x20@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"29x29\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-29x29@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"40x40\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-40x40@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@1x.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"size\" : \"76x76\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-76x76@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"83.5x83.5\",\n      \"idiom\" : \"ipad\",\n      \"filename\" : \"Icon-App-83.5x83.5@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"size\" : \"1024x1024\",\n      \"idiom\" : \"ios-marketing\",\n      \"filename\" : \"Icon-App-1024x1024@1x.png\",\n      \"scale\" : \"1x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/Contents.json",
    "content": "{\n  \"images\" : [\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage.png\",\n      \"scale\" : \"1x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@2x.png\",\n      \"scale\" : \"2x\"\n    },\n    {\n      \"idiom\" : \"universal\",\n      \"filename\" : \"LaunchImage@3x.png\",\n      \"scale\" : \"3x\"\n    }\n  ],\n  \"info\" : {\n    \"version\" : 1,\n    \"author\" : \"xcode\"\n  }\n}\n"
  },
  {
    "path": "ios/Runner/Assets.xcassets/LaunchImage.imageset/README.md",
    "content": "# Launch Screen Assets\n\nYou can customize the launch screen with your own desired assets by replacing the image files in this directory.\n\nYou can also do it by opening your Flutter project's Xcode project with `open ios/Runner.xcworkspace`, selecting `Runner/Assets.xcassets` in the Project Navigator and dropping in the desired images."
  },
  {
    "path": "ios/Runner/Base.lproj/LaunchScreen.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<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\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"12089\"/>\n    </dependencies>\n    <scenes>\n        <!--View Controller-->\n        <scene sceneID=\"EHf-IW-A2E\">\n            <objects>\n                <viewController id=\"01J-lp-oVM\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"Ydg-fD-yQy\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"xbc-2k-c8Z\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"Ze5-6b-2t3\">\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <subviews>\n                            <imageView opaque=\"NO\" clipsSubviews=\"YES\" multipleTouchEnabled=\"YES\" contentMode=\"center\" image=\"LaunchImage\" translatesAutoresizingMaskIntoConstraints=\"NO\" id=\"YRO-k0-Ey4\">\n                            </imageView>\n                        </subviews>\n                        <color key=\"backgroundColor\" red=\"1\" green=\"1\" blue=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"sRGB\"/>\n                        <constraints>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerX\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerX\" id=\"1a2-6s-vTC\"/>\n                            <constraint firstItem=\"YRO-k0-Ey4\" firstAttribute=\"centerY\" secondItem=\"Ze5-6b-2t3\" secondAttribute=\"centerY\" id=\"4X2-HB-R7a\"/>\n                        </constraints>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"iYj-Kq-Ea1\" userLabel=\"First Responder\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n            <point key=\"canvasLocation\" x=\"53\" y=\"375\"/>\n        </scene>\n    </scenes>\n    <resources>\n        <image name=\"LaunchImage\" width=\"168\" height=\"185\"/>\n    </resources>\n</document>\n"
  },
  {
    "path": "ios/Runner/Base.lproj/Main.storyboard",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n<document type=\"com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB\" version=\"3.0\" toolsVersion=\"10117\" systemVersion=\"15F34\" targetRuntime=\"iOS.CocoaTouch\" propertyAccessControl=\"none\" useAutolayout=\"YES\" useTraitCollections=\"YES\" initialViewController=\"BYZ-38-t0r\">\n    <dependencies>\n        <deployment identifier=\"iOS\"/>\n        <plugIn identifier=\"com.apple.InterfaceBuilder.IBCocoaTouchPlugin\" version=\"10085\"/>\n    </dependencies>\n    <scenes>\n        <!--Flutter View Controller-->\n        <scene sceneID=\"tne-QT-ifu\">\n            <objects>\n                <viewController id=\"BYZ-38-t0r\" customClass=\"FlutterViewController\" sceneMemberID=\"viewController\">\n                    <layoutGuides>\n                        <viewControllerLayoutGuide type=\"top\" id=\"y3c-jy-aDJ\"/>\n                        <viewControllerLayoutGuide type=\"bottom\" id=\"wfy-db-euE\"/>\n                    </layoutGuides>\n                    <view key=\"view\" contentMode=\"scaleToFill\" id=\"8bC-Xf-vdC\">\n                        <rect key=\"frame\" x=\"0.0\" y=\"0.0\" width=\"600\" height=\"600\"/>\n                        <autoresizingMask key=\"autoresizingMask\" widthSizable=\"YES\" heightSizable=\"YES\"/>\n                        <color key=\"backgroundColor\" white=\"1\" alpha=\"1\" colorSpace=\"custom\" customColorSpace=\"calibratedWhite\"/>\n                    </view>\n                </viewController>\n                <placeholder placeholderIdentifier=\"IBFirstResponder\" id=\"dkx-z0-nzr\" sceneMemberID=\"firstResponder\"/>\n            </objects>\n        </scene>\n    </scenes>\n</document>\n"
  },
  {
    "path": "ios/Runner/Info.plist",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n\t<key>CFBundleDevelopmentRegion</key>\n\t<string>en</string>\n\t<key>CFBundleExecutable</key>\n\t<string>$(EXECUTABLE_NAME)</string>\n\t<key>CFBundleIdentifier</key>\n\t<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>\n\t<key>CFBundleInfoDictionaryVersion</key>\n\t<string>6.0</string>\n\t<key>CFBundleName</key>\n\t<string>wanandroid_ngu</string>\n\t<key>CFBundlePackageType</key>\n\t<string>APPL</string>\n\t<key>CFBundleShortVersionString</key>\n\t<string>$(FLUTTER_BUILD_NAME)</string>\n\t<key>CFBundleSignature</key>\n\t<string>????</string>\n\t<key>CFBundleVersion</key>\n\t<string>$(FLUTTER_BUILD_NUMBER)</string>\n\t<key>LSRequiresIPhoneOS</key>\n\t<true/>\n\t<key>UILaunchStoryboardName</key>\n\t<string>LaunchScreen</string>\n\t<key>UIMainStoryboardFile</key>\n\t<string>Main</string>\n\t<key>UISupportedInterfaceOrientations</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UISupportedInterfaceOrientations~ipad</key>\n\t<array>\n\t\t<string>UIInterfaceOrientationPortrait</string>\n\t\t<string>UIInterfaceOrientationPortraitUpsideDown</string>\n\t\t<string>UIInterfaceOrientationLandscapeLeft</string>\n\t\t<string>UIInterfaceOrientationLandscapeRight</string>\n\t</array>\n\t<key>UIViewControllerBasedStatusBarAppearance</key>\n\t<false/>\n</dict>\n</plist>\n"
  },
  {
    "path": "ios/Runner/main.m",
    "content": "#import <Flutter/Flutter.h>\n#import <UIKit/UIKit.h>\n#import \"AppDelegate.h\"\n\nint main(int argc, char* argv[]) {\n  @autoreleasepool {\n    return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));\n  }\n}\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.pbxproj",
    "content": "// !$*UTF8*$!\n{\n\tarchiveVersion = 1;\n\tclasses = {\n\t};\n\tobjectVersion = 46;\n\tobjects = {\n\n/* Begin PBXBuildFile section */\n\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };\n\t\t2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */ = {isa = PBXBuildFile; fileRef = 2D5378251FAA1A9400D5DBA9 /* flutter_assets */; };\n\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };\n\t\t3B80C3941E831B6300D905FE /* App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; };\n\t\t3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 3B80C3931E831B6300D905FE /* App.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };\n\t\t9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; };\n\t\t9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 9740EEBA1CF902C7004384FC /* Flutter.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };\n\t\t9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */ = {isa = PBXBuildFile; fileRef = 9740EEB21CF90195004384FC /* Debug.xcconfig */; };\n\t\t978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */; };\n\t\t97C146F31CF9000F007C117D /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 97C146F21CF9000F007C117D /* main.m */; };\n\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };\n\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };\n\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };\n/* End PBXBuildFile section */\n\n/* Begin PBXCopyFilesBuildPhase section */\n\t\t9705A1C41CF9048500538489 /* Embed Frameworks */ = {\n\t\t\tisa = PBXCopyFilesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tdstPath = \"\";\n\t\t\tdstSubfolderSpec = 10;\n\t\t\tfiles = (\n\t\t\t\t3B80C3951E831B6300D905FE /* App.framework in Embed Frameworks */,\n\t\t\t\t9705A1C71CF904A300538489 /* Flutter.framework in Embed Frameworks */,\n\t\t\t);\n\t\t\tname = \"Embed Frameworks\";\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXCopyFilesBuildPhase section */\n\n/* Begin PBXFileReference section */\n\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = \"<group>\"; };\n\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = \"<group>\"; };\n\t\t2D5378251FAA1A9400D5DBA9 /* flutter_assets */ = {isa = PBXFileReference; lastKnownFileType = folder; name = flutter_assets; path = Flutter/flutter_assets; sourceTree = SOURCE_ROOT; };\n\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = \"<group>\"; };\n\t\t3B80C3931E831B6300D905FE /* App.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = App.framework; path = Flutter/App.framework; sourceTree = \"<group>\"; };\n\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = \"<group>\"; };\n\t\t7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = \"<group>\"; };\n\t\t7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = \"<group>\"; };\n\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = \"<group>\"; };\n\t\t9740EEBA1CF902C7004384FC /* Flutter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Flutter.framework; path = Flutter/Flutter.framework; sourceTree = \"<group>\"; };\n\t\t97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };\n\t\t97C146F21CF9000F007C117D /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = \"<group>\"; };\n\t\t97C146FB1CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = \"<group>\"; };\n\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = \"<group>\"; };\n\t\t97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = \"<group>\"; };\n\t\t97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = \"<group>\"; };\n/* End PBXFileReference section */\n\n/* Begin PBXFrameworksBuildPhase section */\n\t\t97C146EB1CF9000F007C117D /* Frameworks */ = {\n\t\t\tisa = PBXFrameworksBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t9705A1C61CF904A100538489 /* Flutter.framework in Frameworks */,\n\t\t\t\t3B80C3941E831B6300D905FE /* App.framework in Frameworks */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXFrameworksBuildPhase section */\n\n/* Begin PBXGroup section */\n\t\t9740EEB11CF90186004384FC /* Flutter */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t2D5378251FAA1A9400D5DBA9 /* flutter_assets */,\n\t\t\t\t3B80C3931E831B6300D905FE /* App.framework */,\n\t\t\t\t3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,\n\t\t\t\t9740EEBA1CF902C7004384FC /* Flutter.framework */,\n\t\t\t\t9740EEB21CF90195004384FC /* Debug.xcconfig */,\n\t\t\t\t7AFA3C8E1D35360C0083082E /* Release.xcconfig */,\n\t\t\t\t9740EEB31CF90195004384FC /* Generated.xcconfig */,\n\t\t\t);\n\t\t\tname = Flutter;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146E51CF9000F007C117D = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t9740EEB11CF90186004384FC /* Flutter */,\n\t\t\t\t97C146F01CF9000F007C117D /* Runner */,\n\t\t\t\t97C146EF1CF9000F007C117D /* Products */,\n\t\t\t\tCF3B75C9A7D2FA2A4C99F110 /* Frameworks */,\n\t\t\t);\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146EF1CF9000F007C117D /* Products */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146EE1CF9000F007C117D /* Runner.app */,\n\t\t\t);\n\t\t\tname = Products;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146F01CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t7AFFD8ED1D35381100E5BB4D /* AppDelegate.h */,\n\t\t\t\t7AFFD8EE1D35381100E5BB4D /* AppDelegate.m */,\n\t\t\t\t97C146FA1CF9000F007C117D /* Main.storyboard */,\n\t\t\t\t97C146FD1CF9000F007C117D /* Assets.xcassets */,\n\t\t\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */,\n\t\t\t\t97C147021CF9000F007C117D /* Info.plist */,\n\t\t\t\t97C146F11CF9000F007C117D /* Supporting Files */,\n\t\t\t\t1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,\n\t\t\t\t1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,\n\t\t\t);\n\t\t\tpath = Runner;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146F11CF9000F007C117D /* Supporting Files */ = {\n\t\t\tisa = PBXGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146F21CF9000F007C117D /* main.m */,\n\t\t\t);\n\t\t\tname = \"Supporting Files\";\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXGroup section */\n\n/* Begin PBXNativeTarget section */\n\t\t97C146ED1CF9000F007C117D /* Runner */ = {\n\t\t\tisa = PBXNativeTarget;\n\t\t\tbuildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */;\n\t\t\tbuildPhases = (\n\t\t\t\t9740EEB61CF901F6004384FC /* Run Script */,\n\t\t\t\t97C146EA1CF9000F007C117D /* Sources */,\n\t\t\t\t97C146EB1CF9000F007C117D /* Frameworks */,\n\t\t\t\t97C146EC1CF9000F007C117D /* Resources */,\n\t\t\t\t9705A1C41CF9048500538489 /* Embed Frameworks */,\n\t\t\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */,\n\t\t\t);\n\t\t\tbuildRules = (\n\t\t\t);\n\t\t\tdependencies = (\n\t\t\t);\n\t\t\tname = Runner;\n\t\t\tproductName = Runner;\n\t\t\tproductReference = 97C146EE1CF9000F007C117D /* Runner.app */;\n\t\t\tproductType = \"com.apple.product-type.application\";\n\t\t};\n/* End PBXNativeTarget section */\n\n/* Begin PBXProject section */\n\t\t97C146E61CF9000F007C117D /* Project object */ = {\n\t\t\tisa = PBXProject;\n\t\t\tattributes = {\n\t\t\t\tLastUpgradeCheck = 0910;\n\t\t\t\tORGANIZATIONNAME = \"The Chromium Authors\";\n\t\t\t\tTargetAttributes = {\n\t\t\t\t\t97C146ED1CF9000F007C117D = {\n\t\t\t\t\t\tCreatedOnToolsVersion = 7.3.1;\n\t\t\t\t\t};\n\t\t\t\t};\n\t\t\t};\n\t\t\tbuildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */;\n\t\t\tcompatibilityVersion = \"Xcode 3.2\";\n\t\t\tdevelopmentRegion = English;\n\t\t\thasScannedForEncodings = 0;\n\t\t\tknownRegions = (\n\t\t\t\ten,\n\t\t\t\tBase,\n\t\t\t);\n\t\t\tmainGroup = 97C146E51CF9000F007C117D;\n\t\t\tproductRefGroup = 97C146EF1CF9000F007C117D /* Products */;\n\t\t\tprojectDirPath = \"\";\n\t\t\tprojectRoot = \"\";\n\t\t\ttargets = (\n\t\t\t\t97C146ED1CF9000F007C117D /* Runner */,\n\t\t\t);\n\t\t};\n/* End PBXProject section */\n\n/* Begin PBXResourcesBuildPhase section */\n\t\t97C146EC1CF9000F007C117D /* Resources */ = {\n\t\t\tisa = PBXResourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */,\n\t\t\t\t3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */,\n\t\t\t\t9740EEB41CF90195004384FC /* Debug.xcconfig in Resources */,\n\t\t\t\t97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */,\n\t\t\t\t2D5378261FAA1A9400D5DBA9 /* flutter_assets in Resources */,\n\t\t\t\t97C146FC1CF9000F007C117D /* Main.storyboard in Resources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXResourcesBuildPhase section */\n\n/* Begin PBXShellScriptBuildPhase section */\n\t\t3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Thin Binary\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" thin\";\n\t\t};\n\t\t9740EEB61CF901F6004384FC /* Run Script */ = {\n\t\t\tisa = PBXShellScriptBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t);\n\t\t\tinputPaths = (\n\t\t\t);\n\t\t\tname = \"Run Script\";\n\t\t\toutputPaths = (\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t\tshellPath = /bin/sh;\n\t\t\tshellScript = \"/bin/sh \\\"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\\\" build\";\n\t\t};\n/* End PBXShellScriptBuildPhase section */\n\n/* Begin PBXSourcesBuildPhase section */\n\t\t97C146EA1CF9000F007C117D /* Sources */ = {\n\t\t\tisa = PBXSourcesBuildPhase;\n\t\t\tbuildActionMask = 2147483647;\n\t\t\tfiles = (\n\t\t\t\t978B8F6F1D3862AE00F588F7 /* AppDelegate.m in Sources */,\n\t\t\t\t97C146F31CF9000F007C117D /* main.m in Sources */,\n\t\t\t\t1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,\n\t\t\t);\n\t\t\trunOnlyForDeploymentPostprocessing = 0;\n\t\t};\n/* End PBXSourcesBuildPhase section */\n\n/* Begin PBXVariantGroup section */\n\t\t97C146FA1CF9000F007C117D /* Main.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C146FB1CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = Main.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n\t\t97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */ = {\n\t\t\tisa = PBXVariantGroup;\n\t\t\tchildren = (\n\t\t\t\t97C147001CF9000F007C117D /* Base */,\n\t\t\t);\n\t\t\tname = LaunchScreen.storyboard;\n\t\t\tsourceTree = \"<group>\";\n\t\t};\n/* End PBXVariantGroup section */\n\n/* Begin XCBuildConfiguration section */\n\t\t249021D3217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t249021D4217E4FDB00AE95B9 /* Profile */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tDEVELOPMENT_TEAM = S8QB4VV633;\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Profile;\n\t\t};\n\t\t97C147031CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = dwarf;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tENABLE_TESTABILITY = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_DYNAMIC_NO_PIC = NO;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_OPTIMIZATION_LEVEL = 0;\n\t\t\t\tGCC_PREPROCESSOR_DEFINITIONS = (\n\t\t\t\t\t\"DEBUG=1\",\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t);\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = YES;\n\t\t\t\tONLY_ACTIVE_ARCH = YES;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147041CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tALWAYS_SEARCH_USER_PATHS = NO;\n\t\t\t\tCLANG_ANALYZER_NONNULL = YES;\n\t\t\t\tCLANG_CXX_LANGUAGE_STANDARD = \"gnu++0x\";\n\t\t\t\tCLANG_CXX_LIBRARY = \"libc++\";\n\t\t\t\tCLANG_ENABLE_MODULES = YES;\n\t\t\t\tCLANG_ENABLE_OBJC_ARC = YES;\n\t\t\t\tCLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;\n\t\t\t\tCLANG_WARN_BOOL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_COMMA = YES;\n\t\t\t\tCLANG_WARN_CONSTANT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;\n\t\t\t\tCLANG_WARN_EMPTY_BODY = YES;\n\t\t\t\tCLANG_WARN_ENUM_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_INFINITE_RECURSION = YES;\n\t\t\t\tCLANG_WARN_INT_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_LITERAL_CONVERSION = YES;\n\t\t\t\tCLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;\n\t\t\t\tCLANG_WARN_RANGE_LOOP_ANALYSIS = YES;\n\t\t\t\tCLANG_WARN_STRICT_PROTOTYPES = YES;\n\t\t\t\tCLANG_WARN_SUSPICIOUS_MOVE = YES;\n\t\t\t\tCLANG_WARN_UNREACHABLE_CODE = YES;\n\t\t\t\tCLANG_WARN__DUPLICATE_METHOD_MATCH = YES;\n\t\t\t\t\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\" = \"iPhone Developer\";\n\t\t\t\tCOPY_PHASE_STRIP = NO;\n\t\t\t\tDEBUG_INFORMATION_FORMAT = \"dwarf-with-dsym\";\n\t\t\t\tENABLE_NS_ASSERTIONS = NO;\n\t\t\t\tENABLE_STRICT_OBJC_MSGSEND = YES;\n\t\t\t\tGCC_C_LANGUAGE_STANDARD = gnu99;\n\t\t\t\tGCC_NO_COMMON_BLOCKS = YES;\n\t\t\t\tGCC_WARN_64_TO_32_BIT_CONVERSION = YES;\n\t\t\t\tGCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;\n\t\t\t\tGCC_WARN_UNDECLARED_SELECTOR = YES;\n\t\t\t\tGCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;\n\t\t\t\tGCC_WARN_UNUSED_FUNCTION = YES;\n\t\t\t\tGCC_WARN_UNUSED_VARIABLE = YES;\n\t\t\t\tIPHONEOS_DEPLOYMENT_TARGET = 8.0;\n\t\t\t\tMTL_ENABLE_DEBUG_INFO = NO;\n\t\t\t\tSDKROOT = iphoneos;\n\t\t\t\tTARGETED_DEVICE_FAMILY = \"1,2\";\n\t\t\t\tVALIDATE_PRODUCT = YES;\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n\t\t97C147061CF9000F007C117D /* Debug */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Debug;\n\t\t};\n\t\t97C147071CF9000F007C117D /* Release */ = {\n\t\t\tisa = XCBuildConfiguration;\n\t\t\tbaseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;\n\t\t\tbuildSettings = {\n\t\t\t\tASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;\n\t\t\t\tCURRENT_PROJECT_VERSION = \"$(FLUTTER_BUILD_NUMBER)\";\n\t\t\t\tENABLE_BITCODE = NO;\n\t\t\t\tFRAMEWORK_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tINFOPLIST_FILE = Runner/Info.plist;\n\t\t\t\tLD_RUNPATH_SEARCH_PATHS = \"$(inherited) @executable_path/Frameworks\";\n\t\t\t\tLIBRARY_SEARCH_PATHS = (\n\t\t\t\t\t\"$(inherited)\",\n\t\t\t\t\t\"$(PROJECT_DIR)/Flutter\",\n\t\t\t\t);\n\t\t\t\tPRODUCT_BUNDLE_IDENTIFIER = com.ngu.wanandroidNgu;\n\t\t\t\tPRODUCT_NAME = \"$(TARGET_NAME)\";\n\t\t\t\tVERSIONING_SYSTEM = \"apple-generic\";\n\t\t\t};\n\t\t\tname = Release;\n\t\t};\n/* End XCBuildConfiguration section */\n\n/* Begin XCConfigurationList section */\n\t\t97C146E91CF9000F007C117D /* Build configuration list for PBXProject \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147031CF9000F007C117D /* Debug */,\n\t\t\t\t97C147041CF9000F007C117D /* Release */,\n\t\t\t\t249021D3217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n\t\t97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget \"Runner\" */ = {\n\t\t\tisa = XCConfigurationList;\n\t\t\tbuildConfigurations = (\n\t\t\t\t97C147061CF9000F007C117D /* Debug */,\n\t\t\t\t97C147071CF9000F007C117D /* Release */,\n\t\t\t\t249021D4217E4FDB00AE95B9 /* Profile */,\n\t\t\t);\n\t\t\tdefaultConfigurationIsVisible = 0;\n\t\t\tdefaultConfigurationName = Release;\n\t\t};\n/* End XCConfigurationList section */\n\t};\n\trootObject = 97C146E61CF9000F007C117D /* Project object */;\n}\n"
  },
  {
    "path": "ios/Runner.xcodeproj/project.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "ios/Runner.xcodeproj/xcshareddata/xcschemes/Runner.xcscheme",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Scheme\n   LastUpgradeVersion = \"0910\"\n   version = \"1.3\">\n   <BuildAction\n      parallelizeBuildables = \"YES\"\n      buildImplicitDependencies = \"YES\">\n      <BuildActionEntries>\n         <BuildActionEntry\n            buildForTesting = \"YES\"\n            buildForRunning = \"YES\"\n            buildForProfiling = \"YES\"\n            buildForArchiving = \"YES\"\n            buildForAnalyzing = \"YES\">\n            <BuildableReference\n               BuildableIdentifier = \"primary\"\n               BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n               BuildableName = \"Runner.app\"\n               BlueprintName = \"Runner\"\n               ReferencedContainer = \"container:Runner.xcodeproj\">\n            </BuildableReference>\n         </BuildActionEntry>\n      </BuildActionEntries>\n   </BuildAction>\n   <TestAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\">\n      <Testables>\n      </Testables>\n      <MacroExpansion>\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </MacroExpansion>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </TestAction>\n   <LaunchAction\n      buildConfiguration = \"Debug\"\n      selectedDebuggerIdentifier = \"Xcode.DebuggerFoundation.Debugger.LLDB\"\n      selectedLauncherIdentifier = \"Xcode.DebuggerFoundation.Launcher.LLDB\"\n      language = \"\"\n      launchStyle = \"0\"\n      useCustomWorkingDirectory = \"NO\"\n      ignoresPersistentStateOnLaunch = \"NO\"\n      debugDocumentVersioning = \"YES\"\n      debugServiceExtension = \"internal\"\n      allowLocationSimulation = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n      <AdditionalOptions>\n      </AdditionalOptions>\n   </LaunchAction>\n   <ProfileAction\n      buildConfiguration = \"Profile\"\n      shouldUseLaunchSchemeArgsEnv = \"YES\"\n      savedToolIdentifier = \"\"\n      useCustomWorkingDirectory = \"NO\"\n      debugDocumentVersioning = \"YES\">\n      <BuildableProductRunnable\n         runnableDebuggingMode = \"0\">\n         <BuildableReference\n            BuildableIdentifier = \"primary\"\n            BlueprintIdentifier = \"97C146ED1CF9000F007C117D\"\n            BuildableName = \"Runner.app\"\n            BlueprintName = \"Runner\"\n            ReferencedContainer = \"container:Runner.xcodeproj\">\n         </BuildableReference>\n      </BuildableProductRunnable>\n   </ProfileAction>\n   <AnalyzeAction\n      buildConfiguration = \"Debug\">\n   </AnalyzeAction>\n   <ArchiveAction\n      buildConfiguration = \"Release\"\n      revealArchiveInOrganizer = \"YES\">\n   </ArchiveAction>\n</Scheme>\n"
  },
  {
    "path": "ios/Runner.xcworkspace/contents.xcworkspacedata",
    "content": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<Workspace\n   version = \"1.0\">\n   <FileRef\n      location = \"group:Runner.xcodeproj\">\n   </FileRef>\n</Workspace>\n"
  },
  {
    "path": "lib/app.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/ui/drawer/drawer.dart';\nimport 'package:wanandroid_ngu/ui/home/home_page.dart';\nimport 'package:wanandroid_ngu/ui/knowledge/knowledge.dart';\nimport 'package:wanandroid_ngu/ui/navigation/navigation.dart';\nimport 'package:wanandroid_ngu/ui/project/project.dart';\nimport 'package:wanandroid_ngu/ui/publicc/publicc.dart';\nimport 'package:wanandroid_ngu/ui/search/search.dart';\n\n//应用页面使用有状态Widget\nclass App extends StatefulWidget {\n  App({Key key}) : super(key: key);\n\n  @override\n  AppState createState() => AppState();\n}\n\n//应用页面状态实现类\nclass AppState extends State<App> {\n  int _selectedIndex = 0; //当前选中项的索引\n\n  final appBarTitles = ['玩Android', '体系', '公众号', '导航', \"项目\"];\n  int elevation = 4;\n\n  var pages = <Widget>[\n    HomePage(),\n    KnowledgePage(),\n    PubliccPage(),\n    NavigationPage(),\n    ProjectPage()\n  ];\n\n  @override\n  Widget build(BuildContext context) {\n    return WillPopScope(\n      onWillPop: _onWillPop,\n      child: Scaffold(\n        drawer: DrawerPage(),\n        appBar: AppBar(\n          title: new Text(appBarTitles[_selectedIndex]),\n          bottom: null,\n          elevation: 0,\n          actions: <Widget>[\n            IconButton(\n                icon: Icon(Icons.search),\n                onPressed: () {\n                  Navigator.of(context)\n                      .push(new MaterialPageRoute(builder: (context) {\n                    return new SearchPage();\n                  }));\n                })\n          ],\n        ),\n        body: new IndexedStack(children: pages, index: _selectedIndex),\n        //底部导航按钮 包含图标及文本\n        bottomNavigationBar: BottomNavigationBar(\n          items: <BottomNavigationBarItem>[\n            BottomNavigationBarItem(icon: Icon(Icons.home), title: Text('首页')),\n            BottomNavigationBarItem(\n                icon: Icon(Icons.assignment), title: Text('体系')),\n            BottomNavigationBarItem(icon: Icon(Icons.chat), title: Text('公众号')),\n            BottomNavigationBarItem(\n                icon: Icon(Icons.navigation), title: Text('导航')),\n            BottomNavigationBarItem(icon: Icon(Icons.book), title: Text('项目'))\n          ],\n          type: BottomNavigationBarType.fixed, //设置显示的模式\n          currentIndex: _selectedIndex, //当前选中项的索引\n          onTap: _onItemTapped, //选择按下处理\n        ),\n      ),\n    );\n  }\n\n  //选择按下处理 设置当前索引为index值\n  void _onItemTapped(int index) {\n    setState(() {\n      _selectedIndex = index;\n      if (index == 2 || index == 4) {\n        elevation = 0;\n      } else {\n        elevation = 4;\n      }\n    });\n  }\n\n  Future<bool> _onWillPop() {\n    return showDialog(\n          context: context,\n          builder: (context) => new AlertDialog(\n                title: new Text('提示'),\n                content: new Text('确定退出应用吗？'),\n                actions: <Widget>[\n                  new FlatButton(\n                    onPressed: () => Navigator.of(context).pop(false),\n                    child: new Text('再看一会'),\n                  ),\n                  new FlatButton(\n                    onPressed: () => Navigator.of(context).pop(true),\n                    child: new Text('退出'),\n                  ),\n                ],\n              ),\n        ) ??\n        false;\n  }\n}\n"
  },
  {
    "path": "lib/base/_base_widget.dart",
    "content": "import 'dart:ui';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\n\nabstract class BaseWidget extends StatefulWidget {\n\n  BaseWidgetState baseWidgetState;\n\n  @override\n  BaseWidgetState createState() {\n    baseWidgetState = getState();\n    return baseWidgetState;\n  }\n\n  BaseWidgetState getState();\n}\n\nabstract class BaseWidgetState<T extends BaseWidget> extends State<T> {\n  bool _isAppBarShow = true; //导航栏是否显示\n\n  bool _isErrorWidgetShow = false; //错误信息是否显示\n  String _errorContentMesage = \"网络请求失败，请检查您的网络\";\n  String _errImgPath = \"images/ic_error.png\";\n\n  bool _isLoadingWidgetShow = false;\n\n  bool _isEmptyWidgetShow = false;\n  String _emptyWidgetContent = \"暂无数据~\";\n  String _emptyImgPath = \"images/ic_empty.png\"; //自己根据需求变更\n\n  FontWeight _fontWidget = FontWeight.w600; //错误页面和空页面的字体粗度\n\n  @override\n  void initState() {\n    super.initState();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n        appBar: _getBaseAppBar(),\n        body: Container(\n          color: Colors.white, //背景颜色，可自己变更\n          child: Stack(\n            children: <Widget>[\n              getContentWidget(context),\n              _getBaseErrorWidget(),\n              _getBaseEmptyWidget(),\n              _getBassLoadingWidget(),\n            ],\n          ),\n        ));\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n  }\n\n  Widget getContentWidget(BuildContext context);\n\n  ///暴露的错误页面方法，可以自己重写定制\n  Widget getErrorWidget() {\n    return Container(\n      //错误页面中心可以自己调整\n      padding: EdgeInsets.fromLTRB(0, 0, 0, 80),\n      color: Colors.white,\n      width: double.infinity,\n      height: double.infinity,\n      child: Center(\n        child: Column(\n          mainAxisAlignment: MainAxisAlignment.center,\n          children: <Widget>[\n            Image(\n              image: AssetImage(_errImgPath),\n              width: 120,\n              height: 120,\n            ),\n            Container(\n              margin: EdgeInsets.fromLTRB(0, 20, 0, 0),\n              child: Text(_errorContentMesage,\n                  style: TextStyle(\n                    color: Colors.grey,\n                    fontWeight: _fontWidget,\n                  )),\n            ),\n            Container(\n                margin: EdgeInsets.fromLTRB(0, 20, 0, 0),\n                child: OutlineButton(\n                  child: Text(\"重新加载\",\n                      style: TextStyle(\n                        color: Colors.grey,\n                        fontWeight: _fontWidget,\n                      )),\n                  onPressed: () => {onClickErrorWidget()},\n                ))\n          ],\n        ),\n      ),\n    );\n  }\n\n  Widget getLoadingWidget() {\n    return Center(\n        child: CupertinoActivityIndicator(\n      radius: 15.0, //值越大加载的图形越大\n    ));\n  }\n\n  Widget getEmptyWidget() {\n    return Container(\n      padding: EdgeInsets.fromLTRB(0, 0, 0, 100),\n      color: Colors.white,\n      width: double.infinity,\n      height: double.infinity,\n      child: Center(\n        child: Container(\n          alignment: Alignment.center,\n          child: Column(\n            mainAxisAlignment: MainAxisAlignment.center,\n            children: <Widget>[\n              Image(\n                color: Colors.black12,\n                image: AssetImage(_emptyImgPath),\n                width: 150,\n                height: 150,\n              ),\n              Container(\n                margin: EdgeInsets.fromLTRB(0, 10, 0, 0),\n                child: Text(_emptyWidgetContent,\n                    style: TextStyle(\n                      color: Colors.grey,\n                      fontWeight: _fontWidget,\n                    )),\n              )\n            ],\n          ),\n        ),\n      ),\n    );\n  }\n\n  PreferredSizeWidget _getBaseAppBar() {\n    return PreferredSize(\n        child: Offstage(\n          offstage: !_isAppBarShow,\n          child: getAppBar(),\n        ),\n        preferredSize: Size.fromHeight(50));\n  }\n\n  ///导航栏 appBar\n  AppBar getAppBar();\n\n  Widget _getBaseErrorWidget() {\n    return Offstage(\n      offstage: !_isErrorWidgetShow,\n      child: getErrorWidget(),\n    );\n  }\n\n  Widget _getBassLoadingWidget() {\n    return Offstage(\n      offstage: !_isLoadingWidgetShow,\n      child: getLoadingWidget(),\n    );\n  }\n\n  Widget _getBaseEmptyWidget() {\n    return Offstage(\n      offstage: !_isEmptyWidgetShow,\n      child: getEmptyWidget(),\n    );\n  }\n\n  ///点击错误页面后展示内容\n  void onClickErrorWidget();\n\n  ///设置错误提示信息\n  void setErrorContent(String content) {\n    if (content != null) {\n      setState(() {\n        _errorContentMesage = content;\n      });\n    }\n  }\n\n  ///设置导航栏隐藏或者显示\n  void setAppBarVisible(bool isVisible) {\n    setState(() {\n      _isAppBarShow = isVisible;\n    });\n  }\n\n  void showContent() {\n    setState(() {\n      _isEmptyWidgetShow = false;\n      _isLoadingWidgetShow = false;\n      _isErrorWidgetShow = false;\n    });\n  }\n\n  void showloading() {\n    setState(() {\n      _isEmptyWidgetShow = false;\n      _isLoadingWidgetShow = true;\n      _isErrorWidgetShow = false;\n    });\n  }\n\n  void showEmpty() {\n    setState(() {\n      _isEmptyWidgetShow = true;\n      _isLoadingWidgetShow = false;\n      _isErrorWidgetShow = false;\n    });\n  }\n\n  void showError() {\n    setState(() {\n      _isEmptyWidgetShow = false;\n      _isLoadingWidgetShow = false;\n      _isErrorWidgetShow = true;\n    });\n  }\n\n  ///设置空页面内容\n  void setEmptyWidgetContent(String content) {\n    if (content != null) {\n      setState(() {\n        _emptyWidgetContent = content;\n      });\n    }\n  }\n\n  ///设置错误页面图片\n  void setErrorImage(String imagePath) {\n    if (imagePath != null) {\n      setState(() {\n        _errImgPath = imagePath;\n      });\n    }\n  }\n\n  ///设置空页面图片\n  void setEmptyImage(String imagePath) {\n    if (imagePath != null) {\n      setState(() {\n        _emptyImgPath = imagePath;\n      });\n    }\n  }\n}\n"
  },
  {
    "path": "lib/common/application.dart",
    "content": "import 'package:event_bus/event_bus.dart';\n\nclass Application{\n  static EventBus eventBus=new EventBus();\n}\n"
  },
  {
    "path": "lib/common/user.dart",
    "content": "import '../model/user_model.dart';\nimport 'package:dio/dio.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\nclass User {\n\n  static final User singleton = User._internal();\n\n  factory User() {\n    return singleton;\n  }\n\n  User._internal();\n\n  List<String> cookie;\n  String userName;\n\n  void saveUserInfo(UserModel _userModel,Response response){\n        List<String> cookies = response.headers[\"set-cookie\"];\n        cookie = cookies;\n        userName = _userModel.data.username;\n        saveInfo();\n  }\n\n  Future<Null> getUserInfo() async {\n  SharedPreferences sp = await SharedPreferences.getInstance();\n  List<String> cookies = sp.getStringList(\"cookies\");\n  if (cookies != null) {\n    cookie = cookies;\n  }\n\n  String username = sp.getString(\"username\");\n  if(username!=null){\n    userName = username;\n  }\n}\n\n  saveInfo() async {\n    SharedPreferences sp = await SharedPreferences.getInstance();\n    sp.setStringList(\"cookies\", cookie);\n    sp.setString(\"username\", userName);\n  }\n\n  void clearUserInfor(){\n    cookie = null;\n    userName = null;\n    clearInfo();\n\n  }\n  \n  clearInfo() async {\n    SharedPreferences sp = await SharedPreferences.getInstance();\n    sp.setStringList(\"cookies\", null);\n    sp.setString(\"username\", null);\n  }\n}\n"
  },
  {
    "path": "lib/db/db_helper.dart",
    "content": "import 'dart:io';\nimport 'package:path_provider/path_provider.dart';\nimport 'package:sqflite/sqflite.dart';\nimport 'dart:async';\nimport 'package:path/path.dart';\nimport 'package:wanandroid_ngu/model/common_websit_model.dart';\n\nclass DatabaseHelper {\n\n  static final DatabaseHelper _instance = DatabaseHelper.internal();\n  factory DatabaseHelper() => _instance;\n\n  final String tableName = \"table_common_web\";\n\n  final String columnId = \"id\";\n  final String columnName = \"name\";\n  final String columnlink = \"link\";\n  final String columnIcon = \"icon\";\n  final String columnOrder = \"web_order\";\n  final String columnVisible = \"visible\";\n\n  static Database _db;\n\n  Future<Database> get db async {\n    if (_db != null) {\n      return _db;\n    }\n    _db = await initDb();\n    return _db;\n  }\n\n  DatabaseHelper.internal();\n\n  initDb() async {\n    Directory documentDirectory = await getApplicationDocumentsDirectory();\n    String path = join(documentDirectory.path, \"wanandroid.db\");\n    var ourDb = await openDatabase(path, version: 1, onCreate: _onCreate);\n    return ourDb;\n  }\n\n  //创建数据库表\n  void _onCreate(Database db, int version) async {\n    await db.execute(\n        \"create table $tableName($columnId integer primary key,$columnIcon text not null, $columnlink text not null,$columnName text not null , $columnVisible integer not null , $columnOrder integer not null)\");\n    print(\"Table is created\");\n  }\n\n//插入\n  Future<int> saveItem(DataListBean item) async {\n    var dbClient = await db;\n    int res = await dbClient.insert(\"$tableName\", item.toMap());\n    print(res.toString());\n    return res;\n  }\n\n  //查询\n  Future<List> getTotalList() async {\n    var dbClient = await db;\n    var result = await dbClient.rawQuery(\"SELECT * FROM $tableName \");\n    return result.toList();\n  }\n\n  //查询总数\n  Future<int> getCount() async {\n    var dbClient = await db;\n    return Sqflite.firstIntValue(await dbClient.rawQuery(\n        \"SELECT COUNT(*) FROM $tableName\"\n    ));\n  }\n\n//按照id查询\n  Future<DataListBean> getItem(int id) async {\n    var dbClient = await db;\n    var result = await dbClient.rawQuery(\"SELECT * FROM $tableName WHERE id = $id\");\n    if (result.length == 0) return null;\n    return DataListBean.fromMap(result.first);\n  }\n\n\n  //清空数据\n  Future<int> clear() async {\n    var dbClient = await db;\n    return await dbClient.delete(tableName);\n  }\n\n\n  //根据id删除\n  Future<int> deleteItem(int id) async {\n    var dbClient = await db;\n    return await dbClient.delete(tableName,\n        where: \"$columnId = ?\", whereArgs: [id]);\n  }\n\n  //修改\n  Future<int> updateItem(DataListBean item) async {\n    var dbClient = await db;\n    return await dbClient.update(\"$tableName\", item.toMap(),\n        where: \"$columnId = ?\", whereArgs: [item.id]);\n  }\n\n  //清空数据库\n\n\n  //关闭\n  Future close() async {\n    var dbClient = await db;\n    return dbClient.close();\n  }\n}\n"
  },
  {
    "path": "lib/event/change_theme_event.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass ChangeThemeEvent {\n\n  Color color;\n\n  ChangeThemeEvent(Color c) {\n    color = c;\n  }\n}"
  },
  {
    "path": "lib/event/login_event.dart",
    "content": "class LoginEvent{\n\n}"
  },
  {
    "path": "lib/http/api.dart",
    "content": "\nclass Api{\n  static const String HOME_BANNER = \"https://www.wanandroid.com/banner/json\";\n\n  static const String HOME_ARTICLE_LIST = \"https://www.wanandroid.com/article/list/\";\n  /// 知识体系\n  static const String SYSTEM_TREE = \"https://www.wanandroid.com/tree/json\";\n  // 知识体系详情\n  static const String SYSTEM_TREE_CONTENT = \"https://www.wanandroid.com/article/list/\";\n  // 公众号名称\n  static const String WX_LIST = \"https://wanandroid.com/wxarticle/chapters/json\";\n  // 公众号文章\n  static const String WX_ARTICLE_LIST = \"https://wanandroid.com/wxarticle/list/\";\n  // 导航列表数据\n  static const String NAVI_LIST = \"https://www.wanandroid.com/navi/json\";\n  // 项目分类\n  static const String PROJECT_TREE = \"https://www.wanandroid.com/project/tree/json\";\n  // 项目列表\n  static const String PROJECT_LIST = \"https://www.wanandroid.com/project/list/\";\n  // 搜索热词\n  static const String SEARCH_HOT_WORD = \"https://www.wanandroid.com//hotkey/json\";\n  // 搜索结果\n  static const String SEARCH_RESULT = \"https://www.wanandroid.com/article/query/\";\n  // 用户登录\n  static const String USER_LOGIN = \"https://www.wanandroid.com/user/login\";\n  // 用户注册\n  static const String USER_REGISTER = \"https://www.wanandroid.com/user/register\";\n  // 收藏列表\n  static const String COLLECTION_LIST = \"https://www.wanandroid.com/lg/collect/list/\";\n  //常用网站\n  static const String COMMON_WEBSITE = \"https://www.wanandroid.com/friend/json\";\n\n\n  // 我的收藏-取消收藏\n  static const String CANCEL_COLLECTION = \"https://www.wanandroid.com/lg/uncollect/\";\n  \n  // 我的收藏-新增收藏\n  static const String ADD_COLLECTION = \"https://www.wanandroid.com/lg/collect/add/json\";\n  // 网站收藏\n  static const String WEBSITE_COLLECTION_LIST = \"https://www.wanandroid.com/lg/collect/usertools/json\";\n  // 取消网站收藏\n  static const String CANCEL_WEBSITE_COLLECTION = \"https://www.wanandroid.com/lg/collect/deletetool/json\";\n  // 新增网站收藏\n  static const String ADD_WEBSITE_COLLECTION = \"https://www.wanandroid.com/lg/collect/addtool/json\";\n  // 编辑网站收藏\n  static const String EDIT_WEBSITE_COLLECTION = \"https://www.wanandroid.com/lg/collect/updatetool/json\";\n\n  // todo列表数据\n  static const String TODO_LIST = \"https://wanandroid.com/lg/todo/list/\";\n  // 新增todo数据\n  static const String ADD_TODO = \"https://www.wanandroid.com/lg/todo/add/json\";\n  // 更新todo数据\n  static const String UPDATE_TODO = \"https://www.wanandroid.com/lg/todo/update/\";\n  // 删除todo数据\n  static const String DELETE_TODO = \"https://www.wanandroid.com/lg/todo/delete/\";\n  // 仅更新todo完成状态\n  static const String DONE_TODO = \"https://www.wanandroid.com/lg/todo/done/\";\n  \n}"
  },
  {
    "path": "lib/http/api_service.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:wanandroid_ngu/common/user.dart';\nimport 'package:wanandroid_ngu/http/dio_manager.dart';\nimport 'package:wanandroid_ngu/model/article_model.dart';\nimport 'package:wanandroid_ngu/model/banner_model.dart';\nimport 'package:wanandroid_ngu/model/base_model.dart';\nimport 'package:wanandroid_ngu/model/collection_model.dart';\nimport 'package:wanandroid_ngu/model/common_websit_model.dart';\nimport 'package:wanandroid_ngu/model/hotword_result_model.dart';\nimport 'package:wanandroid_ngu/model/navi_model.dart';\nimport 'package:wanandroid_ngu/model/pretty_model.dart';\nimport 'package:wanandroid_ngu/model/projectlist_model.dart';\nimport 'package:wanandroid_ngu/model/project_tree_model.dart';\nimport 'package:wanandroid_ngu/model/system_tree_content_model.dart';\nimport 'package:wanandroid_ngu/model/system_tree_model.dart';\nimport 'package:wanandroid_ngu/model/todolist_model.dart';\nimport 'package:wanandroid_ngu/model/user_model.dart';\nimport 'package:wanandroid_ngu/model/website_collection_model.dart';\nimport 'package:wanandroid_ngu/model/wx_article_content_model.dart';\nimport 'package:wanandroid_ngu/model/wx_article_title_model.dart';\nimport 'package:wanandroid_ngu/model/hotword_model.dart';\n\nimport 'api.dart';\n\nclass ApiService {\n  void getBanner(Function callback) async {\n    DioManager.singleton.dio\n        .get(Api.HOME_BANNER, options: _getOptions())\n        .then((response) {\n      callback(BannerModel(response.data));\n    });\n  }\n\n  void getArticleList(Function callback, Function errorback, int _page) async {\n    DioManager.singleton.dio\n        .get(Api.HOME_ARTICLE_LIST + \"$_page/json\", options: _getOptions())\n        .then((response) {\n      callback(ArticleModel(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n\n  /// 获取知识体系列表\n  void getSystemTree(Function callback, Function errorback) async {\n    DioManager.singleton.dio\n        .get(Api.SYSTEM_TREE, options: _getOptions())\n        .then((response) {\n      callback(SystemTreeModel(response.data));\n      }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  /// 获取知识体系列表详情\n  void getSystemTreeContent(Function callback, Function errorback,int _page, int _id) async {\n    DioManager.singleton.dio\n        .get(Api.SYSTEM_TREE_CONTENT + \"$_page/json?cid=$_id\",\n            options: _getOptions())\n        .then((response) {\n      callback(SystemTreeContentModel(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  /// 获取公众号名称\n  void getWxList(Function callback, Function errorback) async {\n    DioManager.singleton.dio\n        .get(Api.WX_LIST, options: _getOptions())\n        .then((response) {\n      callback(WxArticleTitleModel(response.data));\n      }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  /// 获取公众号文章\n  void getWxArticleList(Function callback, int _id, int _page) async {\n    DioManager.singleton.dio\n        .get(Api.WX_ARTICLE_LIST + \"$_id/$_page/json\", options: _getOptions())\n        .then((response) {\n      callback(WxArticleContentModel(response.data));\n    });\n  }\n\n  /// 获取导航列表数据\n  void getNaviList(Function callback, Function errorback) async {\n    DioManager.singleton.dio\n        .get(Api.NAVI_LIST, options: _getOptions())\n        .then((response) {\n      callback(NaviModel(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  /// 获取项目分类\n  void getProjectTree(Function callback,Function errorback) async {\n    DioManager.singleton.dio\n        .get(Api.PROJECT_TREE, options: _getOptions())\n        .then((response) {\n      callback(ProjectTreeModel(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  /// 获取项目列表\n  void getProjectList(Function callback, int _page, int _id) async {\n    DioManager.singleton.dio\n        .get(Api.PROJECT_LIST + \"$_page/json?cid=$_id\", options: _getOptions())\n        .then((response) {\n      callback(ProjectTreeListModel(response.data));\n    });\n  }\n\n  /// 获取搜索热词\n  void getSearchHotWord(Function callback) async {\n    DioManager.singleton.dio\n        .get(Api.SEARCH_HOT_WORD, options: _getOptions())\n        .then((response) {\n      callback(HotwordModel.fromMap(response.data));\n    });\n  }\n\n  /// 获取搜索结果\n  void getSearchResult(Function callback, Function errorback, int _page, String _keyword) async {\n    FormData formData = new FormData.from({\n      \"k\": _keyword,\n    });\n    DioManager.singleton.dio\n        .post(Api.SEARCH_RESULT + \"$_page/json\",\n            data: formData, options: _getOptions())\n        .then((response) {\n      callback(HotwordResultModel.fromMap(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  /// 登录\n  void login(Function callback, String _username, String _password) async {\n    FormData formData =\n        new FormData.from({\"username\": _username, \"password\": _password});\n    DioManager.singleton.dio\n        .post(Api.USER_LOGIN, data: formData, options: _getOptions())\n        .then((response) {\n      callback(UserModel(response.data), response);\n    });\n  }\n\n  /// 注册\n  void register(Function callback, String _username, String _password) async {\n    FormData formData = new FormData.from({\n      \"username\": _username,\n      \"password\": _password,\n      \"repassword\": _password\n    });\n    DioManager.singleton.dio\n        .post(Api.USER_REGISTER, data: formData, options: null)\n        .then((response) {\n      print(response.toString());\n      callback(UserModel(response.data));\n    });\n  }\n\n  /// 获取收藏列表\n  void getCollectionList(\n      Function callback, Function errorback, int _page) async {\n    DioManager.singleton.dio\n        .get(Api.COLLECTION_LIST + \"$_page/json\", options: _getOptions())\n        .then((response) {\n      callback(CollectionModel(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  /// 我的收藏-取消收藏\n  void cancelCollection(\n      Function callback, Function errorback, int _id, int _originId) async {\n    FormData formData = new FormData.from({\"originId\": _originId});\n    DioManager.singleton.dio\n        .post(Api.CANCEL_COLLECTION + \"$_id/json\",\n            data: formData, options: _getOptions())\n        .then((response) {\n      callback(BaseModel(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n\n\n\n  ///常用网站\n  void getCommonWebsite(Function callback, Function errorback) async {\n    DioManager.singleton.dio\n        .get(Api.COMMON_WEBSITE, options: _getOptions())\n        .then((response) {\n      callback(CommonWebsitModel.fromMap(response.data));\n    }).catchError((e) {\n      errorback(e);\n    });\n  }\n\n  void getPrettyGirl(Function callback, int _page) async {\n    DioManager.singleton.dio\n        .get(\"http://gank.io/api/data/福利/10/\" + \"$_page\")\n        .then((response) {\n      callback(PrettyModel.fromMap(response.data));\n    });\n  }\n\n  /// 取消网站收藏\n  void cancelWebsiteCollectionList(Function callback, int _id) async {\n    FormData formData = new FormData.from({\n      \"id\": _id,\n    });\n    DioManager.singleton.dio\n        .post(Api.CANCEL_WEBSITE_COLLECTION,\n            data: formData, options: _getOptions())\n        .then((response) {\n      callback(BaseModel(response.data));\n    });\n  }\n\n\n  Options _getOptions() {\n    Map<String, String> map = new Map();\n    List<String> cookies = User().cookie;\n    map[\"Cookie\"] = cookies.toString();\n    return Options(headers: map);\n  }\n}\n"
  },
  {
    "path": "lib/http/dio_manager.dart",
    "content": "import 'dart:io';\n\nimport 'package:dio/dio.dart';\n\nclass DioManager {\n  Dio _dio;\n\n  DioManager._internal() {\n    _dio = new Dio();\n    (_dio.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate =\n        (client) {\n      client.badCertificateCallback =\n          (X509Certificate cert, String host, int port) {\n        return true;\n      };\n    };\n  }\n\n  static DioManager singleton = DioManager._internal();\n\n  factory DioManager() => singleton;\n\n  get dio {\n    return _dio;\n  }\n}\n"
  },
  {
    "path": "lib/loading.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'dart:async';\n\nimport 'package:shared_preferences/shared_preferences.dart';\nimport 'package:wanandroid_ngu/app.dart';\n\n//加载页面\nclass LoadingPage extends StatefulWidget {\n  @override\n  _LoadingState createState() => new _LoadingState();\n}\n\nclass _LoadingState extends State<LoadingPage> {\n\n  @override\n  void initState(){\n    super.initState();\n    //在加载页面停顿2秒\n    new Future.delayed(Duration(seconds: 2),(){\n      _getHasSkip();\n    });\n  }\n\n  void _getHasSkip ()async {\n    SharedPreferences prefs = await SharedPreferences.getInstance();\n    bool hasSkip = prefs.getBool(\"hasSkip\");\n    if(hasSkip==null||!hasSkip){\n      Navigator.of(context).pushReplacementNamed(\"splash\");\n    }else {\n      Navigator.of(context).pushAndRemoveUntil(\n          new MaterialPageRoute(\n              builder: (context) => App()),\n              (route) => route == null);\n    }\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return new Center(\n      child: Stack(\n        children: <Widget>[\n          //加载页面居中背景图 使用cover模式\n          Image.asset(\"images/loading.png\",fit: BoxFit.cover,),\n        ],\n      ),\n    );\n  }\n}"
  },
  {
    "path": "lib/main.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/common/application.dart';\nimport 'package:wanandroid_ngu/common/user.dart';\nimport 'package:wanandroid_ngu/event/change_theme_event.dart';\nimport 'package:wanandroid_ngu/splash_screen.dart';\nimport 'package:wanandroid_ngu/util/theme_util.dart';\nimport 'package:wanandroid_ngu/util/utils.dart';\nimport './app.dart';\nimport './loading.dart';\nimport 'dart:io';\nimport 'package:flutter/services.dart';\n\nvoid main() {\n  getLoginInfo();\n  runApp(MyApp());\n  if (Platform.isAndroid) {\n// 以下两行 设置android状态栏为透明的沉浸。写在组件渲染之后，是为了在渲染后进行set赋值，覆盖状态栏，写在渲染之前MaterialApp组件会覆盖掉这个值。\n    SystemUiOverlayStyle systemUiOverlayStyle =\n        SystemUiOverlayStyle(statusBarColor: Colors.transparent);\n    SystemChrome.setSystemUIOverlayStyle(systemUiOverlayStyle);\n  }\n}\n\nFuture<Null> getLoginInfo() async {\n  User.singleton.getUserInfo();\n}\n\nclass MyApp extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() {\n    return MyAppState();\n  }\n}\n\nclass MyAppState extends State<MyApp> {\n\n  Color themeColor = ThemeUtils.currentColorTheme;\n  @override\n  void initState() {\n    super.initState();\n    Utils.getColorThemeIndex().then((index) {\n      print('color theme index = $index');\n      if (index != null) {\n        ThemeUtils.currentColorTheme = ThemeUtils.supportColors[index];\n        Application.eventBus\n            .fire(new ChangeThemeEvent(ThemeUtils.supportColors[index]));\n      }\n    });\n\n    Application.eventBus.on<ChangeThemeEvent>().listen((event) {\n      setState(() {\n        themeColor = event.color;\n      });\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return MaterialApp(\n      title: \"玩Android\",\n      debugShowCheckedModeBanner: false,\n      theme:\n          new ThemeData(primaryColor: themeColor, brightness: Brightness.light),\n      routes: <String, WidgetBuilder>{\n        \"app\": (BuildContext context) => new App(),\n        \"splash\": (BuildContext context) => new SplashScreen(),\n      },\n      home: new LoadingPage(),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/model/article_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass ArticleModel {\n\n  int errorCode;\n  String errorMsg;\n  Data data;\n\n  ArticleModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory ArticleModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ArticleModel.fromJson(json.decode(jsonStr)) : new ArticleModel.fromJson(jsonStr);\n\n  ArticleModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : new Data.fromJson(jsonRes['data']);\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass Data {\n\n  int curPage;\n  int offset;\n  int pageCount;\n  int size;\n  int total;\n  bool over;\n  List<Article> datas;\n\n  Data.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});\n\n  Data.fromJson(jsonRes) {\n    curPage = jsonRes['curPage'];\n    offset = jsonRes['offset'];\n    pageCount = jsonRes['pageCount'];\n    size = jsonRes['size'];\n    total = jsonRes['total'];\n    over = jsonRes['over'];\n    datas = jsonRes['datas'] == null ? null : [];\n\n    for (var datasItem in datas == null ? [] : jsonRes['datas']){\n      datas.add(datasItem == null ? null : new Article.fromJson(datasItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"curPage\": $curPage,\"offset\": $offset,\"pageCount\": $pageCount,\"size\": $size,\"total\": $total,\"over\": $over,\"datas\": $datas}';\n  }\n}\n\nclass Article {\n\n  int chapterId;\n  int courseId;\n  int id;\n  int publishTime;\n  int superChapterId;\n  int type;\n  int userId;\n  int visible;\n  int zan;\n  bool collect;\n  bool fresh;\n  String apkLink;\n  String author;\n  String chapterName;\n  String desc;\n  String envelopePic;\n  String link;\n  String niceDate;\n  String origin;\n  String projectLink;\n  String superChapterName;\n  String title;\n  List<Tag> tags;\n\n  Article.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});\n\n  Article.fromJson(jsonRes) {\n    chapterId = jsonRes['chapterId'];\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    publishTime = jsonRes['publishTime'];\n    superChapterId = jsonRes['superChapterId'];\n    type = jsonRes['type'];\n    userId = jsonRes['userId'];\n    visible = jsonRes['visible'];\n    zan = jsonRes['zan'];\n    collect = jsonRes['collect'];\n    fresh = jsonRes['fresh'];\n    apkLink = jsonRes['apkLink'];\n    author = jsonRes['author'];\n    chapterName = jsonRes['chapterName'];\n    desc = jsonRes['desc'];\n    envelopePic = jsonRes['envelopePic'];\n    link = jsonRes['link'];\n    niceDate = jsonRes['niceDate'];\n    origin = jsonRes['origin'];\n    projectLink = jsonRes['projectLink'];\n    superChapterName = jsonRes['superChapterName'];\n    title = jsonRes['title'];\n    tags = jsonRes['tags'] == null ? null : [];\n\n    for (var tagsItem in tags == null ? [] : jsonRes['tags']){\n      tags.add(tagsItem == null ? null : new Tag.fromJson(tagsItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"chapterId\": $chapterId,\"courseId\": $courseId,\"id\": $id,\"publishTime\": $publishTime,\"superChapterId\": $superChapterId,\"type\": $type,\"userId\": $userId,\"visible\": $visible,\"zan\": $zan,\"collect\": $collect,\"fresh\": $fresh,\"apkLink\": ${apkLink != null?'${json.encode(apkLink)}':'null'},\"author\": ${author != null?'${json.encode(author)}':'null'},\"chapterName\": ${chapterName != null?'${json.encode(chapterName)}':'null'},\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"envelopePic\": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"niceDate\": ${niceDate != null?'${json.encode(niceDate)}':'null'},\"origin\": ${origin != null?'${json.encode(origin)}':'null'},\"projectLink\": ${projectLink != null?'${json.encode(projectLink)}':'null'},\"superChapterName\": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'},\"tags\": $tags}';\n  }\n}\n\nclass Tag {\n\n  String name;\n  String url;\n\n  Tag.fromParams({this.name, this.url});\n\n  Tag.fromJson(jsonRes) {\n    name = jsonRes['name'];\n    url = jsonRes['url'];\n  }\n\n  @override\n  String toString() {\n    return '{\"name\": ${name != null?'${json.encode(name)}':'null'},\"url\": ${url != null?'${json.encode(url)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/banner_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass BannerModel {\n\n  int errorCode;\n  String errorMsg;\n  List<BannerData> data;\n\n  BannerModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory BannerModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BannerModel.fromJson(json.decode(jsonStr)) : new BannerModel.fromJson(jsonStr);\n\n  BannerModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : [];\n\n    for (var dataItem in data == null ? [] : jsonRes['data']){\n      data.add(dataItem == null ? null : new BannerData.fromJson(dataItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass BannerData {\n\n  int id;\n  int isVisible;\n  int order;\n  int type;\n  String desc;\n  String imagePath;\n  String title;\n  String url;\n\n  BannerData.fromParams({this.id, this.isVisible, this.order, this.type, this.desc, this.imagePath, this.title, this.url});\n\n  BannerData.fromJson(jsonRes) {\n    id = jsonRes['id'];\n    isVisible = jsonRes['isVisible'];\n    order = jsonRes['order'];\n    type = jsonRes['type'];\n    desc = jsonRes['desc'];\n    imagePath = jsonRes['imagePath'];\n    title = jsonRes['title'];\n    url = jsonRes['url'];\n  }\n\n  @override\n  String toString() {\n    return '{\"id\": $id,\"isVisible\": $isVisible,\"order\": $order,\"type\": $type,\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"imagePath\": ${imagePath != null?'${json.encode(imagePath)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'},\"url\": ${url != null?'${json.encode(url)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/base_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass BaseModel {\n\n  int errorCode;\n  String errorMsg;\n\n  BaseModel.fromParams({ this.errorCode, this.errorMsg});\n\n  factory BaseModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new BaseModel.fromJson(json.decode(jsonStr)) : new BaseModel.fromJson(jsonStr);\n  \n  BaseModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/collection_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass CollectionModel {\n\n  int errorCode;\n  String errorMsg;\n  CollectionData data;\n\n  CollectionModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory CollectionModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CollectionModel.fromJson(json.decode(jsonStr)) : new CollectionModel.fromJson(jsonStr);\n  \n  CollectionModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : new CollectionData.fromJson(jsonRes['data']);\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass CollectionData {\n\n  int curPage;\n  int offset;\n  int pageCount;\n  int size;\n  int total;\n  bool over;\n  List<Collection> datas;\n\n  CollectionData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});\n  \n  CollectionData.fromJson(jsonRes) {\n    curPage = jsonRes['curPage'];\n    offset = jsonRes['offset'];\n    pageCount = jsonRes['pageCount'];\n    size = jsonRes['size'];\n    total = jsonRes['total'];\n    over = jsonRes['over'];\n    datas = jsonRes['datas'] == null ? null : [];\n\n    for (var datasItem in datas == null ? [] : jsonRes['datas']){\n            datas.add(datasItem == null ? null : new Collection.fromJson(datasItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"curPage\": $curPage,\"offset\": $offset,\"pageCount\": $pageCount,\"size\": $size,\"total\": $total,\"over\": $over,\"datas\": $datas}';\n  }\n}\n\nclass Collection {\n\n  int chapterId;\n  int courseId;\n  int id;\n  int originId;\n  int publishTime;\n  int userId;\n  int visible;\n  int zan;\n  String author;\n  String chapterName;\n  String desc;\n  String envelopePic;\n  String link;\n  String niceDate;\n  String origin;\n  String title;\n\n  Collection.fromParams({this.chapterId, this.courseId, this.id, this.originId, this.publishTime, this.userId, this.visible, this.zan, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.title});\n  \n  Collection.fromJson(jsonRes) {\n    chapterId = jsonRes['chapterId'];\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    originId = jsonRes['originId'];\n    publishTime = jsonRes['publishTime'];\n    userId = jsonRes['userId'];\n    visible = jsonRes['visible'];\n    zan = jsonRes['zan'];\n    author = jsonRes['author'];\n    chapterName = jsonRes['chapterName'];\n    desc = jsonRes['desc'];\n    envelopePic = jsonRes['envelopePic'];\n    link = jsonRes['link'];\n    niceDate = jsonRes['niceDate'];\n    origin = jsonRes['origin'];\n    title = jsonRes['title'];\n  }\n\n  @override\n  String toString() {\n    return '{\"chapterId\": $chapterId,\"courseId\": $courseId,\"id\": $id,\"originId\": ${origin != null?'${json.encode(origin)}':'null'}Id,\"publishTime\": $publishTime,\"userId\": $userId,\"visible\": $visible,\"zan\": $zan,\"author\": ${author != null?'${json.encode(author)}':'null'},\"chapterName\": ${chapterName != null?'${json.encode(chapterName)}':'null'},\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"envelopePic\": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"niceDate\": ${niceDate != null?'${json.encode(niceDate)}':'null'},\"origin\": ${origin != null?'${json.encode(origin)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/common_websit_model.dart",
    "content": "class CommonWebsitModel {\n\n  String errorMsg;\n  int errorCode;\n  List<DataListBean> data;\n\n  static CommonWebsitModel fromMap(Map<String, dynamic> map) {\n    CommonWebsitModel common_websit_model = new CommonWebsitModel();\n    common_websit_model.errorMsg = map['errorMsg'];\n    common_websit_model.errorCode = map['errorCode'];\n    common_websit_model.data = DataListBean.fromMapList(map['data']);\n    return common_websit_model;\n  }\n\n  static List<CommonWebsitModel> fromMapList(dynamic mapList) {\n    List<CommonWebsitModel> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n\n}\n\nclass DataListBean {\n\n  String icon;\n  String link;\n  String name;\n  int id;\n  int order;\n  int visible;\n\n  static DataListBean fromMap(Map<String, dynamic> map) {\n    DataListBean dataListBean = new DataListBean();\n    dataListBean.icon = map['icon'];\n    dataListBean.link = map['link'];\n    dataListBean.name = map['name'];\n    dataListBean.id = map['id'];\n    dataListBean.order = map['order'];\n    dataListBean.visible = map['visible'];\n    return dataListBean;\n  }\n\n  static List<DataListBean> fromMapList(dynamic mapList) {\n    List<DataListBean> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n\n  Map<String, dynamic> toMap() {\n    var map = Map<String, dynamic>();\n    map[\"icon\"] = icon;\n    map[\"link\"] = link;\n    map[\"name\"] = name;\n    map[\"id\"] = id;\n    map[\"web_order\"] = order;\n    map[\"visible\"] = visible;\n\n    if (id != null) {\n      map[\"id\"] = id;\n    }\n\n    return map;\n  }\n\n}\n"
  },
  {
    "path": "lib/model/common_website_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass CommonWebsiteModel {\n\n  int errorCode;\n  String errorMsg;\n  List<CommonWebsiteData> data;\n\n  CommonWebsiteModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory CommonWebsiteModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new CommonWebsiteModel.fromJson(json.decode(jsonStr)) : new CommonWebsiteModel.fromJson(jsonStr);\n\n  CommonWebsiteModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : [];\n\n    for (var dataItem in data == null ? [] : jsonRes['data']){\n      data.add(dataItem == null ? null : new CommonWebsiteData.fromJson(dataItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass CommonWebsiteData {\n\n  int id;\n  int order;\n  int visible;\n  String icon;\n  String link;\n  String name;\n\n  CommonWebsiteData.fromParams({this.id, this.order, this.visible, this.icon, this.link, this.name});\n\n  CommonWebsiteData.fromJson(jsonRes) {\n    id = jsonRes['id'];\n    order = jsonRes['order'];\n    visible = jsonRes['visible'];\n    icon = jsonRes['icon'];\n    link = jsonRes['link'];\n    name = jsonRes['name'];\n  }\n\n  @override\n  String toString() {\n    return '{\"id\": $id,\"order\": $order,\"visible\": $visible,\"icon\": ${icon != null?'${json.encode(icon)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"name\": ${name != null?'${json.encode(name)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/hotword_model.dart",
    "content": "class HotwordModel {\n\n  String errorMsg;\n  int errorCode;\n  List<DataListBean> data;\n\n  static HotwordModel fromMap(Map<String, dynamic> map) {\n    HotwordModel hotword_model = new HotwordModel();\n    hotword_model.errorMsg = map['errorMsg'];\n    hotword_model.errorCode = map['errorCode'];\n    hotword_model.data = DataListBean.fromMapList(map['data']);\n    return hotword_model;\n  }\n\n  static List<HotwordModel> fromMapList(dynamic mapList) {\n    List<HotwordModel> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n\n}\n\nclass DataListBean {\n\n  String link;\n  String name;\n  int id;\n  int order;\n  int visible;\n\n  static DataListBean fromMap(Map<String, dynamic> map) {\n    DataListBean dataListBean = new DataListBean();\n    dataListBean.link = map['link'];\n    dataListBean.name = map['name'];\n    dataListBean.id = map['id'];\n    dataListBean.order = map['order'];\n    dataListBean.visible = map['visible'];\n    return dataListBean;\n  }\n\n  static List<DataListBean> fromMapList(dynamic mapList) {\n    List<DataListBean> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n}\n"
  },
  {
    "path": "lib/model/hotword_result_model.dart",
    "content": "class HotwordResultModel {\n\n  String errorMsg;\n  int errorCode;\n  DataBean data;\n\n  static HotwordResultModel fromMap(Map<String, dynamic> map) {\n    HotwordResultModel hotword_result_model = new HotwordResultModel();\n    hotword_result_model.errorMsg = map['errorMsg'];\n    hotword_result_model.errorCode = map['errorCode'];\n    hotword_result_model.data = DataBean.fromMap(map['data']);\n    return hotword_result_model;\n  }\n\n  static List<HotwordResultModel> fromMapList(dynamic mapList) {\n    List<HotwordResultModel> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n\n}\n\nclass DataBean {\n  bool over;\n  int curPage;\n  int offset;\n  int pageCount;\n  int size;\n  int total;\n  List<DatasListBean> datas;\n\n  static DataBean fromMap(Map<String, dynamic> map) {\n    DataBean dataBean = new DataBean();\n    dataBean.over = map['over'];\n    dataBean.curPage = map['curPage'];\n    dataBean.offset = map['offset'];\n    dataBean.pageCount = map['pageCount'];\n    dataBean.size = map['size'];\n    dataBean.total = map['total'];\n    dataBean.datas = DatasListBean.fromMapList(map['datas']);\n    return dataBean;\n  }\n\n  static List<DataBean> fromMapList(dynamic mapList) {\n    List<DataBean> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n}\n\nclass DatasListBean {\n\n  String apkLink;\n  String author;\n  String chapterName;\n  String desc;\n  String envelopePic;\n  String link;\n  String niceDate;\n  String origin;\n  String projectLink;\n  String superChapterName;\n  String title;\n  bool collect;\n  bool fresh;\n  int chapterId;\n  int courseId;\n  int id;\n  int publishTime;\n  int superChapterId;\n  int type;\n  int userId;\n  int visible;\n  int zan;\n  List<TagsListBean> tags;\n\n  static DatasListBean fromMap(Map<String, dynamic> map) {\n    DatasListBean datasListBean = new DatasListBean();\n    datasListBean.apkLink = map['apkLink'];\n    datasListBean.author = map['author'];\n    datasListBean.chapterName = map['chapterName'];\n    datasListBean.desc = map['desc'];\n    datasListBean.envelopePic = map['envelopePic'];\n    datasListBean.link = map['link'];\n    datasListBean.niceDate = map['niceDate'];\n    datasListBean.origin = map['origin'];\n    datasListBean.projectLink = map['projectLink'];\n    datasListBean.superChapterName = map['superChapterName'];\n    datasListBean.title = map['title'];\n    datasListBean.collect = map['collect'];\n    datasListBean.fresh = map['fresh'];\n    datasListBean.chapterId = map['chapterId'];\n    datasListBean.courseId = map['courseId'];\n    datasListBean.id = map['id'];\n    datasListBean.publishTime = map['publishTime'];\n    datasListBean.superChapterId = map['superChapterId'];\n    datasListBean.type = map['type'];\n    datasListBean.userId = map['userId'];\n    datasListBean.visible = map['visible'];\n    datasListBean.zan = map['zan'];\n    datasListBean.tags = TagsListBean.fromMapList(map['tags']);\n    return datasListBean;\n  }\n\n  static List<DatasListBean> fromMapList(dynamic mapList) {\n    List<DatasListBean> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n}\n\nclass TagsListBean {\n  String name;\n  String url;\n\n  static TagsListBean fromMap(Map<String, dynamic> map) {\n    TagsListBean tagsListBean = new TagsListBean();\n    tagsListBean.name = map['name'];\n    tagsListBean.url = map['url'];\n    return tagsListBean;\n  }\n\n  static List<TagsListBean> fromMapList(dynamic mapList) {\n    List<TagsListBean> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n}\n"
  },
  {
    "path": "lib/model/navi_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass NaviModel {\n\n  int errorCode;\n  String errorMsg;\n  List<NaviData> data;\n\n  NaviModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory NaviModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new NaviModel.fromJson(json.decode(jsonStr)) : new NaviModel.fromJson(jsonStr);\n\n  NaviModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : [];\n\n    for (var dataItem in data == null ? [] : jsonRes['data']){\n      data.add(dataItem == null ? null : new NaviData.fromJson(dataItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass NaviData {\n\n  int cid;\n  String name;\n  List<NaviArticle> articles;\n\n  NaviData.fromParams({this.cid, this.name, this.articles});\n\n  NaviData.fromJson(jsonRes) {\n    cid = jsonRes['cid'];\n    name = jsonRes['name'];\n    articles = jsonRes['articles'] == null ? null : [];\n\n    for (var articlesItem in articles == null ? [] : jsonRes['articles']){\n      articles.add(articlesItem == null ? null : new NaviArticle.fromJson(articlesItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"cid\": $cid,\"name\": ${name != null?'${json.encode(name)}':'null'},\"articles\": $articles}';\n  }\n}\n\nclass NaviArticle {\n\n  int chapterId;\n  int courseId;\n  int id;\n  int publishTime;\n  int superChapterId;\n  int type;\n  int userId;\n  int visible;\n  int zan;\n  bool collect;\n  bool fresh;\n  String apkLink;\n  String author;\n  String chapterName;\n  String desc;\n  String envelopePic;\n  String link;\n  String niceDate;\n  String origin;\n  String projectLink;\n  String superChapterName;\n  String title;\n  List<dynamic> tags;\n\n  NaviArticle.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});\n\n  NaviArticle.fromJson(jsonRes) {\n    chapterId = jsonRes['chapterId'];\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    publishTime = jsonRes['publishTime'];\n    superChapterId = jsonRes['superChapterId'];\n    type = jsonRes['type'];\n    userId = jsonRes['userId'];\n    visible = jsonRes['visible'];\n    zan = jsonRes['zan'];\n    collect = jsonRes['collect'];\n    fresh = jsonRes['fresh'];\n    apkLink = jsonRes['apkLink'];\n    author = jsonRes['author'];\n    chapterName = jsonRes['chapterName'];\n    desc = jsonRes['desc'];\n    envelopePic = jsonRes['envelopePic'];\n    link = jsonRes['link'];\n    niceDate = jsonRes['niceDate'];\n    origin = jsonRes['origin'];\n    projectLink = jsonRes['projectLink'];\n    superChapterName = jsonRes['superChapterName'];\n    title = jsonRes['title'];\n    tags = jsonRes['tags'] == null ? null : [];\n\n    for (var tagsItem in tags == null ? [] : jsonRes['tags']){\n      tags.add(tagsItem);\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"chapterId\": $chapterId,\"courseId\": $courseId,\"id\": $id,\"publishTime\": $publishTime,\"superChapterId\": $superChapterId,\"type\": $type,\"userId\": $userId,\"visible\": $visible,\"zan\": $zan,\"collect\": $collect,\"fresh\": $fresh,\"apkLink\": ${apkLink != null?'${json.encode(apkLink)}':'null'},\"author\": ${author != null?'${json.encode(author)}':'null'},\"chapterName\": ${chapterName != null?'${json.encode(chapterName)}':'null'},\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"envelopePic\": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"niceDate\": ${niceDate != null?'${json.encode(niceDate)}':'null'},\"origin\": ${origin != null?'${json.encode(origin)}':'null'},\"projectLink\": ${projectLink != null?'${json.encode(projectLink)}':'null'},\"superChapterName\": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'},\"tags\": $tags}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/pretty_model.dart",
    "content": "class PrettyModel {\n\n\n  bool error;\n  List<ResultsListBean> results;\n\n  static PrettyModel fromMap(Map<String, dynamic> map) {\n    PrettyModel pretty_model = new PrettyModel();\n    pretty_model.error = map['error'];\n    pretty_model.results = ResultsListBean.fromMapList(map['results']);\n    return pretty_model;\n  }\n\n  static List<PrettyModel> fromMapList(dynamic mapList) {\n    List<PrettyModel> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n\n}\n\nclass ResultsListBean {\n\n  String _id;\n  String createdAt;\n  String desc;\n  String publishedAt;\n  String source;\n  String type;\n  String url;\n  String who;\n  bool used;\n\n  static ResultsListBean fromMap(Map<String, dynamic> map) {\n    ResultsListBean resultsListBean = new ResultsListBean();\n    resultsListBean._id = map['_id'];\n    resultsListBean.createdAt = map['createdAt'];\n    resultsListBean.desc = map['desc'];\n    resultsListBean.publishedAt = map['publishedAt'];\n    resultsListBean.source = map['source'];\n    resultsListBean.type = map['type'];\n    resultsListBean.url = map['url'];\n    resultsListBean.who = map['who'];\n    resultsListBean.used = map['used'];\n    return resultsListBean;\n  }\n\n  static List<ResultsListBean> fromMapList(dynamic mapList) {\n    List<ResultsListBean> list = new List(mapList.length);\n    for (int i = 0; i < mapList.length; i++) {\n      list[i] = fromMap(mapList[i]);\n    }\n    return list;\n  }\n}\n"
  },
  {
    "path": "lib/model/project_tree_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass ProjectTreeModel {\n\n  int errorCode;\n  String errorMsg;\n  List<ProjectTreeData> data;\n\n  ProjectTreeModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory ProjectTreeModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ProjectTreeModel.fromJson(json.decode(jsonStr)) : new ProjectTreeModel.fromJson(jsonStr);\n\n  ProjectTreeModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : [];\n\n    for (var dataItem in data == null ? [] : jsonRes['data']){\n      data.add(dataItem == null ? null : new ProjectTreeData.fromJson(dataItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass ProjectTreeData {\n\n  int courseId;\n  int id;\n  int order;\n  int parentChapterId;\n  int visible;\n  bool userControlSetTop;\n  String name;\n  List<dynamic> children;\n\n  ProjectTreeData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});\n\n  ProjectTreeData.fromJson(jsonRes) {\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    order = jsonRes['order'];\n    parentChapterId = jsonRes['parentChapterId'];\n    visible = jsonRes['visible'];\n    userControlSetTop = jsonRes['userControlSetTop'];\n    name = jsonRes['name'];\n    children = jsonRes['children'] == null ? null : [];\n\n    for (var childrenItem in children == null ? [] : jsonRes['children']){\n      children.add(childrenItem);\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"courseId\": $courseId,\"id\": $id,\"order\": $order,\"parentChapterId\": $parentChapterId,\"visible\": $visible,\"userControlSetTop\": $userControlSetTop,\"name\": ${name != null?'${json.encode(name)}':'null'},\"children\": $children}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/projectlist_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass ProjectTreeListModel {\n\n  int errorCode;\n  String errorMsg;\n  ProjectTreeListData data;\n\n  ProjectTreeListModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory ProjectTreeListModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new ProjectTreeListModel.fromJson(json.decode(jsonStr)) : new ProjectTreeListModel.fromJson(jsonStr);\n\n  ProjectTreeListModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : new ProjectTreeListData.fromJson(jsonRes['data']);\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass ProjectTreeListData {\n\n  int curPage;\n  int offset;\n  int pageCount;\n  int size;\n  int total;\n  bool over;\n  List<ProjectTreeListDatas> datas;\n\n  ProjectTreeListData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});\n\n  ProjectTreeListData.fromJson(jsonRes) {\n    curPage = jsonRes['curPage'];\n    offset = jsonRes['offset'];\n    pageCount = jsonRes['pageCount'];\n    size = jsonRes['size'];\n    total = jsonRes['total'];\n    over = jsonRes['over'];\n    datas = jsonRes['datas'] == null ? null : [];\n\n    for (var datasItem in datas == null ? [] : jsonRes['datas']){\n      datas.add(datasItem == null ? null : new ProjectTreeListDatas.fromJson(datasItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"curPage\": $curPage,\"offset\": $offset,\"pageCount\": $pageCount,\"size\": $size,\"total\": $total,\"over\": $over,\"datas\": $datas}';\n  }\n}\n\nclass ProjectTreeListDatas {\n\n  int chapterId;\n  int courseId;\n  int id;\n  int publishTime;\n  int superChapterId;\n  int type;\n  int userId;\n  int visible;\n  int zan;\n  bool collect;\n  bool fresh;\n  String apkLink;\n  String author;\n  String chapterName;\n  String desc;\n  String envelopePic;\n  String link;\n  String niceDate;\n  String origin;\n  String projectLink;\n  String superChapterName;\n  String title;\n  List<ProjectTreeListTag> tags;\n\n  ProjectTreeListDatas.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});\n\n  ProjectTreeListDatas.fromJson(jsonRes) {\n    chapterId = jsonRes['chapterId'];\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    publishTime = jsonRes['publishTime'];\n    superChapterId = jsonRes['superChapterId'];\n    type = jsonRes['type'];\n    userId = jsonRes['userId'];\n    visible = jsonRes['visible'];\n    zan = jsonRes['zan'];\n    collect = jsonRes['collect'];\n    fresh = jsonRes['fresh'];\n    apkLink = jsonRes['apkLink'];\n    author = jsonRes['author'];\n    chapterName = jsonRes['chapterName'];\n    desc = jsonRes['desc'];\n    envelopePic = jsonRes['envelopePic'];\n    link = jsonRes['link'];\n    niceDate = jsonRes['niceDate'];\n    origin = jsonRes['origin'];\n    projectLink = jsonRes['projectLink'];\n    superChapterName = jsonRes['superChapterName'];\n    title = jsonRes['title'];\n    tags = jsonRes['tags'] == null ? null : [];\n\n    for (var tagsItem in tags == null ? [] : jsonRes['tags']){\n      tags.add(tagsItem == null ? null : new ProjectTreeListTag.fromJson(tagsItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"chapterId\": $chapterId,\"courseId\": $courseId,\"id\": $id,\"publishTime\": $publishTime,\"superChapterId\": $superChapterId,\"type\": $type,\"userId\": $userId,\"visible\": $visible,\"zan\": $zan,\"collect\": $collect,\"fresh\": $fresh,\"apkLink\": ${apkLink != null?'${json.encode(apkLink)}':'null'},\"author\": ${author != null?'${json.encode(author)}':'null'},\"chapterName\": ${chapterName != null?'${json.encode(chapterName)}':'null'},\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"envelopePic\": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"niceDate\": ${niceDate != null?'${json.encode(niceDate)}':'null'},\"origin\": ${origin != null?'${json.encode(origin)}':'null'},\"projectLink\": ${projectLink != null?'${json.encode(projectLink)}':'null'},\"superChapterName\": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'},\"tags\": $tags}';\n  }\n}\n\nclass ProjectTreeListTag {\n\n  String name;\n  String url;\n\n  ProjectTreeListTag.fromParams({this.name, this.url});\n\n  ProjectTreeListTag.fromJson(jsonRes) {\n    name = jsonRes['name'];\n    url = jsonRes['url'];\n  }\n\n  @override\n  String toString() {\n    return '{\"name\": ${name != null?'${json.encode(name)}':'null'},\"url\": ${url != null?'${json.encode(url)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/system_tree_content_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass SystemTreeContentModel {\n\n  int errorCode;\n  String errorMsg;\n  SystemTreeContentData data;\n\n  SystemTreeContentModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory SystemTreeContentModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new SystemTreeContentModel.fromJson(json.decode(jsonStr)) : new SystemTreeContentModel.fromJson(jsonStr);\n\n  SystemTreeContentModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : new SystemTreeContentData.fromJson(jsonRes['data']);\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass SystemTreeContentData {\n\n  int curPage;\n  int offset;\n  int pageCount;\n  int size;\n  int total;\n  bool over;\n  List<SystemTreeContentChild> datas;\n\n  SystemTreeContentData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});\n\n  SystemTreeContentData.fromJson(jsonRes) {\n    curPage = jsonRes['curPage'];\n    offset = jsonRes['offset'];\n    pageCount = jsonRes['pageCount'];\n    size = jsonRes['size'];\n    total = jsonRes['total'];\n    over = jsonRes['over'];\n    datas = jsonRes['datas'] == null ? null : [];\n\n    for (var datasItem in datas == null ? [] : jsonRes['datas']){\n      datas.add(datasItem == null ? null : new SystemTreeContentChild.fromJson(datasItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"curPage\": $curPage,\"offset\": $offset,\"pageCount\": $pageCount,\"size\": $size,\"total\": $total,\"over\": $over,\"datas\": $datas}';\n  }\n}\n\nclass SystemTreeContentChild {\n\n  int chapterId;\n  int courseId;\n  int id;\n  int publishTime;\n  int superChapterId;\n  int type;\n  int userId;\n  int visible;\n  int zan;\n  bool collect;\n  bool fresh;\n  String apkLink;\n  String author;\n  String chapterName;\n  String desc;\n  String envelopePic;\n  String link;\n  String niceDate;\n  String origin;\n  String projectLink;\n  String superChapterName;\n  String title;\n  List<dynamic> tags;\n\n  SystemTreeContentChild.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});\n\n  SystemTreeContentChild.fromJson(jsonRes) {\n    chapterId = jsonRes['chapterId'];\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    publishTime = jsonRes['publishTime'];\n    superChapterId = jsonRes['superChapterId'];\n    type = jsonRes['type'];\n    userId = jsonRes['userId'];\n    visible = jsonRes['visible'];\n    zan = jsonRes['zan'];\n    collect = jsonRes['collect'];\n    fresh = jsonRes['fresh'];\n    apkLink = jsonRes['apkLink'];\n    author = jsonRes['author'];\n    chapterName = jsonRes['chapterName'];\n    desc = jsonRes['desc'];\n    envelopePic = jsonRes['envelopePic'];\n    link = jsonRes['link'];\n    niceDate = jsonRes['niceDate'];\n    origin = jsonRes['origin'];\n    projectLink = jsonRes['projectLink'];\n    superChapterName = jsonRes['superChapterName'];\n    title = jsonRes['title'];\n    tags = jsonRes['tags'] == null ? null : [];\n\n    for (var tagsItem in tags == null ? [] : jsonRes['tags']){\n      tags.add(tagsItem);\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"chapterId\": $chapterId,\"courseId\": $courseId,\"id\": $id,\"publishTime\": $publishTime,\"superChapterId\": $superChapterId,\"type\": $type,\"userId\": $userId,\"visible\": $visible,\"zan\": $zan,\"collect\": $collect,\"fresh\": $fresh,\"apkLink\": ${apkLink != null?'${json.encode(apkLink)}':'null'},\"author\": ${author != null?'${json.encode(author)}':'null'},\"chapterName\": ${chapterName != null?'${json.encode(chapterName)}':'null'},\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"envelopePic\": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"niceDate\": ${niceDate != null?'${json.encode(niceDate)}':'null'},\"origin\": ${origin != null?'${json.encode(origin)}':'null'},\"projectLink\": ${projectLink != null?'${json.encode(projectLink)}':'null'},\"superChapterName\": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'},\"tags\": $tags}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/system_tree_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass SystemTreeModel {\n\n  int errorCode;\n  String errorMsg;\n  List<SystemTreeData> data;\n\n  SystemTreeModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory SystemTreeModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new SystemTreeModel.fromJson(json.decode(jsonStr)) : new SystemTreeModel.fromJson(jsonStr);\n\n  SystemTreeModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : [];\n\n    for (var dataItem in data == null ? [] : jsonRes['data']){\n      data.add(dataItem == null ? null : new SystemTreeData.fromJson(dataItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass SystemTreeData {\n\n  int courseId;\n  int id;\n  int order;\n  int parentChapterId;\n  int visible;\n  bool userControlSetTop;\n  String name;\n  List<SystemTreeChild> children;\n\n  SystemTreeData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});\n\n  SystemTreeData.fromJson(jsonRes) {\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    order = jsonRes['order'];\n    parentChapterId = jsonRes['parentChapterId'];\n    visible = jsonRes['visible'];\n    userControlSetTop = jsonRes['userControlSetTop'];\n    name = jsonRes['name'];\n    children = jsonRes['children'] == null ? null : [];\n\n    for (var childrenItem in children == null ? [] : jsonRes['children']){\n      children.add(childrenItem == null ? null : new SystemTreeChild.fromJson(childrenItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"courseId\": $courseId,\"id\": $id,\"order\": $order,\"parentChapterId\": $parentChapterId,\"visible\": $visible,\"userControlSetTop\": $userControlSetTop,\"name\": ${name != null?'${json.encode(name)}':'null'},\"children\": $children}';\n  }\n}\n\nclass SystemTreeChild {\n\n  int courseId;\n  int id;\n  int order;\n  int parentChapterId;\n  int visible;\n  bool userControlSetTop;\n  String name;\n  List<dynamic> children;\n\n  SystemTreeChild.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});\n\n  SystemTreeChild.fromJson(jsonRes) {\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    order = jsonRes['order'];\n    parentChapterId = jsonRes['parentChapterId'];\n    visible = jsonRes['visible'];\n    userControlSetTop = jsonRes['userControlSetTop'];\n    name = jsonRes['name'];\n    children = jsonRes['children'] == null ? null : [];\n\n    for (var childrenItem in children == null ? [] : jsonRes['children']){\n      children.add(childrenItem);\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"courseId\": $courseId,\"id\": $id,\"order\": $order,\"parentChapterId\": $parentChapterId,\"visible\": $visible,\"userControlSetTop\": $userControlSetTop,\"name\": ${name != null?'${json.encode(name)}':'null'},\"children\": $children}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/todo_item.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass TodoItem extends StatelessWidget {\n  String _itemName;\n  String _dateCreated;\n  int _id;\n\n  TodoItem(this._itemName, this._dateCreated);\n\n  TodoItem.map(dynamic obj) {\n    this._itemName = obj[\"itemName\"];\n    this._dateCreated = obj[\"dateCreated\"];\n    this._id = obj[\"id\"];\n  }\n\n  String get itemName => _itemName;\n  String get dateCreated => _dateCreated;\n  int get id => _id;\n\n  Map<String, dynamic> toMap() {\n    var map = Map<String, dynamic>();\n    map[\"itemName\"] = _itemName;\n    map[\"dateCreated\"] = _dateCreated;\n\n    if (_id != null) {\n      map[\"id\"] = _id;\n    }\n\n    return map;\n  }\n\n  TodoItem.fromMap(Map<String, dynamic> map) {\n    this._itemName = map[\"itemName\"];\n    this._dateCreated = map[\"dateCreated\"];\n    this._id = map[\"id\"];\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Container(\n      margin: const EdgeInsets.all(8.0),\n      child: Row(\n        crossAxisAlignment: CrossAxisAlignment.start,\n        children: <Widget>[\n          //solve the overflow problem\n          Expanded(\n            \n            child: Column(\n              crossAxisAlignment: CrossAxisAlignment.start,\n              children: <Widget>[\n                Text(\n                  _itemName,\n                  style: TextStyle(\n                      color: Colors.black,\n                      fontWeight: FontWeight.bold,\n                      fontSize: 18.0),\n                  maxLines: 1,\n                  overflow: TextOverflow.ellipsis,\n                ),\n                Container(\n                  margin: const EdgeInsets.only(top: 10.0),\n                  child: Text(\n                    \"Created on: $_dateCreated\",\n                    style: TextStyle(\n                        color: Colors.black,\n                        fontSize: 12.0,\n                        fontStyle: FontStyle.italic),\n                  ),\n                ),\n              ],\n            ),\n          )\n        ],\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/model/todolist_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass TodoListModel {\n\n  int errorCode;\n  String errorMsg;\n  TodoListData data;\n\n  TodoListModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory TodoListModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new TodoListModel.fromJson(json.decode(jsonStr)) : new TodoListModel.fromJson(jsonStr);\n  \n  TodoListModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : new TodoListData.fromJson(jsonRes['data']);\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass TodoListData {\n\n  int type;\n  List<TodoListDatas> doneList;\n  List<TodoListDatas> todoList;\n\n  TodoListData.fromParams({this.type, this.doneList, this.todoList});\n  \n  TodoListData.fromJson(jsonRes) {\n    type = jsonRes['type'];\n    doneList = jsonRes['doneList'] == null ? null : [];\n\n    for (var doneListItem in doneList == null ? [] : jsonRes['doneList']){\n            doneList.add(doneListItem == null ? null : new TodoListDatas.fromJson(doneListItem));\n    }\n\n    todoList = jsonRes['todoList'] == null ? null : [];\n\n    for (var todoListItem in todoList == null ? [] : jsonRes['todoList']){\n            todoList.add(todoListItem == null ? null : new TodoListDatas.fromJson(todoListItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"type\": $type,\"doneList\": $doneList,\"todoList\": $todoList}';\n  }\n}\n\nclass TodoListDatas {\n\n  int date;\n  List<TodoData> todoList;\n\n  TodoListDatas.fromParams({this.date, this.todoList});\n  \n  TodoListDatas.fromJson(jsonRes) {\n    date = jsonRes['date'];\n    todoList = jsonRes['todoList'] == null ? null : [];\n\n    for (var todoListItem in todoList == null ? [] : jsonRes['todoList']){\n            todoList.add(todoListItem == null ? null : new TodoData.fromJson(todoListItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"date\": $date,\"todoList\": $todoList}';\n  }\n}\n\nclass TodoData {\n\n  TodoData();\n\n  TodoData.origin(String title){\n    this.title = title;\n  }\n\n  int completeDate;\n  int date;\n  int id;\n  int priority;\n  int status;\n  int type;\n  int userId;\n  String completeDateStr;\n  String content;\n  String dateStr;\n  String title;\n\n  TodoData.fromParams({this.completeDate, this.date, this.id, this.priority, this.status, this.type, this.userId, this.completeDateStr, this.content, this.dateStr, this.title});\n  \n  TodoData.fromJson(jsonRes) {\n    completeDate = jsonRes['completeDate'];\n    date = jsonRes['date'];\n    id = jsonRes['id'];\n    priority = jsonRes['priority'];\n    status = jsonRes['status'];\n    type = jsonRes['type'];\n    userId = jsonRes['userId'];\n    completeDateStr = jsonRes['completeDateStr'];\n    content = jsonRes['content'];\n    dateStr = jsonRes['dateStr'];\n    title = jsonRes['title'];\n  }\n\n  @override\n  String toString() {\n    return '{\"completeDate\": $completeDate,\"date\": $date,\"id\": $id,\"priority\": $priority,\"status\": $status,\"type\": $type,\"userId\": $userId,\"completeDateStr\": ${completeDateStr != null?'${json.encode(completeDateStr)}':'null'},\"content\": ${content != null?'${json.encode(content)}':'null'},\"dateStr\": ${dateStr != null?'${json.encode(dateStr)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'}}';\n  }\n}\n\n\n\n"
  },
  {
    "path": "lib/model/user_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass UserModel {\n\n  int errorCode;\n  String errorMsg;\n  UserData data;\n\n  UserModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory UserModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new UserModel.fromJson(json.decode(jsonStr)) : new UserModel.fromJson(jsonStr);\n  \n  UserModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : new UserData.fromJson(jsonRes['data']);\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass UserData {\n\n  int id;\n  int type;\n  String email;\n  String icon;\n  String password;\n  String token;\n  String username;\n  List<dynamic> chapterTops;\n  List<int> collectIds;\n\n  UserData.fromParams({this.id, this.type, this.email, this.icon, this.password, this.token, this.username, this.chapterTops, this.collectIds});\n  \n  UserData.fromJson(jsonRes) {\n    id = jsonRes['id'];\n    type = jsonRes['type'];\n    email = jsonRes['email'];\n    icon = jsonRes['icon'];\n    password = jsonRes['password'];\n    token = jsonRes['token'];\n    username = jsonRes['username'];\n    chapterTops = jsonRes['chapterTops'] == null ? null : [];\n\n    for (var chapterTopsItem in chapterTops == null ? [] : jsonRes['chapterTops']){\n            chapterTops.add(chapterTopsItem);\n    }\n\n    collectIds = jsonRes['collectIds'] == null ? null : [];\n\n    for (var collectIdsItem in collectIds == null ? [] : jsonRes['collectIds']){\n            collectIds.add(collectIdsItem);\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"id\": $id,\"type\": $type,\"email\": ${email != null?'${json.encode(email)}':'null'},\"icon\": ${icon != null?'${json.encode(icon)}':'null'},\"password\": ${password != null?'${json.encode(password)}':'null'},\"token\": ${token != null?'${json.encode(token)}':'null'},\"username\": ${username != null?'${json.encode(username)}':'null'},\"chapterTops\": $chapterTops,\"collectIds\": $collectIds}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/website_collection_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass WebsiteCollectionModel {\n\n  int errorCode;\n  String errorMsg;\n  List<WebsiteCollectionData> data;\n\n  WebsiteCollectionModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory WebsiteCollectionModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WebsiteCollectionModel.fromJson(json.decode(jsonStr)) : new WebsiteCollectionModel.fromJson(jsonStr);\n  \n  WebsiteCollectionModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : [];\n\n    for (var dataItem in data == null ? [] : jsonRes['data']){\n            data.add(dataItem == null ? null : new WebsiteCollectionData.fromJson(dataItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass WebsiteCollectionData {\n\n  int id;\n  int order;\n  int userId;\n  int visible;\n  String desc;\n  String icon;\n  String link;\n  String name;\n\n  WebsiteCollectionData.fromParams({this.id, this.order, this.userId, this.visible, this.desc, this.icon, this.link, this.name});\n  \n  WebsiteCollectionData.fromJson(jsonRes) {\n    id = jsonRes['id'];\n    order = jsonRes['order'];\n    userId = jsonRes['userId'];\n    visible = jsonRes['visible'];\n    desc = jsonRes['desc'];\n    icon = jsonRes['icon'];\n    link = jsonRes['link'];\n    name = jsonRes['name'];\n  }\n\n  @override\n  String toString() {\n    return '{\"id\": $id,\"order\": $order,\"userId\": $userId,\"visible\": $visible,\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"icon\": ${icon != null?'${json.encode(icon)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"name\": ${name != null?'${json.encode(name)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/wx_article_content_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass WxArticleContentModel {\n\n  int errorCode;\n  String errorMsg;\n  WxArticleContentData data;\n\n  WxArticleContentModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory WxArticleContentModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WxArticleContentModel.fromJson(json.decode(jsonStr)) : new WxArticleContentModel.fromJson(jsonStr);\n\n  WxArticleContentModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : new WxArticleContentData.fromJson(jsonRes['data']);\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass WxArticleContentData {\n\n  int curPage;\n  int offset;\n  int pageCount;\n  int size;\n  int total;\n  bool over;\n  List<WxArticleContentDatas> datas;\n\n  WxArticleContentData.fromParams({this.curPage, this.offset, this.pageCount, this.size, this.total, this.over, this.datas});\n\n  WxArticleContentData.fromJson(jsonRes) {\n    curPage = jsonRes['curPage'];\n    offset = jsonRes['offset'];\n    pageCount = jsonRes['pageCount'];\n    size = jsonRes['size'];\n    total = jsonRes['total'];\n    over = jsonRes['over'];\n    datas = jsonRes['datas'] == null ? null : [];\n\n    for (var datasItem in datas == null ? [] : jsonRes['datas']){\n      datas.add(datasItem == null ? null : new WxArticleContentDatas.fromJson(datasItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"curPage\": $curPage,\"offset\": $offset,\"pageCount\": $pageCount,\"size\": $size,\"total\": $total,\"over\": $over,\"datas\": $datas}';\n  }\n}\n\nclass WxArticleContentDatas {\n\n  int chapterId;\n  int courseId;\n  int id;\n  int publishTime;\n  int superChapterId;\n  int type;\n  int userId;\n  int visible;\n  int zan;\n  bool collect;\n  bool fresh;\n  String apkLink;\n  String author;\n  String chapterName;\n  String desc;\n  String envelopePic;\n  String link;\n  String niceDate;\n  String origin;\n  String projectLink;\n  String superChapterName;\n  String title;\n  List<WxArticleContentTags> tags;\n\n  WxArticleContentDatas.fromParams({this.chapterId, this.courseId, this.id, this.publishTime, this.superChapterId, this.type, this.userId, this.visible, this.zan, this.collect, this.fresh, this.apkLink, this.author, this.chapterName, this.desc, this.envelopePic, this.link, this.niceDate, this.origin, this.projectLink, this.superChapterName, this.title, this.tags});\n\n  WxArticleContentDatas.fromJson(jsonRes) {\n    chapterId = jsonRes['chapterId'];\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    publishTime = jsonRes['publishTime'];\n    superChapterId = jsonRes['superChapterId'];\n    type = jsonRes['type'];\n    userId = jsonRes['userId'];\n    visible = jsonRes['visible'];\n    zan = jsonRes['zan'];\n    collect = jsonRes['collect'];\n    fresh = jsonRes['fresh'];\n    apkLink = jsonRes['apkLink'];\n    author = jsonRes['author'];\n    chapterName = jsonRes['chapterName'];\n    desc = jsonRes['desc'];\n    envelopePic = jsonRes['envelopePic'];\n    link = jsonRes['link'];\n    niceDate = jsonRes['niceDate'];\n    origin = jsonRes['origin'];\n    projectLink = jsonRes['projectLink'];\n    superChapterName = jsonRes['superChapterName'];\n    title = jsonRes['title'];\n    tags = jsonRes['tags'] == null ? null : [];\n\n    for (var tagsItem in tags == null ? [] : jsonRes['tags']){\n      tags.add(tagsItem == null ? null : new WxArticleContentTags.fromJson(tagsItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"chapterId\": $chapterId,\"courseId\": $courseId,\"id\": $id,\"publishTime\": $publishTime,\"superChapterId\": $superChapterId,\"type\": $type,\"userId\": $userId,\"visible\": $visible,\"zan\": $zan,\"collect\": $collect,\"fresh\": $fresh,\"apkLink\": ${apkLink != null?'${json.encode(apkLink)}':'null'},\"author\": ${author != null?'${json.encode(author)}':'null'},\"chapterName\": ${chapterName != null?'${json.encode(chapterName)}':'null'},\"desc\": ${desc != null?'${json.encode(desc)}':'null'},\"envelopePic\": ${envelopePic != null?'${json.encode(envelopePic)}':'null'},\"link\": ${link != null?'${json.encode(link)}':'null'},\"niceDate\": ${niceDate != null?'${json.encode(niceDate)}':'null'},\"origin\": ${origin != null?'${json.encode(origin)}':'null'},\"projectLink\": ${projectLink != null?'${json.encode(projectLink)}':'null'},\"superChapterName\": ${superChapterName != null?'${json.encode(superChapterName)}':'null'},\"title\": ${title != null?'${json.encode(title)}':'null'},\"tags\": $tags}';\n  }\n}\n\nclass WxArticleContentTags {\n\n  String name;\n  String url;\n\n  WxArticleContentTags.fromParams({this.name, this.url});\n\n  WxArticleContentTags.fromJson(jsonRes) {\n    name = jsonRes['name'];\n    url = jsonRes['url'];\n  }\n\n  @override\n  String toString() {\n    return '{\"name\": ${name != null?'${json.encode(name)}':'null'},\"url\": ${url != null?'${json.encode(url)}':'null'}}';\n  }\n}\n\n"
  },
  {
    "path": "lib/model/wx_article_title_model.dart",
    "content": "import 'dart:convert' show json;\n\nclass WxArticleTitleModel {\n\n  int errorCode;\n  String errorMsg;\n  List<WxArticleTitleData> data;\n\n  WxArticleTitleModel.fromParams({this.errorCode, this.errorMsg, this.data});\n\n  factory WxArticleTitleModel(jsonStr) => jsonStr == null ? null : jsonStr is String ? new WxArticleTitleModel.fromJson(json.decode(jsonStr)) : new WxArticleTitleModel.fromJson(jsonStr);\n\n  WxArticleTitleModel.fromJson(jsonRes) {\n    errorCode = jsonRes['errorCode'];\n    errorMsg = jsonRes['errorMsg'];\n    data = jsonRes['data'] == null ? null : [];\n\n    for (var dataItem in data == null ? [] : jsonRes['data']){\n      data.add(dataItem == null ? null : new WxArticleTitleData.fromJson(dataItem));\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"errorCode\": $errorCode,\"errorMsg\": ${errorMsg != null?'${json.encode(errorMsg)}':'null'},\"data\": $data}';\n  }\n}\n\nclass WxArticleTitleData {\n\n  int courseId;\n  int id;\n  int order;\n  int parentChapterId;\n  int visible;\n  bool userControlSetTop;\n  String name;\n  List<dynamic> children;\n\n  WxArticleTitleData.fromParams({this.courseId, this.id, this.order, this.parentChapterId, this.visible, this.userControlSetTop, this.name, this.children});\n\n  WxArticleTitleData.fromJson(jsonRes) {\n    courseId = jsonRes['courseId'];\n    id = jsonRes['id'];\n    order = jsonRes['order'];\n    parentChapterId = jsonRes['parentChapterId'];\n    visible = jsonRes['visible'];\n    userControlSetTop = jsonRes['userControlSetTop'];\n    name = jsonRes['name'];\n    children = jsonRes['children'] == null ? null : [];\n\n    for (var childrenItem in children == null ? [] : jsonRes['children']){\n      children.add(childrenItem);\n    }\n  }\n\n  @override\n  String toString() {\n    return '{\"courseId\": $courseId,\"id\": $id,\"order\": $order,\"parentChapterId\": $parentChapterId,\"visible\": $visible,\"userControlSetTop\": $userControlSetTop,\"name\": ${name != null?'${json.encode(name)}':'null'},\"children\": $children}';\n  }\n}\n\n"
  },
  {
    "path": "lib/splash_screen.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:intro_slider/intro_slider.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\nimport 'package:wanandroid_ngu/app.dart';\nclass SplashScreen extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() {\n    return new SplashScreenState() ;\n  }\n\n}\n\nclass SplashScreenState extends State<SplashScreen> {\n\n  List<Slide> slides = new List();\n\n  @override\n  void initState() {\n    super.initState();\n\n    slides.add(\n      new Slide(\n        title: \"Flutter\",\n        description:\n        \"Flutter是谷歌的移动UI框架，可以快速在iOS和Android上构建高质量的原生用户界面。 Flutter可以与现有的代码一起工作。在全世界，Flutter正在被越来越多的开发者和组织使用，并且Flutter是完全免费、开源的。\",\n        styleDescription: TextStyle(\n            color: Colors.white,\n            fontSize: 20.0,\n            fontFamily: 'Raleway'),\n        marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),\n        colorBegin: Color(0xffFFDAB9),\n        colorEnd: Color(0xff40E0D0),\n        directionColorBegin: Alignment.topLeft,\n        directionColorEnd: Alignment.bottomRight,\n      ),\n    );\n\n    slides.add(\n      new Slide(\n        title: \"Wanandroid\",\n        description:\n        \"这是一款使用Flutter写的WanAndroid客户端应用，在Android和IOS都完美运行,可以用来入门Flutter，简单明了，适合初学者,项目完全开源，如果本项目确实能够帮助到你学习Flutter，谢谢start，有问题请提交Issues,我会及时回复。\",\n        styleDescription: TextStyle(\n            color: Colors.white,\n            fontSize: 20.0,\n            fontFamily: 'Raleway'),\n        marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),\n        colorBegin: Color(0xffFFFACD),\n        colorEnd: Color(0xffFF6347),\n        directionColorBegin: Alignment.topLeft,\n        directionColorEnd: Alignment.bottomRight,\n      ),\n    );\n\n    slides.add(\n      new Slide(\n        title: \"Welcome\",\n        description:\n        \"赠人玫瑰，手有余香；\\n分享技术，传递快乐。\",\n        styleDescription: TextStyle(\n            color: Colors.white,\n            fontSize: 20.0,\n            fontFamily: 'Raleway'),\n        marginDescription: EdgeInsets.only(left: 20.0, right: 20.0, top: 20.0, bottom: 70.0),\n        colorBegin: Color(0xffFFA500),\n        colorEnd: Color(0xff7FFFD4),\n        directionColorBegin: Alignment.topLeft,\n        directionColorEnd: Alignment.bottomRight,\n      ),\n    );\n  }\n\n  void onDonePress() {\n    _setHasSkip();\n    Navigator.of(context).pushAndRemoveUntil(\n        new MaterialPageRoute(\n            builder: (context) => App()),\n            (route) => route == null);\n  }\n\n  void onSkipPress() {\n    _setHasSkip();\n    Navigator.of(context).pushAndRemoveUntil(\n        new MaterialPageRoute(\n            builder: (context) => App()),\n            (route) => route == null);\n  }\n\n  void _setHasSkip ()async {\n    SharedPreferences prefs = await SharedPreferences.getInstance();\n    await prefs.setBool(\"hasSkip\", true);\n  }\n\n\n  @override\n  Widget build(BuildContext context) {\n    return IntroSlider(\n        slides: this.slides,\n      onDonePress: this.onDonePress,\n      //renderSkipBtn: this.onSkipPress,\n      nameSkipBtn: \"跳过\",\n      nameNextBtn: \"下一页\",\n      nameDoneBtn: \"进入\",\n    );\n  }\n}"
  },
  {
    "path": "lib/ui/drawer/about.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass AboutMePage extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() {\n    return AboutMePageState();\n  }\n}\n\nclass AboutMePageState extends State<AboutMePage> {\n  TextStyle textStyle = new TextStyle(\n      color: Colors.blue,\n      decoration: new TextDecoration.combine([TextDecoration.underline]));\n\n  @override\n  Widget build(BuildContext context) {\n    return new Scaffold(\n        appBar: new AppBar(\n          title: new Text(\"关于作者\"),\n        ),\n        body: new Container(\n          padding: EdgeInsets.fromLTRB(35, 50, 35, 15),\n          child: new Column(\n            children: <Widget>[\n\n              CircleAvatar(\n                minRadius: 60,\n                maxRadius: 60,\n                backgroundImage: AssetImage('images/head.jpg'),\n              ),\n\n              Padding(padding: EdgeInsets.only(top: 30)),\n\n              new Text(\"基于Google Flutter的玩Android客户端\"),\n\n              Container(\n                margin: const EdgeInsets.fromLTRB(0.0, 80.0, 0.0, 0.0),\n                child: new Row(\n\n                  children: <Widget>[\n                    new Text(\"邮箱：\"),\n                    new Text(\n                      \"zw20082012@126.com\",\n                      style: TextStyle(color: Colors.blue),\n\n                    ),\n                  ],\n                ),\n              ),\n\n              GestureDetector(\n                child: new Container(\n                  margin: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),\n                  child: new Row(\n\n                    children: <Widget>[\n                      new Text(\"CSDN：\"),\n                      new Text(\n                        \"https://blog.csdn.net/zw2008224044\",\n                        style: textStyle,\n                      ),\n                    ],\n                  ),\n                ),\n                onTap: () {\n                  Navigator.of(context)\n                      .push(new MaterialPageRoute(builder: (ctx) {\n                    return new WebViewPage(\n                        title: \"ngu2008\",\n                        url: \"https://blog.csdn.net/zw2008224044\");\n                  }));\n                },\n              ),\n              GestureDetector(\n                child: new Container(\n                  margin: const EdgeInsets.fromLTRB(0.0, 20.0, 0.0, 0.0),\n                  child: new Row(\n\n                    children: <Widget>[\n                      new Text(\"GitHub：\"),\n                      new Text(\n                        \"https://github.com/ngu2008/wanandroid\",\n                        style: textStyle,\n                      ),\n                    ],\n                  ),\n                ),\n                onTap: () {\n                  Navigator.of(context)\n                      .push(new MaterialPageRoute(builder: (ctx) {\n                    return new WebViewPage(\n                        title: \"GitHub\",\n                        url: \"https://github.com/ngu2008/wanandroid\");\n                  }));\n                },\n              ),\n              Expanded(child: Container(), flex: 1),\n              new Text(\n                \"本项目仅供学习使用，不得用作商业目的\",\n                style: new TextStyle(fontSize: 12.0),\n              )\n            ],\n          ),\n        ));\n  }\n}\n"
  },
  {
    "path": "lib/ui/drawer/collctions.dart",
    "content": "import 'dart:ui';\nimport 'package:dio/dio.dart';\nimport 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter_slidable/flutter_slidable.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/base_model.dart';\nimport 'package:wanandroid_ngu/model/collection_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass CollectionsPage extends BaseWidget {\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return CollectionsPageState();\n  }\n}\n\nclass CollectionsPageState extends BaseWidgetState<CollectionsPage> {\n  List<Collection> _datas = new List();\n  ScrollController _scrollController = ScrollController(); //listview的控制器\n  int _page = 0; //加载的页数\n\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n\n  Future<Null> getData() async {\n    _page = 0;\n    ApiService().getCollectionList((\n      CollectionModel _collectionModel,\n    ) {\n      if (_collectionModel.errorCode==0) {//成功\n        if (_collectionModel.data.datas.length > 0) {//有数据\n          showContent();\n          setState(() {\n            _datas.clear();\n            _datas.addAll(_collectionModel.data.datas);\n          });\n        } else {//数据为空\n          showEmpty();\n        }\n      }else{\n        Fluttertoast.showToast(msg: _collectionModel.errorMsg);\n      }\n    }, (DioError error) {//发生错误\n      print(error.response);\n      setState(() {\n        showError();\n      });\n    }, _page);\n  }\n\n  Future<Null> _getMore() async {\n    _page++;\n    ApiService().getCollectionList((\n      CollectionModel _collectionModel,\n    ){\n      if (_collectionModel.errorCode==0) {//成功\n        showContent();\n        if (_collectionModel.data.datas.length > 0) {//有数据\n          setState(() {\n            _datas.addAll(_collectionModel.data.datas);\n          });\n        } else {//数据为空\n          Fluttertoast.showToast(msg:\"没有更多数据了\");\n        }\n      }else{\n        Fluttertoast.showToast(msg: _collectionModel.errorMsg);\n      }\n    }, (DioError error) {\n      print(error.response);\n      setState(() {\n        showError();\n      });\n    }, _page);\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    showloading();\n    getData();\n    _scrollController.addListener(() {\n      if (_scrollController.position.pixels ==\n          _scrollController.position.maxScrollExtent) {\n        _getMore();\n      }\n    });\n    _scrollController.addListener(() {\n      //当前位置是否超过屏幕高度\n      if (_scrollController.offset < 200 && showToTopBtn) {\n        setState(() {\n          showToTopBtn = false;\n        });\n      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n        setState(() {\n          showToTopBtn = true;\n        });\n      }\n    });\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    return Scaffold(\n      body: RefreshIndicator(\n          displacement: 15,\n          child: ListView.separated(\n            //普通项\n            itemBuilder: _renderRow,\n            //插入项\n            separatorBuilder: (BuildContext context, int index) {\n              return Container(\n                height: 0.5,\n                color: Colors.black26,\n              );\n            },\n            controller: _scrollController,\n            itemCount: _datas.length + 1,\n          ),\n          onRefresh: getData),\n      floatingActionButton: !showToTopBtn ? null : FloatingActionButton(\n          child: Icon(Icons.arrow_upward),\n          onPressed: () {\n            //返回到顶部时执行动画\n            _scrollController.animateTo(.0,\n                duration: Duration(milliseconds: 200),\n                curve: Curves.ease\n            );\n          }\n      ),\n    );\n  }\n\n  Future<Null> _cancelCollection(int _position, int _id, int _originId) async {\n    ApiService().cancelCollection((BaseModel _baseModel) {\n      if (_baseModel.errorCode == 0) {\n        _datas.removeAt(_position);\n      }\n      Scaffold.of(context).showSnackBar(new SnackBar(\n        content: Text(\"移除成功！\"),\n      ));\n      setState(() {});\n    }, (DioError error) {\n      print(error.response);\n      setState(() {\n        showError();\n      });\n    }, _id, _originId);\n  }\n\n  Widget _renderRow(BuildContext context, int index) {\n    if (index < _datas.length) {\n      return _itemView(context, index);\n    }\n    return null;\n  }\n\n  Widget _itemView(BuildContext context, int index) {\n    return InkWell(\n      child: _slideRow(index, _datas[index]),\n      onTap: () {\n        Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n          return new WebViewPage(\n              title: _datas[index].title, url: _datas[index].link);\n        }));\n      },\n    );\n  }\n\n  Widget _slideRow(int index, Collection item) {\n    return new Slidable(\n      delegate: new SlidableDrawerDelegate(),\n      actionExtentRatio: 0.25,\n      child: _newsRow(item),\n      secondaryActions: <Widget>[\n        new IconSlideAction(\n          caption: '取消收藏',\n          color: Colors.red,\n          icon: Icons.delete,\n          onTap: () {\n            _cancelCollection(index, item.id, item.originId);\n          },\n        ),\n      ],\n    );\n  }\n\n  Widget _newsRow(Collection item) {\n    return new Column(\n      children: <Widget>[\n        new Container(\n            padding: EdgeInsets.fromLTRB(16, 16, 16, 8),\n            child: new Row(\n              mainAxisAlignment: MainAxisAlignment.spaceBetween,\n              children: <Widget>[\n                Text(\n                  \"作者：\" + item.author,\n                  style: TextStyle(fontSize: 12),\n                ),\n                new Expanded(\n                  child: new Text(\n                    \"收藏时间：\" + item.niceDate,\n                    style: TextStyle(fontSize: 12),\n                    textAlign: TextAlign.right,\n                  ),\n                ),\n              ],\n            )),\n        Container(\n            padding: EdgeInsets.fromLTRB(16, 0, 16, 0),\n            child: Row(\n              children: <Widget>[\n                Expanded(\n                    child: Text(\n                  item.title,\n                  style: TextStyle(\n                    fontSize: 16,\n                    fontWeight: FontWeight.bold,\n                    color: const Color(0xFF3D4E5F),\n                  ),\n                  textAlign: TextAlign.left,\n                ))\n              ],\n            )),\n        Container(\n            padding: EdgeInsets.fromLTRB(16, 8, 16, 16),\n            child: Row(\n              children: <Widget>[\n                item.chapterName.isNotEmpty\n                    ? Expanded(\n                        child: Text(\n                          \"分类：\" + item.chapterName,\n                          style: TextStyle(fontSize: 12),\n                        ),\n                      )\n                    : Text(\"\")\n              ],\n            )),\n      ],\n    );\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _scrollController.dispose();\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    getData();\n  }\n\n  @override\n  AppBar getAppBar() {\n    return  AppBar(\n      title: Text(\"我的收藏\"),\n      elevation: 0.4,\n    );\n  }\n}\n"
  },
  {
    "path": "lib/ui/drawer/common_website.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/db/db_helper.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/common_websit_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass CommonWebsitePage extends BaseWidget {\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return CommonWebsitePageState();\n  }\n}\n\nclass CommonWebsitePageState extends BaseWidgetState<CommonWebsitePage> {\n  List<DataListBean> _datas = new List();\n  ScrollController _scrollController = ScrollController();\n  var db = DatabaseHelper();\n\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n\n  Future<Null> _getData() async {\n    ApiService().getCommonWebsite((CommonWebsitModel commonWebsitModel) {\n      if (commonWebsitModel.errorCode == 0) {\n        var datas = commonWebsitModel.data;\n        if (datas != null && datas.length > 0) {\n          showContent();\n          setState(() {\n            _datas = datas;\n          });\n          //清空表数据\n          db.clear();\n          //数据存入数据库\n          for (int i = 0; i < datas.length; i++) {\n            db.saveItem(datas[i]);\n          }\n        } else {\n          showEmpty();\n        }\n      } else {\n        Fluttertoast.showToast(msg: commonWebsitModel.errorMsg);\n      }\n    }, (DioError error) {\n      //发生错误\n      print(error.response);\n//      setState(() {\n//        showError();\n//      });\n    });\n  }\n\n  _getDataFromDb() async {\n    List datas = await db.getTotalList();\n    if (datas.length > 0) {\n      datas.forEach((item) {\n        DataListBean dataListBean = DataListBean.fromMap(item);\n        _datas.add(dataListBean);\n      });\n      setState(() {\n\n      });\n    } else {\n      showloading();\n    }\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    // showloading();\n    //读取数据库的数据\n    _getDataFromDb();\n\n    _getData();\n    _scrollController.addListener(() {\n      //当前位置是否超过屏幕高度\n      if (_scrollController.offset < 200 && showToTopBtn) {\n        setState(() {\n          showToTopBtn = false;\n        });\n      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n        setState(() {\n          showToTopBtn = true;\n        });\n      }\n    });\n  }\n\n  Widget _getBodyWidget(List<DataListBean> datas) {\n    return RefreshIndicator(\n      displacement: 15,\n      onRefresh: _getData,\n      child: GridView.builder(\n          padding: EdgeInsets.all(15),\n          gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(\n              crossAxisCount: 2, //每行2列\n              mainAxisSpacing: 15,\n              crossAxisSpacing: 15,\n              childAspectRatio: 1.333 //\n          ),\n          controller: _scrollController,\n          itemCount: _datas.length,\n          itemBuilder: _renderItem),\n    );\n  }\n\n  Color _getColor(int index) {\n    switch (index % 8) {\n      case 0:\n        return const Color(0xFFfb6e52);\n      case 1:\n        return const Color(0xFFa1d46f);\n      case 2:\n        return const Color(0xFF5cc0e2);\n      case 3:\n        return const Color(0xFFffbb44);\n      case 4:\n        return const Color(0xFFef6666);\n      case 5:\n        return const Color(0xFFf8d19e);\n      case 6:\n        return const Color(0xFF48cfae);\n      case 7:\n        return const Color(0xFFaa9ef8);\n    }\n  }\n\n  Widget _renderItem(BuildContext context, int index) {\n    return new InkWell(\n      onTap: () {\n        Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n          return new WebViewPage(\n              title: _datas[index].name, url: _datas[index].link);\n        }));\n      },\n      child: Container(\n        padding: EdgeInsets.only(top: 25, left: 25),\n        color: _getColor(index),\n        child: Text(\n          _datas[index].name,\n          style: TextStyle(\n              color: Colors.white, fontSize: 16, fontWeight: FontWeight.bold),\n        ),\n      ),\n    );\n  }\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(\"常用网站\"),\n      elevation: 0.4,\n    );\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    return Scaffold(\n      body: _getBodyWidget(_datas),\n      floatingActionButton: !showToTopBtn\n          ? null\n          : FloatingActionButton(\n          child: Icon(Icons.arrow_upward),\n          onPressed: () {\n            //返回到顶部时执行动画\n            _scrollController.animateTo(.0,\n                duration: Duration(milliseconds: 200), curve: Curves.ease);\n          }),\n    );\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    _getData();\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n  }\n\n}\n"
  },
  {
    "path": "lib/ui/drawer/drawer.dart",
    "content": "import 'package:flutter/cupertino.dart';\nimport 'package:flutter/material.dart';\nimport 'package:share/share.dart';\nimport 'package:wanandroid_ngu/common/application.dart';\nimport 'package:wanandroid_ngu/common/user.dart';\nimport 'package:wanandroid_ngu/event/change_theme_event.dart';\nimport 'package:wanandroid_ngu/event/login_event.dart';\nimport 'package:wanandroid_ngu/ui/drawer/about.dart';\nimport 'package:wanandroid_ngu/ui/drawer/collctions.dart';\nimport 'package:wanandroid_ngu/ui/drawer/common_website.dart';\nimport 'package:wanandroid_ngu/ui/drawer/pretty.dart';\nimport 'package:wanandroid_ngu/ui/login/login_page.dart';\nimport 'package:wanandroid_ngu/util/theme_util.dart';\nimport 'package:wanandroid_ngu/util/utils.dart';\n\nclass DrawerPage extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() {\n    return new DrawerPageState();\n  }\n}\n\nclass DrawerPageState extends State<DrawerPage> {\n  bool isLogin = false;\n  String username = \"未登录\";\n\n  @override\n  void initState() {\n    super.initState();\n    this.registerLoginEvent();\n    if (null != User.singleton.userName) {\n      isLogin = true;\n      username = User.singleton.userName;\n    }\n  }\n\n  void registerLoginEvent() {\n    Application.eventBus.on<LoginEvent>().listen((event) {\n      changeUI();\n    });\n  }\n\n  changeUI() async {\n    setState(() {\n      isLogin = true;\n      username = User.singleton.userName;\n    });\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Drawer(\n      child: ListView(\n        padding: EdgeInsets.zero,\n        children: <Widget>[\n          UserAccountsDrawerHeader(\n            accountName: InkWell(\n              child: Text(username,\n                  style: TextStyle(fontWeight: FontWeight.bold, fontSize: 20)),\n              onTap: () {\n                if (!isLogin) {\n                  Navigator.of(context)\n                      .push(new MaterialPageRoute(builder: (context) {\n                    return new LoginPage();\n                  }));\n                }\n              },\n            ),\n            currentAccountPicture: InkWell(\n              child: CircleAvatar(\n                backgroundImage: AssetImage('images/head.jpg'),\n              ),\n              onTap: () {\n                if (!isLogin) {\n                  Navigator.of(context)\n                      .push(new MaterialPageRoute(builder: (context) {\n                    return new LoginPage();\n                  }));\n                }\n              },\n            ),\n          ),\n          ListTile(\n            title: Text(\n              '我的收藏',\n              textAlign: TextAlign.left,\n            ),\n            leading: Icon(Icons.collections, size: 22.0),\n            onTap: () {\n              if (isLogin) {\n                onCollectionClick();\n              } else {\n                onLoginClick();\n              }\n            },\n          ),\n          ListTile(\n            title: Text(\n              '常用网站',\n              textAlign: TextAlign.left,\n            ),\n            leading: Icon(Icons.web, size: 22.0),\n            onTap: () {\n              Navigator.of(context)\n                  .push(new MaterialPageRoute(builder: (context) {\n                return new CommonWebsitePage();\n              }));\n            },\n          ),\n          ListTile(\n            title: Text(\n              '主题',\n              textAlign: TextAlign.left,\n            ),\n            leading: Icon(Icons.settings, size: 22.0),\n            onTap: () {\n              showDialog(\n                context: context,\n                builder: (BuildContext context) {\n                  return new SimpleDialog(\n                    title: Text(\"设置主题\"),\n                    children: ThemeUtils.supportColors.map((Color color) {\n                      return new SimpleDialogOption(\n                        child: Container(\n                          padding: EdgeInsets.fromLTRB(10, 8, 10, 8),\n                          height: 35,\n                          color: color,\n                        ),\n                        onPressed: () {\n                          ThemeUtils.currentColorTheme = color;\n                          Utils.setColorTheme(\n                              ThemeUtils.supportColors.indexOf(color));\n                          changeColorTheme(color);\n                          Navigator.of(context).pop();\n                        },\n                      );\n                    }).toList(),\n                  );\n                },\n              );\n            },\n          ),\n          ListTile(\n            title: Text(\n              '分享',\n              textAlign: TextAlign.left,\n            ),\n            leading: Icon(Icons.share, size: 22.0),\n            onTap: () {\n              Share.share(\n                  '给你推荐一个特别好玩的应用玩安卓客户端，点击下载：https://www.pgyer.com/haFL');\n            },\n          ),\n          ListTile(\n            title: Text(\n              '妹子图',\n              textAlign: TextAlign.left,\n            ),\n            leading: Icon(Icons.directions_bike, size: 22.0),\n            onTap: () {\n              Navigator.of(context)\n                  .push(new MaterialPageRoute(builder: (context) {\n                return new PrettyPage();\n              }));\n            },\n          ),\n          ListTile(\n            title: Text(\n              '关于作者',\n              textAlign: TextAlign.left,\n            ),\n            leading: Icon(Icons.info, size: 22.0),\n            onTap: () {\n              Navigator.of(context)\n                  .push(new MaterialPageRoute(builder: (context) {\n                return new AboutMePage();\n              }));\n            },\n          ),\n          logoutWidget()\n        ],\n      ),\n    );\n  }\n\n  Widget logoutWidget() {\n    if (User.singleton.userName != null) {\n      return ListTile(\n        title: Text(\n          '退出登录',\n          textAlign: TextAlign.left,\n        ),\n        leading: Icon(Icons.power_settings_new, size: 22.0),\n        onTap: () {\n          User.singleton.clearUserInfor();\n          setState(() {\n            isLogin = false;\n            username = \"未登录\";\n          });\n        },\n      );\n    } else {\n      return SizedBox(\n        height: 0,\n      );\n    }\n  }\n\n  void onCollectionClick() async {\n    await Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n      return new CollectionsPage();\n    }));\n  }\n\n  void onLoginClick() async {\n    await Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n      return new LoginPage();\n    }));\n  }\n\n  changeColorTheme(Color c) {\n    Application.eventBus.fire(new ChangeThemeEvent(c));\n  }\n}\n"
  },
  {
    "path": "lib/ui/drawer/pretty.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:photo_view/photo_view_gallery.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/pretty_model.dart';\n\nclass PrettyPage extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() {\n    return new PrettyPageState();\n  }\n}\n\nclass PrettyPageState extends State<PrettyPage> {\n\n  //当前页数据\n  List<ResultsListBean> _datas = new List();\n\n  //所有的照片数据\n  List<PhotoViewGalleryPageOptions> photos = new List();\n\n  int _page = 1;\n\n  Future<Null> _getData() async {\n    ApiService().getPrettyGirl((PrettyModel prettyModel) {\n      setState(() {\n        _datas = prettyModel.results;\n        for (int i = 0; i < _datas.length; i++) {\n          PhotoViewGalleryPageOptions pageOptions = PhotoViewGalleryPageOptions(\n              imageProvider: NetworkImage(_datas[i].url));\n          photos.add(pageOptions);\n        }\n      });\n    }, _page);\n  }\n\n\n  @override\n  void initState() {\n    super.initState();\n    _getData();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      appBar: AppBar(\n        title: Text(\"妹子图\"),\n      ),\n      body: Container(\n          child: PhotoViewGallery(\n        onPageChanged: (int index) {\n          if(index==photos.length-1){//加载到最有一页\n            _page++;\n            _getData();\n          }\n        },\n        pageOptions: photos,\n        backgroundDecoration: BoxDecoration(color: Colors.black87),\n      )),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/ui/home/banner.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter_swiper/flutter_swiper.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/banner_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass BannerWidget extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() {\n    return BannerWidgetState();\n  }\n}\n\nclass BannerWidgetState extends State<BannerWidget> {\n\n  List<BannerData> _bannerList = new List();\n\n  @override\n  void initState() {\n    _bannerList.add(null);\n    _getBanner();\n  }\n\n  Future<Null> _getBanner() {\n    ApiService().getBanner((BannerModel _bannerModel) {\n      if (_bannerModel.data.length > 0) {\n        setState(() {\n          _bannerList = _bannerModel.data;\n        });\n      }\n    });\n\n  }\n\n  Widget buildItemImageWidget(BuildContext context, int index) {\n    return new InkWell(\n      onTap: () {\n        Navigator.of(context).push(new MaterialPageRoute(builder: (context){\n          return new WebViewPage(title: _bannerList[index].title,url: _bannerList[index].url);\n        }));\n      },\n      child: new Container(\n        child: new Image.network(\n          _bannerList[index].imagePath,\n          fit: BoxFit.fill,\n        ),\n      ),\n    );\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Swiper(\n      itemBuilder: (BuildContext context, int index) {\n        if (_bannerList[index] == null ||\n            _bannerList[index].imagePath == null) {\n          return new Container(\n            color: Colors.grey[100],\n          );\n        } else {\n          return buildItemImageWidget(context, index);\n        }\n      },\n      itemCount: _bannerList.length,\n      autoplay: true,\n      pagination: new SwiperPagination(),\n    );;\n  }\n}\n"
  },
  {
    "path": "lib/ui/home/home_page.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/article_model.dart';\nimport 'package:wanandroid_ngu/ui/home/banner.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass HomePage extends BaseWidget {\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return HomePageState();\n  }\n}\n\nclass HomePageState extends BaseWidgetState<HomePage> {\n  List<Article> _datas = new List();\n  //listview控制器\n  ScrollController _scrollController = ScrollController();\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n  int _page = 0;\n\n\n  @override\n  void initState() {\n    super.initState();\n    setAppBarVisible(false);\n\n    getData();\n    _scrollController.addListener(() {\n      //滑到了底部，加载更多\n      if (_scrollController.position.pixels ==\n          _scrollController.position.maxScrollExtent) {\n        _getMore();\n      }\n\n      //当前位置是否超过屏幕高度\n      if (_scrollController.offset < 200 && showToTopBtn) {\n        setState(() {\n          showToTopBtn = false;\n        });\n      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n        setState(() {\n          showToTopBtn = true;\n        });\n      }\n    });\n  }\n\n  //获取文章列表数据\n  Future<Null> getData() async {\n    _page = 0;\n    ApiService().getArticleList((ArticleModel _articleModel) {\n      if (_articleModel.errorCode == 0) {\n        //成功\n        if (_articleModel.data.datas.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _datas.clear();\n            _datas.addAll(_articleModel.data.datas);\n          });\n        } else {\n          //数据为空\n          showEmpty();\n        }\n      } else {\n        Fluttertoast.showToast(msg: _articleModel.errorMsg);\n      }\n    }, (DioError error) {\n      //发生错误\n      print(error.response);\n      setState(() {\n        showError();\n      });\n    }, _page);\n  }\n\n  //加载更多的数据\n  Future<Null> _getMore() async {\n    _page++;\n    ApiService().getArticleList((ArticleModel _articleModel) {\n      if (_articleModel.errorCode == 0) {\n        //成功\n        if (_articleModel.data.datas.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _datas.addAll(_articleModel.data.datas);\n          });\n        } else {\n          //数据为空\n          Fluttertoast.showToast(msg: \"没有更多数据了\");\n        }\n      } else {\n        Fluttertoast.showToast(msg: _articleModel.errorMsg);\n      }\n    }, (DioError error) {\n      //发生错误\n      print(error.response);\n      setState(() {\n        showError();\n      });\n    }, _page);\n  }\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(\"不显示\"),\n    );\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    return Scaffold(\n      body: RefreshIndicator(\n        displacement: 15,\n        onRefresh: getData,\n        child: ListView.separated(\n            itemBuilder: _renderRow,\n            physics: new AlwaysScrollableScrollPhysics(),\n            separatorBuilder: (BuildContext context, int index) {\n              return Container(\n                height: 0.5,\n                color: Colors.black26,\n              );\n            },\n            controller: _scrollController,\n            //包含轮播图和加载更多\n            itemCount: _datas.length + 2),\n      ),\n      floatingActionButton: !showToTopBtn\n          ? null\n          : FloatingActionButton(\n          child: Icon(Icons.arrow_upward),\n          onPressed: () {\n            //返回到顶部时执行动画\n            _scrollController.animateTo(.0,\n                duration: Duration(milliseconds: 200), curve: Curves.ease);\n          }),\n    );\n  }\n\n  Widget _renderRow(BuildContext context, int index) {\n    if (index == 0) {\n      return Container(\n        height: 200,\n        color: Colors.green,\n        child: new BannerWidget(),\n      );\n    }\n\n    if (index < _datas.length - 1) {\n      return new InkWell(\n        onTap: ()  {\n           Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n            return new WebViewPage(\n                title: _datas[index - 1].title, url: _datas[index - 1].link);\n          }));\n\n        },\n        child: Column(\n          children: <Widget>[\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 16, 16, 8),\n              child: Row(\n                children: <Widget>[\n                  Text(\n                    _datas[index - 1].author,\n                    style: TextStyle(fontSize: 12),\n                    textAlign: TextAlign.left,\n                  ),\n                  Expanded(\n                    child: Text(\n                      _datas[index - 1].niceDate,\n                      style: TextStyle(fontSize: 12),\n                      textAlign: TextAlign.right,\n                    ),\n                  ),\n                ],\n              ),\n            ),\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 0, 16, 0),\n              child: Row(\n                children: <Widget>[\n                  Expanded(\n                    child: Text(\n                      _datas[index - 1].title,\n                      maxLines: 2,\n                      style: TextStyle(\n                        fontSize: 16,\n                        fontWeight: FontWeight.bold,\n                        color: const Color(0xFF3D4E5F),\n                      ),\n                      textAlign: TextAlign.left,\n                    ),\n                  )\n                ],\n              ),\n            ),\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 8, 16, 16),\n              child: Row(\n                children: <Widget>[\n                  Expanded(\n                    child: Text(\n                      _datas[index - 1].superChapterName,\n                      style: TextStyle(fontSize: 12),\n                      textAlign: TextAlign.left,\n                    ),\n                  )\n                ],\n              ),\n            ),\n          ],\n        ),\n      );\n    }\n    return null;\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _scrollController.dispose();\n  }\n\n  @override\n  bool get wantKeepAlive => true;\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    getData();\n  }\n}"
  },
  {
    "path": "lib/ui/knowledge/knowledge.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/system_tree_model.dart';\nimport 'package:wanandroid_ngu/ui/knowledge/knowledge_content.dart';\nimport 'package:wanandroid_ngu/util/utils.dart';\n\nclass KnowledgePage extends BaseWidget {\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return KnowledgePageState();\n  }\n}\n\nclass KnowledgePageState extends BaseWidgetState<KnowledgePage> {\n  List<SystemTreeData> _datas = new List();\n  //listview控制器\n  ScrollController _scrollController = ScrollController();\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n\n  @override\n  void initState() {\n    super.initState();\n    setAppBarVisible(false);\n    _getData();\n\n    _scrollController.addListener(() {\n      //当前位置是否超过屏幕高度\n      if (_scrollController.offset < 200 && showToTopBtn) {\n        setState(() {\n          showToTopBtn = false;\n        });\n      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n        setState(() {\n          showToTopBtn = true;\n        });\n      }\n    });\n  }\n\n  Future<Null> _getData() async {\n    ApiService().getSystemTree((SystemTreeModel _systemTreeModel) {\n      if (_systemTreeModel.errorCode == 0) {\n        //成功\n        if (_systemTreeModel.data.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _datas.clear();\n            _datas.addAll(_systemTreeModel.data);\n          });\n        } else {\n          //数据为空\n          showEmpty();\n        }\n      } else {\n        Fluttertoast.showToast(msg: _systemTreeModel.errorMsg);\n      }\n    },(DioError error) {\n      //发生错误\n      print(error.response);\n      showError();\n    });\n  }\n\n  Widget _renderRow(BuildContext context, int index) {\n    if (index < _datas.length) {\n      return InkWell(\n          onTap: () {\n            Navigator.of(context)\n                .push(new MaterialPageRoute(builder: (context) {\n              return new KnowledgeContentPage(new ValueKey(_datas[index]));\n            }));\n          },\n          child: Container(\n            color: Colors.white,\n            child: Row(\n              mainAxisAlignment: MainAxisAlignment.center,\n              children: <Widget>[\n                Expanded(\n                    child: Container(\n                  padding: EdgeInsets.all(16),\n                  child: Column(\n                    mainAxisAlignment: MainAxisAlignment.start,\n                    children: <Widget>[\n                      Container(\n                        alignment: Alignment.centerLeft,\n                        padding: EdgeInsets.only(bottom: 8),\n                        child: Text(\n                          _datas[index].name,\n                          style: TextStyle(\n                              fontSize: 16,\n                              color: Color(0xFF3D4E5F),\n                              fontWeight: FontWeight.bold),\n                          textAlign: TextAlign.left,\n                        ),\n                      ),\n                      Container(\n                          alignment: Alignment.centerLeft,\n                          child: buildChildren(_datas[index].children)),\n                    ],\n                  ),\n                )),\n                Icon(Icons.chevron_right)\n              ],\n            ),\n          ));\n    }\n    return null;\n  }\n\n  Widget buildChildren(List<SystemTreeChild> children) {\n    List<Widget> tiles = []; //先建一个数组用于存放循环生成的widget\n    Widget content; //单独一个widget组件，用于返回需要生成的内容widget\n    for (var item in children) {\n      tiles.add(\n        new Chip(\n          materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,\n          backgroundColor: Utils.getChipBgColor(item.name),\n          label: new Text(item.name),\n//          avatar: new CircleAvatar(backgroundColor: Colors.blue,child: Text(\"A\"),),\n        ),\n      );\n    }\n\n    content = Wrap(\n        spacing: 12,\n        runSpacing: 12,\n        alignment: WrapAlignment.start,\n        children: tiles);\n\n    return content;\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _scrollController.dispose();\n  }\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(\"不显示\"),\n    );\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    return Scaffold(\n      body: RefreshIndicator(\n        displacement: 15,\n        onRefresh: _getData,\n        child: ListView.separated(\n          itemBuilder: _renderRow,\n          physics: new AlwaysScrollableScrollPhysics(),\n          separatorBuilder: (BuildContext context, int index) {\n            return Container(\n              height: 0.5,\n              color: Colors.black26,\n            );\n          },\n          itemCount: _datas.length,\n          controller: _scrollController,\n        ),\n      ),\n      floatingActionButton: !showToTopBtn ? null : FloatingActionButton(\n          child: Icon(Icons.arrow_upward),\n          onPressed: () {\n            //返回到顶部时执行动画\n            _scrollController.animateTo(.0,\n                duration: Duration(milliseconds: 200),\n                curve: Curves.ease\n            );\n          }\n      ),\n    );\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    _getData();\n  }\n\n}\n"
  },
  {
    "path": "lib/ui/knowledge/knowledge_content.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/system_tree_content_model.dart';\nimport 'package:wanandroid_ngu/model/system_tree_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass KnowledgeContentPage extends StatefulWidget {\n  SystemTreeData data;\n\n  KnowledgeContentPage(ValueKey<SystemTreeData> key) : super(key: key) {\n    this.data = key.value;\n  }\n\n  @override\n  State<StatefulWidget> createState() {\n    return KnowledgeContentPageState();\n  }\n}\n\nclass KnowledgeContentPageState extends State<KnowledgeContentPage>\n    with TickerProviderStateMixin {\n  SystemTreeData _datas;\n  TabController _tabController;\n\n  @override\n  void initState() {\n    super.initState();\n    _datas = widget.data;\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _tabController.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    _tabController =\n        new TabController(length: _datas.children.length, vsync: this);\n    return new Scaffold(\n      appBar: new AppBar(\n        title: Text(_datas.name),\n        bottom: new TabBar(\n            indicatorColor: Colors.white,\n            labelStyle:TextStyle(fontSize: 16),\n            unselectedLabelStyle: TextStyle(fontSize: 16),\n            controller: _tabController,\n            isScrollable: true,\n            tabs: _datas.children.map((SystemTreeChild item) {\n              return Tab(\n                text: item.name,\n              );\n            }).toList()),\n      ),\n      body: TabBarView(\n\n        controller: _tabController,\n        children: _datas.children.map((item) {\n          return NewsList(\n            item.id,\n          );\n        }).toList(),\n      ),\n    );\n  }\n}\n\n//知识体系文章列表\nclass NewsList extends BaseWidget {\n  final int id;\n  NewsList(this.id);\n\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return _NewsListState();\n  } //知识体系id\n}\n\nclass _NewsListState extends BaseWidgetState<NewsList> {\n  List<SystemTreeContentChild> _datas = new List();\n  ScrollController _scrollController = ScrollController(); //listview的控制器\n  int _page = 0;\n\n  @override\n  void initState() {\n    setAppBarVisible(false);\n    showloading();\n    getData();\n    _scrollController.addListener(() {\n      if (_scrollController.position.pixels ==\n          _scrollController.position.maxScrollExtent) {\n        _getMore();\n      }\n    });\n  }\n\n  Future<Null> getData() async {\n    _page = 0;\n    int _id = widget.id;\n\n    ApiService().getSystemTreeContent(\n        (SystemTreeContentModel _systemTreeContentModel) {\n\n          if (_systemTreeContentModel.errorCode == 0) {\n            //成功\n            if (_systemTreeContentModel.data.datas.length > 0) {\n              //有数据\n              showContent();\n              setState(() {\n                _datas = _systemTreeContentModel.data.datas;\n              });\n            } else {\n              //数据为空\n              showEmpty();\n            }\n          } else {\n            Fluttertoast.showToast(msg: _systemTreeContentModel.errorMsg);\n          }\n    },(DioError error) {\n      //发生错误\n      print(error.response);\n      showError();\n    }, _page, _id);\n  }\n\n  Future<Null> _getMore() async {\n    _page++;\n    int _id = widget.id;\n\n    ApiService().getSystemTreeContent(\n        (SystemTreeContentModel _systemTreeContentModel) {\n\n          if (_systemTreeContentModel.errorCode == 0) {\n            //成功\n            if (_systemTreeContentModel.data.datas.length > 0) {\n              //有数据\n              showContent();\n              setState(() {\n                _datas.addAll(_systemTreeContentModel.data.datas);\n              });\n            } else {\n              //数据为空\n              Fluttertoast.showToast(msg: \"没有更多数据了\");\n            }\n          } else {\n            Fluttertoast.showToast(msg: _systemTreeContentModel.errorMsg);\n          }\n    },(DioError error) {\n      //发生错误\n      print(error.response);\n      showError();\n    }, _page, _id);\n  }\n\n  Widget _renderRow(BuildContext context, int index) {\n    if (index < _datas.length) {\n      return InkWell(\n        child: Container(\n          child: _newsRow(_datas[index]),\n        ),\n        onTap: () {\n          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n            return new WebViewPage(\n                title: _datas[index].title, url: _datas[index].link);\n          }));\n        },\n      );\n    }\n    return null;\n  }\n\n  //新闻列表单个item\n  Widget _newsRow(SystemTreeContentChild item) {\n    return new Container(\n      color: Colors.white,\n      padding: EdgeInsets.all(16),\n      child: Column(\n        children: <Widget>[\n          new Container(\n              padding: EdgeInsets.fromLTRB(8, 8, 8, 8),\n              child: new Row(\n                mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                children: <Widget>[\n                  Text(\n                    item.author,\n                    style: TextStyle(fontSize: 12, color: Colors.grey),\n                  ),\n                  new Expanded(\n                    child: new Text(\n                      item.niceDate,\n                      style: TextStyle(fontSize: 12, color: Colors.grey),\n                      textAlign: TextAlign.right,\n                    ),\n                  ),\n                ],\n              )),\n          Container(\n              padding: EdgeInsets.fromLTRB(8, 0, 8, 8),\n              child: Row(\n                children: <Widget>[\n                  Expanded(\n                      child: Text(\n                    item.title,\n                    style: TextStyle(\n                        fontSize: 16,\n                        color: const Color(0xFF3D4E5F),\n                        fontWeight: FontWeight.bold),\n                    textAlign: TextAlign.left,\n                  ))\n                ],\n              )),\n          Container(\n              padding: EdgeInsets.fromLTRB(8, 0, 8, 8),\n              child: Row(\n                children: <Widget>[\n                  Text(\n                    item.superChapterName,\n                    style: TextStyle(fontSize: 12, color: Colors.grey),\n                  ),\n                  new Text(\n                    \"/\" + item.chapterName,\n                    style: TextStyle(fontSize: 12, color: Colors.grey),\n                    textAlign: TextAlign.right,\n                  ),\n                ],\n              )),\n        ],\n      ),\n    );\n  }\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(\"不显示\"),\n    );\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    return RefreshIndicator(\n      onRefresh: getData,\n      child: ListView.separated(\n        physics: new AlwaysScrollableScrollPhysics(),\n        itemBuilder: _renderRow,\n        itemCount: _datas.length + 1,\n        controller: _scrollController,\n        separatorBuilder: (BuildContext context, int index) {\n          return Container(\n            height: 0.5,\n            color: Colors.black26,\n          );\n        },\n      ),\n    );\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    getData();\n  }\n}\n"
  },
  {
    "path": "lib/ui/login/login_page.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:flutter/services.dart';\nimport 'package:font_awesome_flutter/font_awesome_flutter.dart';\nimport 'package:wanandroid_ngu/common/application.dart';\nimport 'package:wanandroid_ngu/common/user.dart';\nimport 'package:wanandroid_ngu/event/login_event.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/user_model.dart';\nimport 'package:wanandroid_ngu/util/bubble_indication_painter.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/util/theme_util.dart';\n\nclass LoginPage extends StatefulWidget {\n  LoginPage({Key key}) : super(key: key);\n\n  @override\n  _LoginPageState createState() => new _LoginPageState();\n}\n\nclass _LoginPageState extends State<LoginPage>\n    with SingleTickerProviderStateMixin {\n\n  Color themeColor = ThemeUtils.currentColorTheme;\n\n  final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();\n\n  final FocusNode myFocusNodeEmailLogin = FocusNode();\n  final FocusNode myFocusNodePasswordLogin = FocusNode();\n\n  final FocusNode myFocusNodePassword = FocusNode();\n  final FocusNode myFocusNodeName = FocusNode();\n\n  TextEditingController loginEmailController = new TextEditingController();\n  TextEditingController loginPasswordController = new TextEditingController();\n\n  bool _obscureTextLogin = true;\n  bool _obscureTextSignup = true;\n  bool _obscureTextSignupConfirm = true;\n\n  TextEditingController signupNameController = new TextEditingController();\n  TextEditingController signupPasswordController = new TextEditingController();\n  TextEditingController signupConfirmPasswordController =\n      new TextEditingController();\n\n  PageController _pageController;\n\n  Color left = Colors.black;\n  Color right = Colors.white;\n\n  String title = \"登录\";\n\n  @override\n  Widget build(BuildContext context) {\n    return new Scaffold(\n      appBar: AppBar(\n        title: Text(title),\n      ),\n      key: _scaffoldKey,\n      body: NotificationListener<OverscrollIndicatorNotification>(\n        onNotification: (overscroll) {\n          overscroll.disallowGlow();\n        },\n        child: SingleChildScrollView(\n          child: Container(\n            width: MediaQuery.of(context).size.width,\n            height: MediaQuery.of(context).size.height >= 775.0\n                ? MediaQuery.of(context).size.height\n                : 775.0,\n            decoration: new BoxDecoration(\n              gradient: new LinearGradient(\n                  colors: [Color(0xFFffffff), Color(0xFFffffff)],\n                  begin: const FractionalOffset(0.0, 0.0),\n                  end: const FractionalOffset(1.0, 1.0),\n                  stops: [0.0, 1.0],\n                  tileMode: TileMode.clamp),\n            ),\n            child: Column(\n              mainAxisSize: MainAxisSize.max,\n              children: <Widget>[\n                Padding(\n                  padding: EdgeInsets.only(top: 60.0),\n                  child: _buildMenuBar(context),\n                ),\n                Expanded(\n                  flex: 2,\n                  child: PageView(\n                    controller: _pageController,\n                    onPageChanged: (i) {\n                      if (i == 0) {\n                        setState(() {\n                          right = Colors.white;\n                          left = Colors.black;\n                          title = \"登录\";\n                        });\n                      } else if (i == 1) {\n                        setState(() {\n                          right = Colors.black;\n                          left = Colors.white;\n                          title = \"注册\";\n                        });\n                      }\n                    },\n                    children: <Widget>[\n                      new ConstrainedBox(\n                        constraints: const BoxConstraints.expand(),\n                        child: _buildSignIn(context),\n                      ),\n                      new ConstrainedBox(\n                        constraints: const BoxConstraints.expand(),\n                        child: _buildSignUp(context),\n                      ),\n                    ],\n                  ),\n                ),\n              ],\n            ),\n          ),\n        ),\n      ),\n    );\n  }\n\n  @override\n  void dispose() {\n    myFocusNodePassword.dispose();\n    myFocusNodeName.dispose();\n    _pageController?.dispose();\n    super.dispose();\n  }\n\n  @override\n  void initState() {\n    super.initState();\n\n    SystemChrome.setPreferredOrientations([\n      DeviceOrientation.portraitUp,\n      DeviceOrientation.portraitDown,\n    ]);\n\n    _pageController = PageController();\n  }\n\n  void showInSnackBar(String value) {\n    FocusScope.of(context).requestFocus(new FocusNode());\n    _scaffoldKey.currentState?.removeCurrentSnackBar();\n    _scaffoldKey.currentState.showSnackBar(new SnackBar(\n      content: new Text(\n        value,\n        textAlign: TextAlign.center,\n        style: TextStyle(\n          color: Colors.white,\n          fontSize: 16.0,\n        ),\n      ),\n      backgroundColor: themeColor,\n      duration: Duration(seconds: 3),\n    ));\n  }\n\n  Widget _buildMenuBar(BuildContext context) {\n    return Container(\n      width: 300.0,\n      height: 50.0,\n      decoration: BoxDecoration(\n        color: Color(0x552B2B2B),\n        borderRadius: BorderRadius.all(Radius.circular(25.0)),\n      ),\n      child: CustomPaint(\n        painter: TabIndicationPainter(pageController: _pageController),\n        child: Row(\n          mainAxisAlignment: MainAxisAlignment.spaceEvenly,\n          children: <Widget>[\n            Expanded(\n              child: FlatButton(\n                splashColor: Colors.transparent,\n                highlightColor: Colors.transparent,\n                onPressed: _onSignInButtonPress,\n                child: Text(\n                  \"登录\",\n                  style: TextStyle(color: left, fontSize: 16.0),\n                ),\n              ),\n            ),\n            //Container(height: 33.0, width: 1.0, color: Colors.white),\n            Expanded(\n              child: FlatButton(\n                splashColor: Colors.transparent,\n                highlightColor: Colors.transparent,\n                onPressed: _onSignUpButtonPress,\n                child: Text(\n                  \"注册\",\n                  style: TextStyle(\n                    color: right,\n                    fontSize: 16.0,\n                  ),\n                ),\n              ),\n            ),\n          ],\n        ),\n      ),\n    );\n  }\n\n  Widget _buildSignIn(BuildContext context) {\n    //登录\n    Future<Null> _login() async {\n      String username = loginEmailController.text;\n      String password = loginPasswordController.text;\n      if ((null != username && username.trim().length > 0) &&\n          (null != password && password.trim().length > 0)) {\n        ApiService().login((UserModel _userModel, Response response) {\n          if (_userModel != null) {\n            User().saveUserInfo(_userModel, response);\n            Application.eventBus.fire(new LoginEvent());\n            if (_userModel.errorCode == 0) {\n              Fluttertoast.showToast(msg: \"登录成功！\");\n              Navigator.of(context).pop();\n            } else {\n              Fluttertoast.showToast(msg: _userModel.errorMsg);\n            }\n          }\n        }, username, password);\n      } else {\n        Fluttertoast.showToast(\n          msg: \"用户名或者密码不能为空\",\n        );\n      }\n    }\n\n    return Container(\n      padding: EdgeInsets.only(top: 23.0),\n      child: Column(\n        children: <Widget>[\n          Stack(\n            alignment: Alignment.topCenter,\n            overflow: Overflow.visible,\n            children: <Widget>[\n              Card(\n                elevation: 2.0,\n                color: Colors.white,\n                shape: RoundedRectangleBorder(\n                  borderRadius: BorderRadius.circular(8.0),\n                ),\n                child: Container(\n                  width: 300.0,\n                  height: 150.0,\n                  child: Column(\n                    children: <Widget>[\n                      Padding(\n                        padding: EdgeInsets.only(\n                            top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),\n                        child: TextField(\n                          focusNode: myFocusNodeEmailLogin,\n                          controller: loginEmailController,\n                          keyboardType: TextInputType.emailAddress,\n                          style: TextStyle(fontSize: 14.0, color: Colors.black),\n                          decoration: InputDecoration(\n                            border: InputBorder.none,\n                            icon: Icon(\n                              FontAwesomeIcons.user,\n                              color: Colors.black,\n                              size: 18.0,\n                            ),\n                            hintText: \"用户名\",\n                            hintStyle: TextStyle(fontSize: 17.0),\n                          ),\n                        ),\n                      ),\n                      Container(\n                        width: 250.0,\n                        height: 1.0,\n                        color: Colors.grey[400],\n                      ),\n                      Padding(\n                        padding: EdgeInsets.only(\n                            top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),\n                        child: TextField(\n                          focusNode: myFocusNodePasswordLogin,\n                          controller: loginPasswordController,\n                          obscureText: _obscureTextLogin,\n                          style: TextStyle(fontSize: 16.0, color: Colors.black),\n                          decoration: InputDecoration(\n                            border: InputBorder.none,\n                            icon: Icon(\n                              FontAwesomeIcons.lock,\n                              size: 22.0,\n                              color: Colors.black,\n                            ),\n                            hintText: \"密码\",\n                            hintStyle: TextStyle(fontSize: 17.0),\n                            suffixIcon: GestureDetector(\n                              onTap: _toggleLogin,\n                              child: Icon(\n                                FontAwesomeIcons.eye,\n                                size: 15.0,\n                                color: Colors.black,\n                              ),\n                            ),\n                          ),\n                        ),\n                      ),\n                    ],\n                  ),\n                ),\n              ),\n              Container(\n                margin: EdgeInsets.only(top: 240.0),\n                decoration: new BoxDecoration(\n                  borderRadius: BorderRadius.all(Radius.circular(5.0)),\n                  boxShadow: <BoxShadow>[\n                    BoxShadow(\n                      color: const Color(0xFFffffff),\n                      offset: Offset(1.0, 6.0),\n                      blurRadius: 20.0,\n                    ),\n                    BoxShadow(\n                      color: const Color(0xFFffffff),\n                      offset: Offset(1.0, 6.0),\n                      blurRadius: 20.0,\n                    ),\n                  ],\n                  gradient: new LinearGradient(\n                      colors: [Color(0xFFffffff), Color(0xFFffffff)],\n                      begin: const FractionalOffset(0.2, 0.2),\n                      end: const FractionalOffset(1.0, 1.0),\n                      stops: [0.0, 1.0],\n                      tileMode: TileMode.clamp),\n                ),\n                child: FlatButton(\n                    shape: RoundedRectangleBorder(\n                        side: BorderSide(\n                          color: themeColor,\n                          width: 1,\n                        ),\n                        borderRadius: BorderRadius.circular(30)),\n                    color: themeColor,\n                    child: Padding(\n                      padding: const EdgeInsets.symmetric(\n                          vertical: 10.0, horizontal: 60.0),\n                      child: Text(\n                        \"登录\",\n                        style: TextStyle(\n                          color: Colors.white,\n                          fontSize: 18.0,\n                        ),\n                      ),\n                    ),\n                    onPressed: () {\n                      _login();\n                    }),\n              ),\n            ],\n          )\n        ],\n      ),\n    );\n  }\n\n  Widget _buildSignUp(BuildContext context) {\n    Future<Null> _regist() async {\n      String username = signupNameController.text;\n      String password = signupPasswordController.text;\n      String rePassword = signupConfirmPasswordController.text;\n\n      if ((null != username && username.trim().length > 0) &&\n          (null != password && password.trim().length > 0) &&\n          (null != rePassword && rePassword.trim().length > 0)) {\n        if (password != rePassword) {\n          Fluttertoast.showToast(msg: \"两次密码输入不一致！\");\n        } else {\n          ApiService().register((UserModel _userModel) {\n            if (_userModel != null) {\n              if (_userModel.errorCode == 0) {\n                Fluttertoast.showToast(msg: \"注册成功！\");\n              } else {\n                Fluttertoast.showToast(msg: _userModel.errorMsg);\n              }\n            }\n          }, username, password);\n        }\n      } else {\n        Fluttertoast.showToast(\n          msg: \"用户名或者密码不能为空\",\n        );\n      }\n    }\n\n    return Container(\n      padding: EdgeInsets.only(top: 23.0),\n      child: Column(\n        children: <Widget>[\n          Stack(\n            alignment: Alignment.topCenter,\n            overflow: Overflow.visible,\n            children: <Widget>[\n              Card(\n                elevation: 2.0,\n                color: Colors.white,\n                shape: RoundedRectangleBorder(\n                  borderRadius: BorderRadius.circular(8.0),\n                ),\n                child: Container(\n                  width: 300.0,\n                  height: 210.0,\n                  child: Column(\n                    children: <Widget>[\n                      Padding(\n                        padding: EdgeInsets.only(\n                            top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),\n                        child: TextField(\n                          focusNode: myFocusNodeName,\n                          controller: signupNameController,\n                          keyboardType: TextInputType.text,\n                          textCapitalization: TextCapitalization.words,\n                          style: TextStyle(fontSize: 16.0, color: Colors.black),\n                          decoration: InputDecoration(\n                            border: InputBorder.none,\n                            icon: Icon(\n                              FontAwesomeIcons.user,\n                              color: Colors.black,\n                            ),\n                            hintText: \"用户名\",\n                            hintStyle: TextStyle(fontSize: 16.0),\n                          ),\n                        ),\n                      ),\n                      Container(\n                        width: 250.0,\n                        height: 1.0,\n                        color: Colors.grey[400],\n                      ),\n                      Padding(\n                        padding: EdgeInsets.only(\n                            top: 10.0, bottom: 10.0, left: 25.0, right: 25.0),\n                        child: TextField(\n                          focusNode: myFocusNodePassword,\n                          controller: signupPasswordController,\n                          obscureText: _obscureTextSignup,\n                          style: TextStyle(fontSize: 16.0, color: Colors.black),\n                          decoration: InputDecoration(\n                            border: InputBorder.none,\n                            icon: Icon(\n                              FontAwesomeIcons.lock,\n                              color: Colors.black,\n                            ),\n                            hintText: \"密码\",\n                            hintStyle: TextStyle(fontSize: 16.0),\n                            suffixIcon: GestureDetector(\n                              onTap: _toggleSignup,\n                              child: Icon(\n                                FontAwesomeIcons.eye,\n                                size: 15.0,\n                                color: Colors.black,\n                              ),\n                            ),\n                          ),\n                        ),\n                      ),\n                      Container(\n                        width: 250.0,\n                        height: 1.0,\n                        color: Colors.grey[400],\n                      ),\n                      Padding(\n                        padding: EdgeInsets.only(\n                            top: 10.0, bottom: 10, left: 25.0, right: 25.0),\n                        child: TextField(\n                          controller: signupConfirmPasswordController,\n                          obscureText: _obscureTextSignupConfirm,\n                          style: TextStyle(fontSize: 16.0, color: Colors.black),\n                          decoration: InputDecoration(\n                            border: InputBorder.none,\n                            icon: Icon(\n                              FontAwesomeIcons.lock,\n                              color: Colors.black,\n                            ),\n                            hintText: \"确认密码\",\n                            hintStyle: TextStyle(fontSize: 16.0),\n                            suffixIcon: GestureDetector(\n                              onTap: _toggleSignupConfirm,\n                              child: Icon(\n                                FontAwesomeIcons.eye,\n                                size: 15.0,\n                                color: Colors.black,\n                              ),\n                            ),\n                          ),\n                        ),\n                      ),\n                    ],\n                  ),\n                ),\n              ),\n              Container(\n                margin: EdgeInsets.only(top: 340.0),\n                decoration: new BoxDecoration(\n                  borderRadius: BorderRadius.all(Radius.circular(5.0)),\n                ),\n                child: FlatButton(\n                    shape: RoundedRectangleBorder(\n                        side: BorderSide(\n                          color: themeColor,\n                          width: 1,\n                        ),\n                        borderRadius: BorderRadius.circular(30)),\n                    color: themeColor,\n                    child: Padding(\n                      padding: const EdgeInsets.symmetric(\n                          vertical: 10.0, horizontal: 60.0),\n                      child: Text(\n                        \"注册\",\n                        style: TextStyle(color: Colors.white, fontSize: 18.0),\n                      ),\n                    ),\n                    onPressed: () {\n                      _regist();\n                    }),\n              ),\n            ],\n          ),\n        ],\n      ),\n    );\n  }\n\n  //切换到登录\n  void _onSignInButtonPress() {\n    _pageController.animateToPage(0,\n        duration: Duration(milliseconds: 500), curve: Curves.decelerate);\n  }\n\n  //切换到注册\n  void _onSignUpButtonPress() {\n    _pageController?.animateToPage(1,\n        duration: Duration(milliseconds: 500), curve: Curves.decelerate);\n  }\n\n  //登录密码安全开关\n  void _toggleLogin() {\n    setState(() {\n      _obscureTextLogin = !_obscureTextLogin;\n    });\n  }\n\n  //注册密码安全开关\n  void _toggleSignup() {\n    setState(() {\n      _obscureTextSignup = !_obscureTextSignup;\n    });\n  }\n\n//注册确认密码安全开关\n  void _toggleSignupConfirm() {\n    setState(() {\n      _obscureTextSignupConfirm = !_obscureTextSignupConfirm;\n    });\n  }\n}\n"
  },
  {
    "path": "lib/ui/navigation/navigation.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/navi_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\nimport 'package:wanandroid_ngu/util/utils.dart';\n\nclass NavigationPage extends BaseWidget {\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return NavigationState();\n  }\n}\n\nclass NavigationState extends BaseWidgetState<NavigationPage> {\n  List<NaviData> _naviTitles = new List();\n  //listview控制器\n  ScrollController _scrollController = ScrollController();\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n\n  @override\n  void initState() {\n    super.initState();\n    setAppBarVisible(false);\n    _getData();\n\n    _scrollController.addListener(() {\n      _scrollController.addListener(() {\n        //当前位置是否超过屏幕高度\n        if (_scrollController.offset < 200 && showToTopBtn) {\n          setState(() {\n            showToTopBtn = false;\n          });\n        } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n          setState(() {\n            showToTopBtn = true;\n          });\n        }\n      });\n    });\n  }\n\n  Future<Null> _getData() async {\n    ApiService().getNaviList((NaviModel _naviData) {\n\n      if (_naviData.errorCode == 0) {\n        //成功\n        if (_naviData.data.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _naviTitles = _naviData.data;\n          });\n        } else {\n          //数据为空\n          showEmpty();\n        }\n      } else {\n        Fluttertoast.showToast(msg: _naviData.errorMsg);\n      }\n\n    },(DioError error) {\n      //发生错误\n      print(error.response);\n      showError();\n    });\n  }\n\n\n\n  Widget _rightListView(BuildContext context) {\n    return ListView.separated(\n        itemBuilder: _renderContent,\n        itemCount: _naviTitles.length,\n        controller: _scrollController,\n        physics: new AlwaysScrollableScrollPhysics(),\n        separatorBuilder: (BuildContext context, int index) {\n          return Container(\n            height: 0.5,\n            color: Colors.black26,\n          );\n        });\n  }\n\n  Widget _renderContent(BuildContext context, int index) {\n    return Container(\n      color: Colors.white,\n      padding: EdgeInsets.all(16),\n      child: Column(\n        mainAxisAlignment: MainAxisAlignment.start,\n        children: <Widget>[\n          Container(\n            alignment: Alignment.centerLeft,\n            padding: EdgeInsets.only(bottom: 8),\n            child: Text(\n              _naviTitles[index].name,\n              style: TextStyle(\n                  fontSize: 16,\n                  color: Color(0xFF3D4E5F),\n                  fontWeight: FontWeight.bold),\n              textAlign: TextAlign.left,\n            ),\n          ),\n          Container(\n            alignment: Alignment.centerLeft,\n            child: buildChildren(_naviTitles[index].articles),\n          ),\n        ],\n      ),\n    );\n  }\n\n  Widget buildChildren(List<NaviArticle> children) {\n\n    List<Widget> tiles = []; //先建一个数组用于存放循环生成的widget\n    Widget content; //单独一个widg\n\n    for (NaviArticle item in children) {\n      tiles.add(new InkWell(\n        child: new Chip(\n            materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,\n            backgroundColor: Utils.getChipBgColor(item.title),\n            label: new Text(item.title)),\n        onTap: () {\n          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n            return new WebViewPage(title: item.title, url: item.link);\n          }));\n        },\n      ));\n    }\n    content = Wrap(\n      spacing: 12,\n      runSpacing: 12,\n      alignment: WrapAlignment.start,\n      children: tiles,\n    );\n    return content;\n  }\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(\"不显示\"),\n    );\n  }\n\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    return Scaffold(\n      body: RefreshIndicator(\n        displacement: 15,\n        child: _rightListView(context),\n        onRefresh: _getData,\n      ),\n      floatingActionButton: !showToTopBtn\n          ? null\n          : FloatingActionButton(\n          child: Icon(Icons.arrow_upward),\n          onPressed: () {\n            //返回到顶部时执行动画\n            _scrollController.animateTo(.0,\n                duration: Duration(milliseconds: 200), curve: Curves.ease);\n          }),\n    );\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    _getData();\n  }\n}\n"
  },
  {
    "path": "lib/ui/project/project.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/common/application.dart';\nimport 'package:wanandroid_ngu/event/change_theme_event.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/projectlist_model.dart';\nimport 'package:wanandroid_ngu/model/project_tree_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\nimport 'package:wanandroid_ngu/util/theme_util.dart';\n\nclass ProjectPage extends BaseWidget {\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return ProjectPageState();\n  }\n\n}\n\nclass ProjectPageState extends BaseWidgetState<ProjectPage>\n    with TickerProviderStateMixin {\n\n  Color themeColor = ThemeUtils.currentColorTheme;\n  List<ProjectTreeData> _datas = new List();\n  TabController _tabController;\n\n  Future<Null> _getData() async {\n    ApiService().getProjectTree((ProjectTreeModel _projectTreeModel) {\n\n      if (_projectTreeModel.errorCode == 0) {\n        //成功\n        if (_projectTreeModel.data.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _datas = _projectTreeModel.data;\n          });\n        } else {\n          //数据为空\n          showEmpty();\n        }\n      } else {\n        Fluttertoast.showToast(msg: _projectTreeModel.errorMsg);\n      }\n\n    }, (DioError error) {\n        //发生错误\n        print(error.response);\n    showError();\n  });\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    setAppBarVisible(false);\n    _getData();\n    Application.eventBus.on<ChangeThemeEvent>().listen((event) {\n      setState(() {\n        themeColor = event.color;\n      });\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _tabController.dispose();\n    super.dispose();\n  }\n\n\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(\"不显示\"),\n    );\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    _tabController = new TabController(\n      vsync: this,\n      length: _datas.length,\n    );\n    return Scaffold(\n        body: Column(\n          children: <Widget>[\n            Container(\n              color: themeColor,\n              height: 48,\n              child: TabBar(\n                indicatorColor: Colors.white,\n                labelStyle:TextStyle(fontSize: 16),\n                unselectedLabelStyle: TextStyle(fontSize: 16),\n                controller: _tabController,\n                tabs: _datas.map((ProjectTreeData item) {\n                  return Tab(text: item.name);\n                }).toList(),\n                isScrollable: true,\n              ),\n            ),\n            Expanded(\n                child: TabBarView(\n                  controller: _tabController,\n                  children: _datas.map((item) {\n                    return ProjectList(item.id);\n                  }).toList(),\n                ))\n          ],\n        ));\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    _getData();\n  }\n}\n\nclass ProjectList extends StatefulWidget {\n  final int id;\n\n  ProjectList(this.id);\n\n  @override\n  _ProjectListState createState() {\n    return new _ProjectListState();\n  }\n}\n\nclass _ProjectListState extends State<ProjectList> {\n  List<ProjectTreeListDatas> _datas = new List();\n  ScrollController _scrollController = ScrollController();\n  int _page = 1;\n\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n\n  Future<Null> _getData() async {\n    _page = 1;\n    int _id = widget.id;\n    ApiService().getProjectList((ProjectTreeListModel projectTreeListModel) {\n      setState(() {\n        _datas = projectTreeListModel.data.datas;\n      });\n    }, _page, _id);\n  }\n\n  Future<Null> _getMore() async {\n    _page++;\n    int _id = widget.id;\n    ApiService().getProjectList((ProjectTreeListModel projectTreeListModel) {\n      setState(() {\n        _datas.addAll(projectTreeListModel.data.datas);\n      });\n    }, _page, _id);\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    _getData();\n    _scrollController.addListener(() {\n      if (_scrollController.position.pixels ==\n          _scrollController.position.maxScrollExtent) {\n        _getMore();\n      }\n    });\n\n    _scrollController.addListener(() {\n      //当前位置是否超过屏幕高度\n      if (_scrollController.offset < 200 && showToTopBtn) {\n        setState(() {\n          showToTopBtn = false;\n        });\n      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n        setState(() {\n          showToTopBtn = true;\n        });\n      }\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _scrollController.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: RefreshIndicator(\n        displacement: 15,\n        onRefresh: _getData,\n        child: ListView.separated(\n            itemBuilder: _renderRow,\n            physics: new AlwaysScrollableScrollPhysics(),\n            separatorBuilder: (BuildContext context, int index) {\n              return Container(\n                height: 0.5,\n                color: Colors.black26,\n              );\n            },\n            controller: _scrollController,\n            //包含加载更多\n            itemCount: _datas.length + 1),\n      ),\n      floatingActionButton: !showToTopBtn ? null : FloatingActionButton(\n          child: Icon(Icons.arrow_upward),\n          onPressed: () {\n            //返回到顶部时执行动画\n            _scrollController.animateTo(.0,\n                duration: Duration(milliseconds: 200),\n                curve: Curves.ease\n            );\n          }\n      ),\n    );\n  }\n\n  Widget _renderRow(BuildContext context, int index) {\n    if (index < _datas.length) {\n      return new InkWell(\n        onTap: () {\n          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n            return new WebViewPage(\n                title: _datas[index].title, url: _datas[index].link);\n          }));\n        },\n        child: Container(\n          color: Colors.white,\n          child:   Row(\n            children: <Widget>[\n              Expanded(\n                child: Column(\n                  crossAxisAlignment: CrossAxisAlignment.stretch,\n                  children: <Widget>[\n                    Container(\n                      padding: EdgeInsets.fromLTRB(8, 8, 8, 8),\n                      child: Row(\n                        children: <Widget>[\n                          Expanded(\n                            child: Text(\n                              _datas[index].title,\n                              maxLines: 2,\n                              style: TextStyle(\n                                fontSize: 16,\n                                fontWeight: FontWeight.bold,\n                                color: const Color(0xFF3D4E5F),\n                              ),\n                              textAlign: TextAlign.left,\n                            ),\n                          )\n                        ],\n                      ),\n                    ),\n                    Container(\n                      padding: EdgeInsets.fromLTRB(8, 0, 8, 8),\n                      child: Row(\n                        children: <Widget>[\n                          Expanded(\n                            child: Text(\n                              _datas[index].desc,\n                              style: TextStyle(fontSize: 12, color: Colors.grey),\n                              textAlign: TextAlign.left,\n                              maxLines: 3,\n                            ),\n                          )\n                        ],\n                      ),\n                    ),\n                    Container(\n                      padding: EdgeInsets.fromLTRB(8, 0, 8, 8),\n                      child: Row(\n                        mainAxisAlignment: MainAxisAlignment.spaceBetween,\n                        children: <Widget>[\n                          Text(\n                            _datas[index].author,\n                            style: TextStyle(fontSize: 12, color: Colors.grey),\n                          ),\n                          Text(\n                            _datas[index].niceDate,\n                            style: TextStyle(fontSize: 12, color: Colors.grey),\n                          ),\n\n                        ],\n                      ),\n                    )\n                  ],\n                ),\n              ),\n              Container(\n                  padding: EdgeInsets.fromLTRB(8, 16, 8, 8),\n                  child: Image.network(\n                    _datas[index].envelopePic,\n                    width: 80,\n                    height: 120,\n                    fit: BoxFit.fill,\n                  )),\n            ],\n          ) ,\n        ),\n      );\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "lib/ui/public_ui/webview_page.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:flutter_webview_plugin/flutter_webview_plugin.dart';\nimport 'package:wanandroid_ngu/util/theme_util.dart';\n\nclass WebViewPage extends StatefulWidget {\n  String title;\n  String url;\n\n  WebViewPage({\n    Key key,\n    @required this.title,\n    @required this.url,\n  }) : super(key: key);\n\n  @override\n  State<StatefulWidget> createState() {\n    return new WebViewPageState();\n  }\n}\n\nclass WebViewPageState extends State<WebViewPage> {\n  bool isLoad = true;\n  final flutterWebviewPlugin = new FlutterWebviewPlugin();\n\n  @override\n  void initState() {\n    flutterWebviewPlugin.onStateChanged.listen((state) {\n      debugPrint(\"state:_\" + state.type.toString());\n      if (state.type == WebViewState.finishLoad) {\n        setState(() {\n          isLoad = false;\n        });\n      } else if (state.type == WebViewState.startLoad) {\n        setState(() {\n          isLoad = true;\n        });\n      }\n    });\n  }\n\n//  Future<bool> _requestPop() {\n//    //相当于Android的setResult\n//    Navigator.pop(context, \"返回给上一个页面的测试数据\");\n//    return new Future.value(false);\n//  }\n\n  @override\n  Widget build(BuildContext context) {\n    return WillPopScope(\n      child: WebviewScaffold(\n        url: widget.url,\n        appBar: new AppBar(\n          elevation: 0.4,\n          title: new Text(widget.title),\n          bottom: new PreferredSize(\n            child: isLoad\n                ? new LinearProgressIndicator()\n                : new Divider(height: 1.0, color: ThemeUtils.currentColorTheme),\n            preferredSize: const Size.fromHeight(1.0),\n          ),\n        ),\n        withJavascript: true,\n        withZoom: false,\n        withLocalStorage: true,\n      ),\n    );\n  }\n}\n"
  },
  {
    "path": "lib/ui/publicc/publicc.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/common/application.dart';\nimport 'package:wanandroid_ngu/event/change_theme_event.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/wx_article_content_model.dart';\nimport 'package:wanandroid_ngu/model/wx_article_title_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\nimport 'package:wanandroid_ngu/util/theme_util.dart';\n\nclass PubliccPage extends BaseWidget {\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return PubliccPageState();\n  }\n}\n\nclass PubliccPageState extends BaseWidgetState<PubliccPage>\n    with TickerProviderStateMixin {\n\n  Color themeColor = ThemeUtils.currentColorTheme;\n\n  List<WxArticleTitleData> _datas = new List();\n  TabController _tabController;\n\n  Future<Null> _getData() async {\n    ApiService().getWxList((WxArticleTitleModel _articleTitleModel) {\n      if (_articleTitleModel.errorCode == 0) {\n        //成功\n        if (_articleTitleModel.data.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _datas = _articleTitleModel.data;\n          });\n        } else {\n          //数据为空\n          showEmpty();\n        }\n      } else {\n        Fluttertoast.showToast(msg: _articleTitleModel.errorMsg);\n      }\n    }, (DioError error) {\n      //发生错误\n      print(error.response);\n      showError();\n    });\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    setAppBarVisible(false);\n    _getData();\n\n    Application.eventBus.on<ChangeThemeEvent>().listen((event) {\n      setState(() {\n        themeColor = event.color;\n      });\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _tabController.dispose();\n    super.dispose();\n  }\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(\"不显示\"),\n    );\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    _tabController = new TabController(\n      vsync: this,\n      length: _datas.length,\n    );\n    return Scaffold(\n        body: Column(\n      children: <Widget>[\n        Container(\n          color: themeColor,\n          height: 48,\n          child: TabBar(\n            indicatorColor: Colors.white,\n            labelStyle: TextStyle(fontSize: 16),\n            unselectedLabelStyle: TextStyle(fontSize: 16),\n            controller: _tabController,\n            tabs: _datas.map((WxArticleTitleData item) {\n              return Tab(text: item.name);\n            }).toList(),\n            isScrollable: true,\n          ),\n        ),\n        Expanded(\n            child: TabBarView(\n          controller: _tabController,\n          children: _datas.map((item) {\n            return NewsList(item.id);\n          }).toList(),\n        ))\n      ],\n    ));\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    _getData();\n  }\n}\n\nclass NewsList extends StatefulWidget {\n  final int id;\n  NewsList(this.id);\n\n  @override\n  _NewsListState createState() {\n    return new _NewsListState();\n  }\n}\n\nclass _NewsListState extends State<NewsList> {\n  List<WxArticleContentDatas> _datas = new List();\n  ScrollController _scrollController = ScrollController();\n  int _page = 1;\n\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n\n  Future<Null> _getData() async {\n    _page = 1;\n    int _id = widget.id;\n    ApiService().getWxArticleList(\n        (WxArticleContentModel _wxArticleContentModel) {\n      setState(() {\n        _datas = _wxArticleContentModel.data.datas;\n      });\n    }, _id, _page);\n  }\n\n  Future<Null> _getMore() async {\n    _page++;\n    int _id = widget.id;\n    ApiService().getWxArticleList((WxArticleContentModel _articleContentModel) {\n      setState(() {\n        _datas.addAll(_articleContentModel.data.datas);\n      });\n    }, _id, _page);\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    _getData();\n    _scrollController.addListener(() {\n      if (_scrollController.position.pixels ==\n          _scrollController.position.maxScrollExtent) {\n        _getMore();\n      }\n    });\n\n    _scrollController.addListener(() {\n      //当前位置是否超过屏幕高度\n      if (_scrollController.offset < 200 && showToTopBtn) {\n        setState(() {\n          showToTopBtn = false;\n        });\n      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n        setState(() {\n          showToTopBtn = true;\n        });\n      }\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _scrollController.dispose();\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    return Scaffold(\n      body: RefreshIndicator(\n        displacement: 15,\n        onRefresh: _getData,\n        child: ListView.separated(\n            physics: new AlwaysScrollableScrollPhysics(),\n            itemBuilder: _renderRow,\n            separatorBuilder: (BuildContext context, int index) {\n              return Container(\n                height: 0.5,\n                color: Colors.black26,\n              );\n            },\n            controller: _scrollController,\n            //包含加载更多\n            itemCount: _datas.length + 1),\n      ),\n      floatingActionButton: !showToTopBtn\n          ? null\n          : FloatingActionButton(\n              child: Icon(Icons.arrow_upward),\n              onPressed: () {\n                //返回到顶部时执行动画\n                _scrollController.animateTo(.0,\n                    duration: Duration(milliseconds: 200), curve: Curves.ease);\n              }),\n    );\n  }\n\n  Widget _renderRow(BuildContext context, int index) {\n    if (index < _datas.length) {\n      return new InkWell(\n        onTap: () {\n          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n            return new WebViewPage(\n                title: _datas[index].title, url: _datas[index].link);\n          }));\n        },\n        child: Column(\n          children: <Widget>[\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 16, 16, 8),\n              child: Row(\n                children: <Widget>[\n                  Text(\n                    _datas[index].author,\n                    style: TextStyle(fontSize: 12),\n                    textAlign: TextAlign.left,\n                  ),\n                  Expanded(\n                    child: Text(\n                      _datas[index].niceDate,\n                      style: TextStyle(fontSize: 12),\n                      textAlign: TextAlign.right,\n                    ),\n                  ),\n                ],\n              ),\n            ),\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 0, 16, 0),\n              child: Row(\n                children: <Widget>[\n                  Expanded(\n                    child: Text(\n                      _datas[index].title,\n                      maxLines: 2,\n                      style: TextStyle(\n                        fontSize: 16,\n                        fontWeight: FontWeight.bold,\n                        color: const Color(0xFF3D4E5F),\n                      ),\n                      textAlign: TextAlign.left,\n                    ),\n                  )\n                ],\n              ),\n            ),\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 8, 16, 16),\n              child: Row(\n                children: <Widget>[\n                  Expanded(\n                    child: Text(\n                      _datas[index].superChapterName,\n                      style: TextStyle(fontSize: 12),\n                      textAlign: TextAlign.left,\n                    ),\n                  )\n                ],\n              ),\n            ),\n          ],\n        ),\n      );\n    }\n    return null;\n  }\n}\n"
  },
  {
    "path": "lib/ui/search/hot_search_result.dart",
    "content": "import 'package:dio/dio.dart';\nimport 'package:flutter/material.dart';\nimport 'package:fluttertoast/fluttertoast.dart';\nimport 'package:wanandroid_ngu/base/_base_widget.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/hotword_result_model.dart';\nimport 'package:wanandroid_ngu/ui/public_ui/webview_page.dart';\n\nclass HotResultPage extends BaseWidget {\n  String hot;\n  HotResultPage(this.hot);\n\n  @override\n  BaseWidgetState<BaseWidget> getState() {\n    return HotResultPageState();\n  }\n}\n\nclass HotResultPageState extends BaseWidgetState<HotResultPage> {\n  List<DatasListBean> _datas = new List();\n  ScrollController _scrollController = ScrollController();\n  int _page = 0;\n\n  bool showToTopBtn = false; //是否显示“返回到顶部”按钮\n\n  Future<Null> _getData() async {\n    _page = 0;\n    String _keyword = widget.hot;\n    ApiService().getSearchResult((HotwordResultModel otwordResultModel) {\n\n      if (otwordResultModel.errorCode == 0) {\n        //成功\n        if (otwordResultModel.data.datas.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _datas.clear();\n            _datas.addAll(otwordResultModel.data.datas);\n          });\n        } else {\n          //数据为空\n          showEmpty();\n        }\n      } else {\n        Fluttertoast.showToast(msg: otwordResultModel.errorMsg);\n      }\n    },(DioError error) {\n      //发生错误\n      print(error.response);\n      showError();\n    }, _page, _keyword);\n  }\n\n  Future<Null> _getMore() async {\n    _page++;\n    String _keyword = widget.hot;\n    ApiService().getSearchResult((HotwordResultModel otwordResultModel) {\n\n      if (otwordResultModel.errorCode == 0) {\n        //成功\n        if (otwordResultModel.data.datas.length > 0) {\n          //有数据\n          showContent();\n          setState(() {\n            _datas.addAll(otwordResultModel.data.datas);\n          });\n        } else {\n          //数据为空\n          Fluttertoast.showToast(msg: \"没有更多数据了\");\n        }\n      } else {\n        Fluttertoast.showToast(msg: otwordResultModel.errorMsg);\n      }\n\n    },(DioError error) {\n      //发生错误\n      print(error.response);\n      showError();\n    }, _page, _keyword);\n  }\n\n  @override\n  void initState() {\n    super.initState();\n    showloading();\n    _getData();\n\n    _scrollController.addListener(() {\n      if (_scrollController.position.pixels ==\n          _scrollController.position.maxScrollExtent) {\n        _getMore();\n      }\n    });\n\n    _scrollController.addListener(() {\n      //当前位置是否超过屏幕高度\n      if (_scrollController.offset < 200 && showToTopBtn) {\n        setState(() {\n          showToTopBtn = false;\n        });\n      } else if (_scrollController.offset >= 200 && showToTopBtn == false) {\n        setState(() {\n          showToTopBtn = true;\n        });\n      }\n    });\n  }\n\n  @override\n  void dispose() {\n    super.dispose();\n    _scrollController.dispose();\n  }\n\n  Widget _renderRow(BuildContext context, int index) {\n    if (index < _datas.length) {\n      return new InkWell(\n        onTap: () {\n          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n            return new WebViewPage(\n                title: _datas[index]\n                    .title\n                    .replaceAll(\"<em class='highlight'>\", \"\")\n                    .replaceAll(\"<\\/em>\", \"\"),\n                url: _datas[index].link);\n          }));\n        },\n        child: Column(\n          children: <Widget>[\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 16, 16, 8),\n              child: Row(\n                children: <Widget>[\n                  Text(\n                    _datas[index].author,\n                    style: TextStyle(fontSize: 12),\n                    textAlign: TextAlign.left,\n                  ),\n                  Expanded(\n                    child: Text(\n                      _datas[index].niceDate,\n                      style: TextStyle(fontSize: 12),\n                      textAlign: TextAlign.right,\n                    ),\n                  ),\n                ],\n              ),\n            ),\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 0, 16, 0),\n              child: Row(\n                children: <Widget>[\n                  Expanded(\n                    child: Text(\n                      _datas[index]\n                          .title\n                          .replaceAll(\"<em class='highlight'>\", \"\")\n                          .replaceAll(\"<\\/em>\", \"\"),\n                      maxLines: 2,\n                      style: TextStyle(\n                        fontSize: 16,\n                        fontWeight: FontWeight.bold,\n                        color: const Color(0xFF3D4E5F),\n                      ),\n                      textAlign: TextAlign.left,\n                    ),\n                  )\n                ],\n              ),\n            ),\n            Container(\n              color: Colors.white,\n              padding: EdgeInsets.fromLTRB(16, 8, 16, 16),\n              child: Row(\n                children: <Widget>[\n                  Expanded(\n                    child: Text(\n                      _datas[index].superChapterName,\n                      style: TextStyle(fontSize: 12),\n                      textAlign: TextAlign.left,\n                    ),\n                  )\n                ],\n              ),\n            ),\n          ],\n        ),\n      );\n    }\n    return null;\n  }\n\n  @override\n  AppBar getAppBar() {\n    return AppBar(\n      title: Text(widget.hot),\n    );\n  }\n\n  @override\n  Widget getContentWidget(BuildContext context) {\n    return Scaffold(\n      body: RefreshIndicator(\n        onRefresh: _getData,\n        child: ListView.separated(\n            itemBuilder: _renderRow,\n            physics: new AlwaysScrollableScrollPhysics(),\n            separatorBuilder: (BuildContext context, int index) {\n              return Container(\n                height: 0.5,\n                color: Colors.black26,\n              );\n            },\n            controller: _scrollController,\n            //包含加载更多\n            itemCount: _datas.length + 1),\n      ),\n      floatingActionButton: !showToTopBtn\n          ? null\n          : FloatingActionButton(\n          child: Icon(Icons.arrow_upward),\n          onPressed: () {\n            //返回到顶部时执行动画\n            _scrollController.animateTo(.0,\n                duration: Duration(milliseconds: 200), curve: Curves.ease);\n          }),\n    );\n  }\n\n  @override\n  void onClickErrorWidget() {\n    showloading();\n    _getData();\n  }\n}\n"
  },
  {
    "path": "lib/ui/search/search.dart",
    "content": "import 'package:flutter/material.dart';\nimport 'package:wanandroid_ngu/http/api_service.dart';\nimport 'package:wanandroid_ngu/model/hotword_model.dart';\nimport 'package:wanandroid_ngu/ui/search/hot_search_result.dart';\nimport 'package:wanandroid_ngu/util/utils.dart';\n\nclass SearchPage extends StatefulWidget {\n  @override\n  State<StatefulWidget> createState() {\n    return SearchPageState();\n  }\n}\n\nclass SearchPageState extends State<SearchPage> {\n  TextEditingController editingController;\n  FocusNode focusNode = new FocusNode();\n  List<Widget> actions = new List();\n  List<DataListBean> _datas = new List();\n\n  String search;\n\n  @override\n  void initState() {\n    super.initState();\n\n    editingController = new TextEditingController(text: search);\n    editingController.addListener(() {\n      if (editingController.text == null || editingController.text == \"\") {\n        setState(() {\n          actions = [\n            IconButton(\n                icon: Icon(Icons.search),\n                onPressed: () {\n                  changeContent();\n                })\n          ];\n        });\n      } else {\n        setState(() {\n          actions = [\n            IconButton(\n                icon: Icon(Icons.close),\n                onPressed: () {\n                  editingController.clear();\n                  changeContent();\n                }),\n            IconButton(\n                icon: Icon(Icons.search),\n                onPressed: () {\n                  changeContent();\n                })\n          ];\n        });\n      }\n    });\n    _getData();\n  }\n\n  //获取文章列表数据\n  Future<Null> _getData() async {\n    ApiService().getSearchHotWord((HotwordModel hotwordModel) {\n      setState(() {\n        _datas = hotwordModel.data;\n      });\n    });\n  }\n\n  void changeContent() {\n    focusNode.unfocus();\n    setState(() {});\n    if (editingController.text == null || editingController.text == \"\") {\n\n    }else{\n      Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n        return new HotResultPage(editingController.text);\n      }));\n    }\n\n  }\n\n  @override\n  Widget build(BuildContext context) {\n    TextField searchField = new TextField(\n      autofocus: true,\n      style: TextStyle(color: Colors.white),\n      decoration: new InputDecoration(\n          hintStyle: TextStyle(color: Colors.white),\n          border: InputBorder.none,\n          hintText: \"搜索更多干货\"),\n      focusNode: focusNode,\n      controller: editingController,\n    );\n\n    return Scaffold(\n      appBar: AppBar(\n        title: searchField,\n        actions: actions,\n      ),\n      body: buildChildren(_datas),\n    );\n  }\n\n  Widget buildChildren(List<DataListBean> children) {\n    List<Widget> names = []; //先建一个数组用于存放循环生成的widget\n    Widget content; //单独一个widg\n\n    for (DataListBean item in children) {\n      names.add(new InkWell(\n        child: new Chip(\n            materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,\n            backgroundColor: Utils.getChipBgColor(item.name),\n            label: new Text(item.name)),\n        onTap: () {\n          Navigator.of(context).push(new MaterialPageRoute(builder: (context) {\n            return new HotResultPage(item.name);\n          }));\n        },\n      ));\n    }\n    content = Padding(\n        padding: EdgeInsets.only(left: 20),\n        child: Wrap(\n          spacing: 12,\n          runSpacing: 12,\n          alignment: WrapAlignment.start,\n          children: names,\n        ));\n    return Column(\n      crossAxisAlignment: CrossAxisAlignment.start,\n      children: <Widget>[\n        Padding(\n          padding: EdgeInsets.all(15),\n          child: Text(\n            \"热门搜索\",\n            style: TextStyle(color: const Color(0xFF5394FF), fontSize: 18),\n          ),\n        ),\n        content,\n      ],\n    );\n  }\n}\n"
  },
  {
    "path": "lib/util/bubble_indication_painter.dart",
    "content": "import 'dart:math';\n\nimport 'package:flutter/material.dart';\n\nclass TabIndicationPainter extends CustomPainter {\n  Paint painter;\n  final double dxTarget;\n  final double dxEntry;\n  final double radius;\n  final double dy;\n\n  final PageController pageController;\n\n  TabIndicationPainter(\n      {this.dxTarget = 125.0,\n        this.dxEntry = 25.0,\n        this.radius = 21.0,\n        this.dy = 25.0, this.pageController}) : super(repaint: pageController) {\n    painter = new Paint()\n      ..color = Color(0xFFFFFFFF)\n      ..style = PaintingStyle.fill;\n  }\n\n  @override\n  void paint(Canvas canvas, Size size) {\n\n    final pos = pageController.position;\n    double fullExtent = (pos.maxScrollExtent - pos.minScrollExtent + pos.viewportDimension);\n\n    double pageOffset = pos.extentBefore / fullExtent;\n\n    bool left2right = dxEntry < dxTarget;\n    Offset entry = new Offset(left2right ? dxEntry: dxTarget, dy);\n    Offset target = new Offset(left2right ? dxTarget : dxEntry, dy);\n\n    Path path = new Path();\n    path.addArc(\n        new Rect.fromCircle(center: entry, radius: radius), 0.5 * pi, 1 * pi);\n    path.addRect(\n        new Rect.fromLTRB(entry.dx, dy - radius, target.dx, dy + radius));\n    path.addArc(\n        new Rect.fromCircle(center: target, radius: radius), 1.5 * pi, 1 * pi);\n\n    canvas.translate(size.width * pageOffset, 0.0);\n    canvas.drawPath(path, painter);\n  }\n\n  @override\n  bool shouldRepaint(TabIndicationPainter oldDelegate) => true;\n}"
  },
  {
    "path": "lib/util/style_util.dart",
    "content": "import 'package:flutter/material.dart';\n\n\nclass StyleUtil {\n\n  /**\n   * TextStyle:封装\n   * colors:颜色\n   * fontsizes：字体大小\n   * isFontWeight：是否加粗\n   */\n  static TextStyle  getTextStyle(Color colors,double fontsizes,bool isFontWeight){\n    return TextStyle(\n      color:colors,\n      fontSize: fontsizes,\n      fontWeight: isFontWeight == true ? FontWeight.bold : FontWeight.normal ,\n    );\n  }\n  /**\n   * 组件加上下左右padding\n   * w:所要加padding的组件\n   * all:加多少padding\n   */\n  static Widget getPadding(Widget w,double all){\n    return Padding(\n      child:w,\n      padding:EdgeInsets.all(all),\n    );\n  }\n\n  /**\n   * 组件选择性加padding\n   * 这里用了位置可选命名参数{param1,param2,...}来命名参数，也调用的时候可以不传\n   *\n   */\n  static Widget getPaddingfromLTRB(Widget w,{double l,double t,double,r,double b}){\n    return Padding(\n      child:w,\n      padding:EdgeInsets.fromLTRB(l ?? 0,t ?? 0,r ?? 0,b ?? 0),\n    );\n  }\n\n\n\n}"
  },
  {
    "path": "lib/util/theme_util.dart",
    "content": "import 'package:flutter/material.dart';\n\nclass ThemeUtils {\n  // 默认主题色\n  static const Color defaultColor =Colors.redAccent ;\n\n  // 可选的主题色\n  static const List<Color> supportColors = [const Color(0xFF5394FF), Colors.purple, Colors.orange, Colors.deepPurpleAccent, Colors.redAccent, Colors.blue, Colors.amber, Colors.green, Colors.lime, Colors.indigo, Colors.cyan, Colors.teal];\n\n  // 当前的主题色\n  static Color currentColorTheme = defaultColor;\n}"
  },
  {
    "path": "lib/util/utils.dart",
    "content": "import 'package:common_utils/common_utils.dart';\nimport 'package:flutter/material.dart';\nimport 'package:lpinyin/lpinyin.dart';\nimport 'package:shared_preferences/shared_preferences.dart';\n\nclass Utils {\n\n  static final String SP_COLOR_THEME_INDEX = \"colorThemeIndex\";\n\n  static String getImgPath(String name, {String format: 'png'}) {\n    return 'assets/images/$name.$format';\n  }\n\n  static String getPinyin(String str) {\n    return PinyinHelper.getShortPinyin(str).substring(0, 1).toUpperCase();\n  }\n\n  static Color getChipBgColor(String name) {\n    String pinyin = PinyinHelper.getFirstWordPinyin(name);\n    pinyin = pinyin.substring(0, 1).toUpperCase();\n    return nameToColor(pinyin);\n  }\n\n  static Color nameToColor(String name) {\n    // assert(name.length > 1);\n    final int hash = name.hashCode & 0xffff;\n    final double hue = (360.0 * hash / (1 << 15)) % 360.0;\n    return HSVColor.fromAHSV(1.0, hue, 0.4, 0.90).toColor();\n  }\n\n  static String getTimeLine(BuildContext context, int timeMillis) {\n//    LogUtil.e(\"countryCode: \" +\n//        Localizations.localeOf(context).countryCode +\n//        \"   languageCode: \" +\n//        Localizations.localeOf(context).languageCode);\n    return TimelineUtil.format(timeMillis,\n        locale: Localizations.localeOf(context).languageCode,\n        dayFormat: DayFormat.Common);\n  }\n\n  static double getTitleFontSize(String title) {\n    if (ObjectUtil.isEmpty(title) || title.length < 10) {\n      return 18.0;\n    }\n    int count = 0;\n    List<String> list = title.split(\"\");\n    for (int i = 0, length = list.length; i < length; i++) {\n      String ss = list[i];\n      if (RegexUtil.isZh(ss)) {\n        count++;\n      }\n    }\n\n    return (count >= 10 || title.length > 16) ? 14.0 : 18.0;\n  }\n\n  // 设置选择的主题色\n  static setColorTheme(int colorThemeIndex) async {\n    SharedPreferences sp = await SharedPreferences.getInstance();\n    sp.setInt(SP_COLOR_THEME_INDEX, colorThemeIndex);\n  }\n\n  static Future<int> getColorThemeIndex() async {\n    SharedPreferences sp = await SharedPreferences.getInstance();\n    return sp.getInt(SP_COLOR_THEME_INDEX);\n  }\n\n\n}\n"
  },
  {
    "path": "pubspec.yaml",
    "content": "name: wanandroid_ngu\ndescription: A new Flutter application.\n\n# The following defines the version and build number for your application.\n# A version number is three numbers separated by dots, like 1.2.43\n# followed by an optional build number separated by a +.\n# Both the version and the builder number may be overridden in flutter\n# build by specifying --build-name and --build-number, respectively.\n# Read more about versioning at semver.org.\nversion: 1.0.5+5\n\nenvironment:\n  sdk: \">=2.0.0-dev.68.0 <3.0.0\"\n\ndependencies:\n  flutter:\n    sdk: flutter\n\n  # The following adds the Cupertino Icons font to your application.\n  # Use with the CupertinoIcons class for iOS style icons.\n  cupertino_icons: ^0.1.2\n  flutter_swiper: ^1.1.4\n  flutter_webview_plugin: ^0.3.0+2\n  dio: ^2.1.0\n  shared_preferences: ^0.4.3\n  fluttertoast: ^3.1.0\n  event_bus: ^1.0.3\n  flutter_slidable: ^0.4.9\n  # 汉字转拼音库 https://github.com/flutterchina/lpinyin\n  lpinyin: ^1.0.7\n  # Dart 常用工具类库 https://github.com/Sky24n/common_utils\n  common_utils: ^1.0.9\n  flutter_screenutil: ^0.5.0\n  intro_slider: ^1.2.0\n  share: ^0.6.0+1\n  # 查看图片\n  photo_view: ^0.2.2\n  #数据\n  sqflite: ^1.1.3\n  #文件读写\n  path_provider: ^0.5.0+1\n\ndev_dependencies:\n  flutter_test:\n    sdk: flutter\n  font_awesome_flutter: ^8.0.1\n\n\n# For information on the generic Dart part of this file, see the\n# following page: https://www.dartlang.org/tools/pub/pubspec\n\n# The following section is specific to Flutter.\nflutter:\n\n  # The following line ensures that the Material Icons font is\n  # included with your application, so that you can use the icons in\n  # the material Icons class.\n  uses-material-design: true\n\n  assets:\n\n  #加载页面图片资源\n  - images/loading.png\n  - images/flutter.png\n  - images/head.jpg\n  - images/arrow_right.png\n  - images/ic_error.png\n  - images/ic_empty.png"
  },
  {
    "path": "test/widget_test.dart",
    "content": "// This is a basic Flutter widget test.\n//\n// To perform an interaction with a widget in your test, use the WidgetTester\n// utility that Flutter provides. For example, you can send tap and scroll\n// gestures. You can also use WidgetTester to find child widgets in the widget\n// tree, read text, and verify that the values of widget properties are correct.\n\nimport 'package:flutter/material.dart';\nimport 'package:flutter_test/flutter_test.dart';\n\nimport 'package:wanandroid_ngu/main.dart';\n\nvoid main() {\n  testWidgets('Counter increments smoke test', (WidgetTester tester) async {\n    // Build our app and trigger a frame.\n    await tester.pumpWidget(MyApp());\n\n    // Verify that our counter starts at 0.\n    expect(find.text('0'), findsOneWidget);\n    expect(find.text('1'), findsNothing);\n\n    // Tap the '+' icon and trigger a frame.\n    await tester.tap(find.byIcon(Icons.add));\n    await tester.pump();\n\n    // Verify that our counter has incremented.\n    expect(find.text('0'), findsNothing);\n    expect(find.text('1'), findsOneWidget);\n  });\n}\n"
  }
]