[
  {
    "path": ".gitignore",
    "content": ".gradle\n/local.properties\n.DS_Store\n/build\n/captures\n\n.idea\n\n*.iml\n\n# built application files\n*.apk\n*.ap_\n\n!/apk/app-release*\n\n# files for the dex VM\n*.dex\n\n# Java class files\n*.class\n\n# generated files\nbin/\ngen/\n\n# Eclipse project files\n.classpath\n.project\n\n# Proguard folder generated by Eclipse\nproguard/\n\n# Intellij project files\n*.ipr\n*.iws\n"
  },
  {
    "path": "LICENSE",
    "content": "Apache License\nVersion 2.0, January 2004\nhttp://www.apache.org/licenses/\n\nTERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n1. Definitions.\n\n\"License\" shall mean the terms and conditions for use, reproduction, and\ndistribution as defined by Sections 1 through 9 of this document.\n\n\"Licensor\" shall mean the copyright owner or entity authorized by the copyright\nowner that is granting the License.\n\n\"Legal Entity\" shall mean the union of the acting entity and all other entities\nthat control, are controlled by, or are under common control with that entity.\nFor the purposes of this definition, \"control\" means (i) the power, direct or\nindirect, to cause the direction or management of such entity, whether by\ncontract or otherwise, or (ii) ownership of fifty percent (50%) or more of the\noutstanding shares, or (iii) beneficial ownership of such entity.\n\n\"You\" (or \"Your\") shall mean an individual or Legal Entity exercising\npermissions granted by this License.\n\n\"Source\" form shall mean the preferred form for making modifications, including\nbut not limited to software source code, documentation source, and configuration\nfiles.\n\n\"Object\" form shall mean any form resulting from mechanical transformation or\ntranslation of a Source form, including but not limited to compiled object code,\ngenerated documentation, and conversions to other media types.\n\n\"Work\" shall mean the work of authorship, whether in Source or Object form, made\navailable under the License, as indicated by a copyright notice that is included\nin or attached to the work (an example is provided in the Appendix below).\n\n\"Derivative Works\" shall mean any work, whether in Source or Object form, that\nis based on (or derived from) the Work and for which the editorial revisions,\nannotations, elaborations, or other modifications represent, as a whole, an\noriginal work of authorship. For the purposes of this License, Derivative Works\nshall not include works that remain separable from, or merely link (or bind by\nname) to the interfaces of, the Work and Derivative Works thereof.\n\n\"Contribution\" shall mean any work of authorship, including the original version\nof the Work and any modifications or additions to that Work or Derivative Works\nthereof, that is intentionally submitted to Licensor for inclusion in the Work\nby the copyright owner or by an individual or Legal Entity authorized to submit\non behalf of the copyright owner. For the purposes of this definition,\n\"submitted\" means any form of electronic, verbal, or written communication sent\nto the Licensor or its representatives, including but not limited to\ncommunication on electronic mailing lists, source code control systems, and\nissue tracking systems that are managed by, or on behalf of, the Licensor for\nthe purpose of discussing and improving the Work, but excluding communication\nthat is conspicuously marked or otherwise designated in writing by the copyright\nowner as \"Not a Contribution.\"\n\n\"Contributor\" shall mean Licensor and any individual or Legal Entity on behalf\nof whom a Contribution has been received by Licensor and subsequently\nincorporated within the Work.\n\n2. Grant of Copyright License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable copyright license to reproduce, prepare Derivative Works of,\npublicly display, publicly perform, sublicense, and distribute the Work and such\nDerivative Works in Source or Object form.\n\n3. Grant of Patent License.\n\nSubject to the terms and conditions of this License, each Contributor hereby\ngrants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free,\nirrevocable (except as stated in this section) patent license to make, have\nmade, use, offer to sell, sell, import, and otherwise transfer the Work, where\nsuch license applies only to those patent claims licensable by such Contributor\nthat are necessarily infringed by their Contribution(s) alone or by combination\nof their Contribution(s) with the Work to which such Contribution(s) was\nsubmitted. If You institute patent litigation against any entity (including a\ncross-claim or counterclaim in a lawsuit) alleging that the Work or a\nContribution incorporated within the Work constitutes direct or contributory\npatent infringement, then any patent licenses granted to You under this License\nfor that Work shall terminate as of the date such litigation is filed.\n\n4. Redistribution.\n\nYou may reproduce and distribute copies of the Work or Derivative Works thereof\nin any medium, with or without modifications, and in Source or Object form,\nprovided that You meet the following conditions:\n\nYou must give any other recipients of the Work or Derivative Works a copy of\nthis License; and\nYou must cause any modified files to carry prominent notices stating that You\nchanged the files; and\nYou must retain, in the Source form of any Derivative Works that You distribute,\nall copyright, patent, trademark, and attribution notices from the Source form\nof the Work, excluding those notices that do not pertain to any part of the\nDerivative Works; and\nIf the Work includes a \"NOTICE\" text file as part of its distribution, then any\nDerivative Works that You distribute must include a readable copy of the\nattribution notices contained within such NOTICE file, excluding those notices\nthat do not pertain to any part of the Derivative Works, in at least one of the\nfollowing places: within a NOTICE text file distributed as part of the\nDerivative Works; within the Source form or documentation, if provided along\nwith the Derivative Works; or, within a display generated by the Derivative\nWorks, if and wherever such third-party notices normally appear. The contents of\nthe NOTICE file are for informational purposes only and do not modify the\nLicense. You may add Your own attribution notices within Derivative Works that\nYou distribute, alongside or as an addendum to the NOTICE text from the Work,\nprovided that such additional attribution notices cannot be construed as\nmodifying the License.\nYou may add Your own copyright statement to Your modifications and may provide\nadditional or different license terms and conditions for use, reproduction, or\ndistribution of Your modifications, or for any such Derivative Works as a whole,\nprovided Your use, reproduction, and distribution of the Work otherwise complies\nwith the conditions stated in this License.\n\n5. Submission of Contributions.\n\nUnless You explicitly state otherwise, any Contribution intentionally submitted\nfor inclusion in the Work by You to the Licensor shall be under the terms and\nconditions of this License, without any additional terms or conditions.\nNotwithstanding the above, nothing herein shall supersede or modify the terms of\nany separate license agreement you may have executed with Licensor regarding\nsuch Contributions.\n\n6. Trademarks.\n\nThis License does not grant permission to use the trade names, trademarks,\nservice marks, or product names of the Licensor, except as required for\nreasonable and customary use in describing the origin of the Work and\nreproducing the content of the NOTICE file.\n\n7. Disclaimer of Warranty.\n\nUnless required by applicable law or agreed to in writing, Licensor provides the\nWork (and each Contributor provides its Contributions) on an \"AS IS\" BASIS,\nWITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied,\nincluding, without limitation, any warranties or conditions of TITLE,\nNON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are\nsolely responsible for determining the appropriateness of using or\nredistributing the Work and assume any risks associated with Your exercise of\npermissions under this License.\n\n8. Limitation of Liability.\n\nIn no event and under no legal theory, whether in tort (including negligence),\ncontract, or otherwise, unless required by applicable law (such as deliberate\nand grossly negligent acts) or agreed to in writing, shall any Contributor be\nliable to You for damages, including any direct, indirect, special, incidental,\nor consequential damages of any character arising as a result of this License or\nout of the use or inability to use the Work (including but not limited to\ndamages for loss of goodwill, work stoppage, computer failure or malfunction, or\nany and all other commercial damages or losses), even if such Contributor has\nbeen advised of the possibility of such damages.\n\n9. Accepting Warranty or Additional Liability.\n\nWhile redistributing the Work or Derivative Works thereof, You may choose to\noffer, and charge a fee for, acceptance of support, warranty, indemnity, or\nother liability obligations and/or rights consistent with this License. However,\nin accepting such obligations, You may act only on Your own behalf and on Your\nsole responsibility, not on behalf of any other Contributor, and only if You\nagree to indemnify, defend, and hold each Contributor harmless for any liability\nincurred by, or claims asserted against, such Contributor by reason of your\naccepting any such warranty or additional liability.\n\nEND OF TERMS AND CONDITIONS\n\nAPPENDIX: How to apply the Apache License to your work\n\nTo apply the Apache License to your work, attach the following boilerplate\nnotice, with the fields enclosed by brackets \"{}\" replaced with your own\nidentifying information. (Don't include the brackets!) The text should be\nenclosed in the appropriate comment syntax for the file format. We also\nrecommend that a file or class name and description of purpose be included on\nthe same \"printed page\" as the copyright notice for easier identification within\nthird-party archives.\n\n   Copyright 2015 zzhoujay\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n     http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "README.md",
    "content": "#Gank4Android\r\n\r\n> Deprecated 推荐使用更加简介的[DailyGank](https://github.com/zzhoujay/DailyGank)\r\n\r\n> 使用`Groovy`开发的`Gank.IO` `Android`客户端\r\n>\r\n> 遵循Google `Material Design`设计原则\r\n\r\n### 提示\r\n\r\n由于Groovy的效率问题，和由于Groovy引入的一系列问题，本项目将不再推荐使用，推荐使用[DailyGank](https://github.com/zzhoujay/DailyGank)来阅读每天的干货，DailyGank使用Kotlin开发，\r\n并且设计得十分的简洁，比本项目更快更轻量，推荐使用  \r\n**本项目将不再维护**\r\n\r\n### 关于本项目\r\n\r\n* 使用Groovy语言编写,使用[`groovy-android-gradle-plugin`](https://github.com/groovy/groovy-android-gradle-plugin)构建\r\n* 项目中全面使用svg矢量图,感谢[`BetterVectorDrawable`](https://github.com/a-student/BetterVectorDrawable)\r\n* 对应GitHub地址:<https://github.com/zzhoujay/Gank4Android>\r\n\r\n### release版本\r\n\r\n由于github的release中上传比较慢可以到[此处下载](http://www.pgyer.com/gank4android)\r\n\r\n### 截图\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220758_085c1eb1_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220831_147fc0c6_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220846_6352f286_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220909_17bb9a0e_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220925_e86328e7_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220933_ca9446c7_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220940_187a5e9b_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220953_e16a8999_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/220959_513cdc48_141009.jpeg \"运行截图\")\r\n![运行截图](http://git.oschina.net/uploads/images/2015/0929/221006_39429de7_141009.jpeg \"运行截图\")\r\n\r\n_by zzhoujay_\r\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:1.3.0'\n        classpath 'org.codehaus.groovy:gradle-groovy-android-plugin:0.3.6'\n    }\n}\napply plugin: 'groovyx.grooid.groovy-android'\n\nandroid {\n    compileSdkVersion 22\n    buildToolsVersion \"22.0.1\"\n\n    defaultConfig {\n        applicationId \"zhou.gank.io\"\n        minSdkVersion 15\n        targetSdkVersion 22\n        versionCode 3\n        versionName \"1.11\"\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\nproject.androidGroovy {\n    options {\n        sourceCompatibility = '1.7'\n        targetCompatibility = '1.7'\n    }\n}\n\ndependencies {\n    compile fileTree(include: ['*.jar'], dir: 'libs')\n    compile 'com.android.support:design:22.2.1'\n    compile 'com.android.support:appcompat-v7:22.2.1'\n    compile 'com.android.support:cardview-v7:22.2.1'\n    compile 'com.android.support:recyclerview-v7:22.2.1'\n    compile 'org.codehaus.groovy:groovy:2.4.3:grooid'\n    compile('org.codehaus.groovy:groovy-json:2.4.3') {\n        transitive = false\n    }\n    compile 'com.squareup.picasso:picasso:2.5.2'\n    compile 'com.jakewharton:butterknife:7.0.1'\n    compile 'com.bettervectordrawable:lib:0.4'\n    compile 'com.google.code.gson:gson:2.3.1'\n    compile 'com.squareup.okhttp:okhttp:2.5.0'\n    compile 'com.github.flavienlaurent.datetimepicker:library:0.0.2'\n    compile 'zhou.widget:advanceadapter:1.0'\n\n}\n"
  },
  {
    "path": "app/proguard-rules.pro",
    "content": "# Add project specific ProGuard rules here.\n# By default, the flags in this file are appended to flags specified\n# in /Users/zhou/Library/Android/sdk/tools/proguard/proguard-android.txt\n# You can edit the include path and order by changing the proguardFiles\n# directive in build.gradle.\n#\n# For more details, see\n#   http://developer.android.com/guide/developing/tools/proguard.html\n\n# Add any project specific keep options here:\n\n# If your project uses WebView with JS, uncomment the following\n# and specify the fully qualified class name to the JavaScript interface\n# class:\n#-keepclassmembers class fqcn.of.javascript.interface.for.webview {\n#   public *;\n#}\n"
  },
  {
    "path": "app/src/androidTest/java/zhou/gank/io/ApplicationTest.java",
    "content": "package zhou.gank.io;\n\nimport android.app.Application;\nimport android.test.ApplicationTestCase;\n\n/**\n * <a href=\"http://d.android.com/tools/testing/testing_android.html\">Testing Fundamentals</a>\n */\npublic class ApplicationTest extends ApplicationTestCase<Application> {\n    public ApplicationTest() {\n        super(Application.class);\n    }\n}"
  },
  {
    "path": "app/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"zhou.gank.io\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n\n    <application\n        android:name=\".App\"\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/ic_launcher\"\n        android:label=\"@string/app_name\"\n        android:theme=\"@style/AppTheme\">\n\n        <activity\n            android:name=\".MainActivity\"\n            android:screenOrientation=\"portrait\">\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        <activity\n            android:name=\".ui.activity.HomeActivity\"\n            android:screenOrientation=\"portrait\" />\n        <activity\n            android:name=\".ui.activity.TabActivity\"\n            android:screenOrientation=\"portrait\"\n            android:theme=\"@style/AppTheme.Tab\" />\n        <activity\n            android:name=\".ui.activity.WebActivity\"\n            android:screenOrientation=\"portrait\" />\n        <activity\n            android:name=\".ui.activity.SettingActivity\"\n            android:screenOrientation=\"portrait\" />\n        <activity\n            android:name=\".ui.activity.DailyActivity\"\n            android:screenOrientation=\"portrait\" />\n        <activity\n            android:name=\".ui.activity.ImageGalleryActivity\"\n            android:screenOrientation=\"portrait\" />\n        <activity android:name=\".ui.activity.CollectActivity\" />\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/App.groovy",
    "content": "package zhou.gank.io\n\nimport android.app.Activity\nimport android.app.Application\nimport android.content.ClipData\nimport android.content.ClipboardManager\nimport android.net.Uri\nimport android.os.Environment\nimport android.os.Handler\nimport android.os.Looper\nimport android.support.v7.app.AppCompatActivity\nimport android.widget.Toast\nimport com.bettervectordrawable.VectorDrawableCompat\nimport com.google.gson.Gson\nimport com.google.gson.GsonBuilder\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.database.DatabaseManager\nimport zhou.gank.io.net.NetworkManager\nimport zhou.gank.io.util.Notifier\n\n@CompileStatic\nclass App extends Application {\n\n    public static final String SITE_URL = \"http://gank.avosapps.com\";\n    public static final String TYPE_URL = SITE_URL + \"/api/data\";\n    public static final String TIME_URL = SITE_URL + \"/api/day\";\n    public static final String RANDOM_URL = SITE_URL + \"/api/random/data\";\n\n    public static\n    final File SAVE_PATH = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), \"gank\")\n\n    static {\n        if (!SAVE_PATH.exists()) {\n            SAVE_PATH.mkdir()\n        }\n    }\n\n    private static App app;\n\n    static App getInstance() {\n        return app;\n    }\n\n    Gson gson;\n    Handler mainHandler\n    int cardLight, cardDark, textLight, textDark\n    ArrayList<Notifier> notifiers\n    public static boolean hasStarted\n\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        app = this;\n\n        DatabaseManager.init(this)\n\n        cardDark = getColor(R.color.cardview_dark_background)\n        cardLight = getColor(R.color.cardview_light_background)\n        textDark = getColor(R.color.material_grey_50)\n        textLight = getColor(R.color.material_grey_1000)\n\n        mainHandler = new Handler(Looper.getMainLooper())\n\n        gson = new GsonBuilder().setDateFormat(\"yyyy-MM-dd'T'HH:mm:ss.SSS\").create();\n        NetworkManager.getInstance().init(this, gson)\n        NetworkManager.getInstance().setDefaultHandle { e ->\n            switch (e) {\n                case SocketTimeoutException:\n                    return Config.Error.TIME_OUT\n                default:\n                    return Config.Error.UNKOWN\n            }\n        }\n        VectorDrawableCompat.enableResourceInterceptionFor(getResources(),\n                R.drawable.ic_favorite_white_48px,\n                R.drawable.ic_info_48px,R.drawable.ic_refresh_48px,\n                R.drawable.ic_dashboard_48px, R.drawable.ic_event_48px,\n                R.drawable.ic_extension_48px, R.drawable.ic_settings_black_48px,\n                R.drawable.ic_menu_white_48px, R.drawable.ic_view_module_48px,\n                R.drawable.ic_cloud_queue_48px, R.drawable.ic_cloud_off_48px,\n                R.drawable.ic_insert_emoticon_48px, R.drawable.ic_bookmark_48px)\n\n        Config.Configurable.HANDLE_BY_ME = true\n\n        notifiers = new ArrayList<>()\n    }\n\n    static void toast(int id) {\n        Toast.makeText(app, id, Toast.LENGTH_SHORT).show();\n    }\n\n    static void toast(String msg) {\n        Toast.makeText(app, msg, Toast.LENGTH_SHORT).show();\n    }\n\n    static String getStr(int res) {\n        return app.getResources().getString(res);\n    }\n\n    static int getColor(int res) {\n        return app.getResources().getColor(res)\n    }\n\n    static File cacheFile() {\n        return app.getCacheDir();\n    }\n\n    static void copy(String text) {\n        ClipboardManager myClipboard;\n        myClipboard = (ClipboardManager) app.getSystemService(CLIPBOARD_SERVICE);\n        ClipData myClip;\n        myClip = ClipData.newPlainText(\"text\", text);\n        myClipboard.setPrimaryClip(myClip);\n    }\n\n    static void copyUri(Uri uri) {\n        ClipboardManager myClipboard;\n        myClipboard = (ClipboardManager) app.getSystemService(CLIPBOARD_SERVICE);\n        ClipData myClip;\n        myClip = ClipData.newUri(app.getContentResolver(), \"URI\", uri);\n        myClipboard.setPrimaryClip(myClip);\n    }\n\n    static void setTheme(Activity activity) {\n        String theme = Config.getString(getStr(R.string.key_theme), \"light\")\n        switch (theme) {\n            case \"light\":\n                activity.setTheme(R.style.AppTheme)\n                break\n            case \"dark\":\n                activity.setTheme(R.style.AppThemeDark)\n                break\n        }\n    }\n\n    static boolean themeIsLight() {\n        String theme = Config.getString(getStr(R.string.key_theme), \"light\")\n        return theme == \"light\"\n    }\n\n    static boolean addNotifier(Notifier notifier) {\n        app.notifiers.add(notifier)\n    }\n\n    static boolean removeNotifier(Notifier notifier) {\n        app.notifiers.remove(notifier)\n    }\n\n    static void themeChanged() {\n        app.notifiers.each {\n            def notifier = it as Notifier\n            notifier.notice(Config.Action.RESTART)\n        }\n    }\n\n    static void setPrimaryColor(AppCompatActivity activity) {\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/MainActivity.groovy",
    "content": "package zhou.gank.io\n\nimport android.animation.Animator\nimport android.animation.AnimatorListenerAdapter\nimport android.animation.ObjectAnimator\nimport android.animation.PropertyValuesHolder\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.design.widget.FloatingActionButton\nimport android.support.v7.app.AppCompatActivity\nimport android.view.View\nimport android.view.animation.AccelerateDecelerateInterpolator\nimport android.widget.TextView\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.database.DatabaseManager\nimport zhou.gank.io.model.Bookmark\nimport zhou.gank.io.ui.activity.HomeActivity\n\n@CompileStatic\nclass MainActivity extends AppCompatActivity {\n\n    FloatingActionButton fab\n    TextView textView\n    View background\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        App.setTheme(this)\n        super.onCreate(savedInstanceState)\n        if (App.hasStarted) {\n            Open()\n            return\n        } else {\n            App.hasStarted = true\n        }\n        setContentView(R.layout.activity_main);\n\n        fab = findViewById(R.id.fab) as FloatingActionButton\n        textView = findViewById(R.id.textView) as TextView\n        background = findViewById(R.id.background)\n        fab.postDelayed(this.&start, 200)\n    }\n\n\n    def void start() {\n        View parent = fab.getParent() as View\n        float scale = Math.sqrt(parent.getHeight() * parent.getHeight() + parent.getWidth() * parent.getWidth()) / fab.getHeight() as float\n        PropertyValuesHolder holderX = PropertyValuesHolder.ofFloat(\"scaleX\", scale)\n        PropertyValuesHolder holderY = PropertyValuesHolder.ofFloat(\"scaleY\", scale)\n        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(fab as Object, holderX, holderY).setDuration(500)\n        animator.setInterpolator(new AccelerateDecelerateInterpolator())\n        animator.addListener(new AnimatorListenerAdapter() {\n            @Override\n            void onAnimationEnd(Animator animation) {\n                super.onAnimationEnd(animation)\n                background.setBackgroundColor(MainActivity.this.getResources().getColor(R.color.material_purple_500) as int)\n                fab.setVisibility(View.GONE)\n                textView.setVisibility(View.VISIBLE)\n            }\n        })\n        parent.getAlpha()\n\n\n        PropertyValuesHolder holderA = PropertyValuesHolder.ofFloat(\"alpha\", 0, 1)\n        PropertyValuesHolder holderYm = PropertyValuesHolder.ofFloat(\"translationY\", 0, 300)\n        ObjectAnimator a = ObjectAnimator.ofPropertyValuesHolder(textView as Object, holderA, holderYm).setDuration(700)\n        a.setInterpolator(new AccelerateDecelerateInterpolator())\n        a.setStartDelay(500)\n\n        a.addListener(new AnimatorListenerAdapter() {\n            @Override\n            void onAnimationEnd(Animator animation) {\n                super.onAnimationEnd(animation)\n                Open()\n            }\n        })\n\n        animator.start()\n        a.start()\n    }\n\n    public void Open(View view = null) {\n        startActivity(new Intent(this, HomeActivity.class));\n        finish()\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/comment/Config.groovy",
    "content": "package zhou.gank.io.comment\n\nimport android.content.SharedPreferences\nimport android.preference.PreferenceManager\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App;\n\n@CompileStatic\nclass Config {\n\n    public static class Configurable {\n\n        public static int DEFAULT_SIZE = 10\n\n        public static boolean HANDLE_BY_ME = true\n\n        public static int MAX_iteration = 7\n    }\n\n    public static class Static {\n\n        public static final String TYPE = \"type\"\n\n        public static final String URL = \"url\"\n\n        public static final String TITLE = \"title\"\n\n        public static final String CONTENT = \"content\"\n\n        public static final String IS_RANDOM = \"is_random\"\n\n        public static final String IS_IMAGE = \"is_image\"\n\n        public static final String IS_MAIN = \"is_main\"\n\n        public static final String IS_BOOKMARK = \"is_bookmark\"\n\n        public static final String YEAR = \"year\"\n\n        public static final String MONTH = \"month\"\n\n        public static final String DAY = \"day\"\n\n        public static final String URLS = \"urls\"\n\n        public static final String POSITION = \"position\"\n    }\n\n    public static class Type {\n\n        public static final String ANDROID = \"Android\"\n\n        public static final String IOS = \"iOS\"\n\n        public static final String RECOMMEND = \"瞎推荐\"\n\n        public static final String RESOURCES = \"拓展资源\"\n\n        public static final String WELFARE = \"福利\"\n\n        public static final String VIDEO = \"休息视频\"\n\n    }\n\n    public static class Error {\n\n        public static final String UNKOWN = \"未知错误\"\n\n        public static final String TIME_OUT = \"网络连接超时\"\n\n        public static final String FORMDATA_ = \"数据格式出错\"\n    }\n\n    public static class Action {\n\n        //打开drawerLayout\n        public static final int OPEN_DRAWER_LAYOUT = 0x111111\n\n        public static final int CHANGE_DATE = 0x222222\n\n        public static final int FINISH = 0x333333\n\n        public static final int RESTART = 0x444444\n    }\n\n    public static String getString(String key, String d) {\n        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(App.getInstance())\n        preferences.getString(key, d)\n    }\n\n    public static boolean getBoolean(String key, boolean d) {\n        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(App.getInstance())\n        preferences.getBoolean(key, d)\n    }\n\n    public static int getInt(String key, int d) {\n        SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(App.getInstance())\n        preferences.getInt(key, d)\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/data/CollectProvider.groovy",
    "content": "package zhou.gank.io.data\n\nimport android.support.annotation.Nullable;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.database.DatabaseManager\nimport zhou.gank.io.model.Gank\n\n@CompileStatic\npublic class CollectProvider implements DataProvider<List<Gank>> {\n\n    private List<Gank> ganks\n\n    @Override\n    void persistence() {\n\n    }\n\n    @Override\n    List<Gank> get() {\n        return ganks\n    }\n\n    @Override\n    void set(@Nullable List<Gank> ganks, boolean more) {\n        this.ganks = ganks\n    }\n\n    @Override\n    void loadByCache(Closure closure) {\n        new Thread({\n            List<Gank> gs = DatabaseManager.getInstance().selectToGank()\n            App.getInstance().getMainHandler().post({\n                closure?.call(gs)\n            })\n        }).start()\n    }\n\n    @Override\n    void load(Closure closure, boolean more) {\n\n    }\n\n    @Override\n    boolean hasLoad() {\n        return ganks != null\n    }\n\n    @Override\n    boolean needCache() {\n        return false\n    }\n\n    @Override\n    boolean clearCache() {\n        return false\n    }\n\n    @Override\n    String key() {\n        return \"bookmark\"\n    }\n\n    @Override\n    void setNoticeable(boolean noticeable) {\n\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/data/DataManager.groovy",
    "content": "package zhou.gank.io.data\n\nimport android.util.Log\nimport groovy.transform.CompileStatic\n\n@CompileStatic\nclass DataManager {\n\n    private static DataManager dataManager\n\n    public static DataManager getInstance() {\n        if (dataManager == null) {\n            dataManager = new DataManager()\n        }\n        dataManager\n    }\n\n    private HashMap<String, DataProvider> providers\n\n    private DataManager() {\n        providers = new HashMap<>()\n    }\n\n    /**\n     * 添加数据提供器（不进行重复检查）\n     *\n     * @param provider 提供器\n     */\n    public void add(DataProvider provider) {\n        if (provider != null)\n            providers.put(provider.key(), provider)\n    }\n\n    /**\n     * 添加数据提供器\n     *\n     * @param provider 数据提供器\n     * @param check 是否进行重复检查\n     */\n    public void add(DataProvider provider, boolean check) {\n        if (provider == null) {\n            return\n        }\n        if (check) {\n            if (!providers.containsKey(provider.key())) {\n                providers.put(provider.key(), provider)\n            }\n        } else {\n            providers.put(provider.key(), provider)\n        }\n    }\n\n    /**\n     * 移除数据提供器\n     *\n     * @param key key\n     */\n    public void remove(String key) {\n        providers.remove(key)\n    }\n\n    /**\n     * 移出数据提供器\n     *\n     * @param provider 数据提供器\n     */\n    public void remove(DataProvider provider) {\n        if (provider != null) {\n            providers.remove(provider.key())\n        }\n    }\n\n    /**\n     * 获取数据 按照（内存->本地缓存->网络）的顺序获取\n     *\n     * @param key key\n     * @param loadCallback 回调\n     * @param < T >             type\n     */\n    public <T> void get(String key, Closure loadCallback) {\n        try {\n            def provider = providers.get(key) as DataProvider<T>\n            get(provider, loadCallback)\n        } catch (Exception e) {\n            Log.d(\"get\", \"DataManager\", e)\n            loadCallback?.call()\n        }\n    }\n\n    /**\n     * 获取数据\n     *\n     * @param provider 数据提供器\n     * @param loadCallback 回调\n     * @param < T >             type\n     */\n    public <T> void get(DataProvider<T> provider, Closure loadCallback) {\n        if (provider.hasLoad()) {\n            loadCallback?.call(provider.get())\n        } else {\n            provider.loadByCache({t ->\n                if (t != null) {\n                    provider.set(t as T, false)\n                    if (provider.needCache()) {\n                        provider.persistence()\n                    }\n                    loadCallback?.call(provider.get())\n                } else {\n                    provider.load({tn ->\n                        provider.set(tn as T, false);\n                        if (provider.needCache()) {\n                            provider.persistence()\n                        }\n                        loadCallback?.call(provider.get())\n                    }, false)\n                }\n            });\n        }\n    }\n\n    /**\n     * 加载数据\n     *\n     * @param key key\n     * @param loadCallback 回调\n     * @param < T >             type\n     */\n    @SuppressWarnings(\"unchecked\")\n    public <T> void load(String key, Closure loadCallback, boolean more) {\n        try {\n            DataProvider<T> provider = (DataProvider<T>) providers.get(key)\n            load(provider, loadCallback, more)\n        } catch (Exception e) {\n            Log.d(\"load\", \"DataManager\", e)\n            loadCallback?.call(null)\n        }\n    }\n\n    /**\n     * 加载数据\n     *\n     * @param provider 数据提供器\n     * @param loadCallback 回调\n     * @param < T >             type\n     */\n    public <T> void load(DataProvider<T> provider, Closure loadCallback, boolean more) {\n        provider.load({t ->\n            provider.set(t as T, more)\n            if (provider.needCache()) {\n                provider.persistence()\n            }\n            loadCallback?.call(provider.get())\n        }, more);\n    }\n\n    public <T> void update(DataProvider<T> provider, Closure loadCallback) {\n        load(provider, loadCallback, false)\n    }\n\n    void update(String key, Closure loadCallback) {\n        load(key, loadCallback, false)\n    }\n\n    public <T> void more(DataProvider<T> provider, Closure loadCallback) {\n        load(provider, loadCallback, true)\n    }\n\n    void more(String key, Closure loadCallback) {\n        load(key, loadCallback, true)\n    }\n\n    /**\n     * 持久化所有数据\n     */\n    void persistence() {\n        for (Map.Entry<String, DataProvider> entry : providers.entrySet()) {\n            DataProvider dataProvider = entry.getValue();\n            if (dataProvider.needCache()) {\n                dataProvider.persistence()\n            }\n        }\n    }\n\n    void clearAllCache() {\n        for (Map.Entry<String, DataProvider> entry : providers.entrySet()) {\n            DataProvider provider = entry.getValue()\n            provider.clearCache()\n        }\n    }\n\n    void clearCache(String key) {\n        DataProvider provider = providers.get(key)\n        if (provider != null) {\n            provider.clearCache()\n        }\n    }\n\n    boolean hasLoad(String key) {\n        DataProvider provider = providers.get(key)\n        provider != null && provider.hasLoad()\n    }\n\n    boolean exist(String key) {\n        providers.containsKey(key)\n    }\n\n    public void reset() {\n        providers.clear()\n    }\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/data/DataProvider.groovy",
    "content": "package zhou.gank.io.data\n\nimport android.support.annotation.NonNull\nimport android.support.annotation.Nullable\nimport groovy.transform.CompileStatic;\n\n@CompileStatic\ninterface DataProvider<T> {\n\n    /**\n     * 数据持久化（应异步进行）\n     */\n    void persistence();\n\n    /**\n     * 获取数据\n     *\n     * @return 数据\n     */\n    @Nullable\n    T get();\n\n    /**\n     * 设置数据\n     *\n     * @param t 数据\n     */\n    void set(@Nullable T t, boolean more);\n\n    /**\n     * 从缓存中加载数据（应异步实现）\n     *\n     * @param loadCallback 回调\n     */\n    void loadByCache(Closure closure);\n\n    /**\n     * 加载数据（必须异步实现）\n     *\n     * @param loadCallback 回调\n     */\n    void load(Closure closure, boolean more);\n\n    /**\n     * 是否已经加载\n     *\n     * @return boolean\n     */\n    boolean hasLoad();\n\n    /**\n     * 是否需要缓存\n     *\n     * @return boolean\n     */\n    boolean needCache();\n\n    /**\n     * 清空缓存\n     */\n    boolean clearCache();\n\n    /**\n     * 获取该加载器的唯一标识\n     *\n     * @return key\n     */\n    @NonNull\n    String key();\n\n    /**\n     * 设置provide能否发出提醒\n     * @param noticeable\n     */\n    void setNoticeable(boolean noticeable)\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/data/RandomProvider.groovy",
    "content": "package zhou.gank.io.data\n\nimport android.support.annotation.NonNull\nimport android.support.annotation.Nullable\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.model.Result\nimport zhou.gank.io.net.NetworkManager\nimport zhou.gank.io.util.FileKit\nimport zhou.gank.io.util.HashKit\nimport zhou.gank.io.util.LogKit\nimport zhou.gank.io.util.NetworkKit\n\n@CompileStatic\nclass RandomProvider implements DataProvider<List<Gank>> {\n\n    private List<Gank> ganks\n    private int size\n    private String key, type\n    private File file\n    private boolean noticeable\n\n    RandomProvider(String type, int size) {\n        this.type = type;\n        this.size = size;\n        key = HashKit.md5(\"$type-$size-random.cache\");\n        file = new File(App.cacheFile(), key);\n    }\n\n    @Override\n    void persistence() {\n        if (hasLoad()) {\n            new Thread({\n                try {\n                    FileKit.writeObject(file, ganks)\n                } catch (Exception e) {\n                    LogKit.d(\"persistence\", \"random\", e)\n                }\n            }).start();\n        }\n    }\n\n    @Nullable\n    @Override\n    List<Gank> get() {\n        return ganks;\n    }\n\n    @Override\n    void set(@Nullable List<Gank> ganHuos, boolean more) {\n        this.ganks = ganHuos;\n    }\n\n    @Override\n    void loadByCache(Closure closure) {\n        def gks = null\n        if (file.exists()) {\n            try {\n                gks = FileKit.readObject(file)\n            } catch (Exception e) {\n                LogKit.d(\"loadByCache\", \"random\", e)\n            }\n        }\n        closure?.call(gks)\n    }\n\n    @Override\n    void load(Closure closure, boolean more) {\n        if (NetworkManager.getInstance().isNetworkConnected()) {\n            NetworkKit.random(type, size, { result ->\n                def gks = null\n                if (result instanceof Result) {\n                    def r = result as Result\n                    if (r?.isSuccess()) {\n                        gks = r.results\n                    } else {\n                        if (noticeable)\n                            App.toast(R.string.failure_get)\n                    }\n                } else {\n                    if (noticeable)\n                        App.toast(result as String)\n                }\n                closure?.call(gks)\n            })\n        } else {\n            closure?.call()\n            if (noticeable)\n                App.toast(R.string.error_network)\n        }\n    }\n\n    @Override\n    boolean hasLoad() {\n        return ganks != null;\n    }\n\n    @Override\n    boolean needCache() {\n        return false;\n    }\n\n    @Override\n    boolean clearCache() {\n        return file.exists() && file.delete();\n    }\n\n    @NonNull\n    @Override\n    String key() {\n        return key;\n    }\n\n    @Override\n    void setNoticeable(boolean noticeable) {\n        this.noticeable = noticeable;\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/data/TimeProvider.groovy",
    "content": "package zhou.gank.io.data\n\nimport android.support.annotation.NonNull\nimport android.support.annotation.Nullable\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.model.GankDaily\nimport zhou.gank.io.model.ResultDaily\nimport zhou.gank.io.net.NetworkManager\nimport zhou.gank.io.util.FileKit\nimport zhou.gank.io.util.HashKit\nimport zhou.gank.io.util.LogKit\nimport zhou.gank.io.util.NetworkKit\n\n@CompileStatic\nclass TimeProvider implements DataProvider<GankDaily> {\n\n    private GankDaily daily\n    int year, month, day\n    private String key\n    private File file\n    private boolean noticeable\n    private boolean needCache\n\n    TimeProvider(int year, int month, int day) {\n        this.year = year\n        this.month = month\n        this.day = day\n        key = HashKit.md5(\"year:$year,month:$month,day:$day-cache\")\n        file = new File(App.cacheFile(), key)\n\n        Calendar now = Calendar.getInstance()\n        int y = now.get(Calendar.YEAR)\n        if (year < y) {\n            needCache = true\n        } else if (year == y) {\n            int m = now.get(Calendar.MONTH) + 1\n            if (month < m) {\n                needCache = true\n            } else if (month == m) {\n                int d = now.get(Calendar.DAY_OF_MONTH)\n                needCache = day <= d\n            } else {\n                needCache = false\n            }\n        } else {\n            needCache = false\n        }\n    }\n\n    @Override\n    void persistence() {\n        if (hasLoad()) {\n            new Thread({\n                try {\n                    FileKit.writeObject(file, daily)\n                } catch (Exception e) {\n                    LogKit.d(\"persistence\", \"time\", e)\n                }\n            }).start()\n        }\n    }\n\n    @Nullable\n    @Override\n    GankDaily get() {\n        return daily\n    }\n\n    @Override\n    void set(@Nullable GankDaily ganHuos, boolean more) {\n        this.daily = ganHuos\n    }\n\n    @Override\n    void loadByCache(Closure closure) {\n        def d = null\n        if (file.exists()) {\n            new Thread({\n                try {\n                    d = FileKit.readObject(file)\n                } catch (Exception e) {\n                    LogKit.d(\"loadByCache\", \"time\", e)\n                }\n                App.getInstance().getMainHandler().post({\n                    closure?.call(d)\n                })\n            }).start()\n        } else {\n            closure?.call(d)\n        }\n    }\n\n    @Override\n    void load(Closure closure, boolean more) {\n        if (NetworkManager.getInstance().isNetworkConnected()) {\n            NetworkKit.time(year, month, day, { result ->\n                def d = null\n                if (result instanceof ResultDaily) {\n                    def r = result as ResultDaily\n                    if (r.isSuccess()) {\n                        d = r.results\n                    } else {\n                        if (noticeable)\n                            App.toast(R.string.failure_get)\n                    }\n                }\n                closure?.call(d)\n            })\n        } else {\n            closure?.call()\n            if (noticeable)\n                App.toast(R.string.error_network)\n        }\n    }\n\n    @Override\n    public boolean hasLoad() {\n        return daily != null\n    }\n\n    @Override\n    public boolean needCache() {\n        return needCache\n    }\n\n    @Override\n    public boolean clearCache() {\n        return file.exists() && file.delete()\n    }\n\n    @NonNull\n    @Override\n    public String key() {\n        return key\n    }\n\n    @Override\n    void setNoticeable(boolean noticeable) {\n        this.noticeable = noticeable\n    }\n\n    public TimeProvider getNextDay() {\n        Calendar calendar = Calendar.getInstance()\n        calendar.set(Calendar.YEAR, year)\n        calendar.set(Calendar.MONTH, month - 1)\n        calendar.set(Calendar.DAY_OF_MONTH, day)\n        calendar.add(Calendar.DAY_OF_MONTH, 1)\n        return new TimeProvider(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH))\n    }\n\n    public TimeProvider getPrevDay() {\n        Calendar calendar = Calendar.getInstance()\n        calendar.set(Calendar.YEAR, year)\n        calendar.set(Calendar.MONTH, month - 1)\n        calendar.set(Calendar.DAY_OF_MONTH, day)\n        calendar.add(Calendar.DAY_OF_MONTH, -1)\n        return new TimeProvider(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH))\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/data/TypeProvider.groovy",
    "content": "package zhou.gank.io.data\n\nimport android.support.annotation.NonNull\nimport android.support.annotation.Nullable\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.model.Result\nimport zhou.gank.io.net.NetworkManager\nimport zhou.gank.io.util.*\n\n@CompileStatic\nclass TypeProvider implements DataProvider<List<Gank>> {\n\n    private List<Gank> ganks\n    private File file\n    private String type, key\n    private Pageable pageable\n    private boolean noticeable\n\n    TypeProvider(String type, int size) {\n        this.type = type;\n        key = HashKit.md5(\"${type}${size}-cache\")\n        file = new File(App.cacheFile(), key)\n        pageable = new Pageable(1, size)\n    }\n\n    @Override\n    void persistence() {\n        if (hasLoad()) {\n            new Thread({\n                try {\n                    FileKit.writeObject(file, new TypeGankEntity(pageable, ganks))\n                } catch (Exception e) {\n                    LogKit.d(\"persistence\", \"type\", e)\n                }\n            }).start()\n        }\n    }\n\n    @Nullable\n    @Override\n    List<Gank> get() {\n        return ganks\n    }\n\n    @Override\n    void set(@Nullable List<Gank> ganHuos, boolean more) {\n        if (more && ganHuos != null && hasLoad()) {\n            this.ganks.addAll(ganHuos)\n        } else {\n            this.ganks = ganHuos\n        }\n    }\n\n    @Override\n    void loadByCache(Closure closure) {\n        def gks = null\n        if (file.exists()) {\n            new Thread({\n                try {\n                    def tge = FileKit.readObject(file) as TypeGankEntity\n                    gks = tge.g\n                    pageable = tge.p\n                } catch (Exception e) {\n                    LogKit.d(\"loadByCache\", \"type\", e)\n                }\n            }).start()\n            App.getInstance().getMainHandler().post({\n                closure?.call(gks)\n            })\n        }else {\n            closure?.call(gks)\n        }\n    }\n\n    @Override\n    void load(Closure closure, boolean more) {\n        if (NetworkManager.getInstance().isNetworkConnected()) {\n            if (more) {\n                pageable.next()\n            }\n            NetworkKit.type(type, pageable.pageSize, pageable.pageNo, { result ->\n                def gks = null\n                if (result instanceof Result) {\n                    def r = result as Result\n                    if (r?.isSuccess()) {\n                        gks = r.results\n                    } else {\n                        if (more) {\n                            pageable.prev()\n                        }\n                        if (noticeable)\n                            App.toast(R.string.failure_get)\n                    }\n                } else {\n                    if (noticeable)\n                        App.toast(result as String)\n                }\n                closure?.call(gks)\n            })\n        } else {\n            if (noticeable)\n                App.toast(R.string.error_network)\n            closure?.call()\n        }\n    }\n\n    @Override\n    boolean hasLoad() {\n        return ganks != null\n    }\n\n    @Override\n    boolean needCache() {\n        return true\n    }\n\n    @Override\n    boolean clearCache() {\n        return file.exists() && file.delete()\n    }\n\n    @NonNull\n    @Override\n    String key() {\n        return key\n    }\n\n    @Override\n    void setNoticeable(boolean noticeable) {\n        this.noticeable = noticeable\n    }\n\n    public static class TypeGankEntity implements Serializable {\n\n        public Pageable p\n        public List<Gank> g\n\n        TypeGankEntity(Pageable p, List<Gank> g) {\n            this.p = p\n            this.g = g\n        }\n\n        TypeGankEntity() {\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/database/DatabaseManager.groovy",
    "content": "package zhou.gank.io.database\n\nimport android.content.ContentValues\nimport android.content.Context\nimport android.database.Cursor\nimport android.database.sqlite.SQLiteDatabase\nimport android.database.sqlite.SQLiteOpenHelper;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.model.Bookmark\nimport zhou.gank.io.model.Gank\n\n@CompileStatic\npublic class DatabaseManager {\n\n    public static final String TABLE_NAME = \"bookmark\"\n    public static final String URL = \"url\"\n    public static final String TITLE = \"title\"\n    public static final String TIME = \"time\"\n\n    private static DatabaseManager databaseManager\n\n    public static DatabaseManager getInstance() {\n        return databaseManager\n    }\n\n    public static void init(Context context) {\n        databaseManager = new DatabaseManager(context)\n    }\n\n\n    private DatabaseHelper databasehelper\n    private SQLiteDatabase database\n\n    private DatabaseManager(Context context) {\n        databasehelper = new DatabaseHelper(context)\n    }\n\n    public void insert(Bookmark bookmark) {\n        start()\n        ContentValues cv = new ContentValues(3)\n        cv.put(URL, bookmark.url)\n        cv.put(TITLE, bookmark.title)\n        cv.put(TIME, bookmark.time.getTime())\n        database.insert(TABLE_NAME, null, cv)\n        end()\n    }\n\n    public void delete(String url) {\n        start()\n        database.delete(TABLE_NAME, \"url=?\", url)\n        end()\n    }\n\n    public List<Bookmark> select() {\n        start()\n        String sql = \"select * from $TABLE_NAME order by $TIME desc;\"\n        Cursor cursor = database.rawQuery(sql)\n        int count = cursor?.getCount()\n        List<Bookmark> bookmarks = new ArrayList<>(count)\n        if (cursor) {\n            cursor.moveToFirst()\n            for (int i = 0; i < count; i++) {\n                String url = cursor.getString(0)\n                String title = cursor.getString(1)\n                long time = cursor.getLong(2)\n                bookmarks.add(new Bookmark(url, title, new Date(time)))\n                cursor.moveToNext()\n            }\n        }\n        end()\n        return bookmarks\n    }\n\n    public List<Gank> selectToGank() {\n        start()\n        String sql = \"select * from $TABLE_NAME order by $TIME desc;\"\n        Cursor cursor = database.rawQuery(sql)\n        int count = cursor?.getCount()\n        List<Gank> gs = new ArrayList<>(count)\n        if (cursor) {\n            cursor.moveToFirst()\n            for (int i = 0; i < count; i++) {\n                String url = cursor.getString(0)\n                String title = cursor.getString(1)\n                long time = cursor.getLong(2)\n                gs.add(new Gank(title, url, new Date(time)))\n                cursor.moveToNext()\n            }\n        }\n        end()\n        return gs\n    }\n\n    public boolean isExist(String url) {\n        start()\n        String sql = \"select * from $TABLE_NAME where $URL=?\"\n        Cursor cursor = database.rawQuery(sql, url)\n        boolean flag = false\n        if (cursor && cursor.getCount() > 0) {\n            flag = true\n        }\n        end()\n        return flag\n    }\n\n\n    private void start() {\n        database = databasehelper.getWritableDatabase()\n    }\n\n    private end() {\n        database?.close()\n    }\n\n    private class DatabaseHelper extends SQLiteOpenHelper {\n\n        private static final int VERSION = 1\n        private static final String DATABASE_NAME = \"ganke\"\n\n        DatabaseHelper(Context context) {\n            super(context, DATABASE_NAME, null, VERSION)\n        }\n\n        @Override\n        void onCreate(SQLiteDatabase sqLiteDatabase) {\n            String sql = \"create table $TABLE_NAME (${DatabaseManager.URL} text primary key,${TITLE} text not null,$TIME long not null);\"\n            println(sql)\n            sqLiteDatabase.execSQL(sql)\n        }\n\n        @Override\n        void onUpgrade(SQLiteDatabase sqLiteDatabase, int i, int i1) {\n\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/model/BaseResult.groovy",
    "content": "package zhou.gank.io.model\n\nimport groovy.transform.CompileStatic;\n\n@CompileStatic\nabstract class BaseResult implements Serializable {\n\n    boolean error\n\n    abstract boolean isSuccess()\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/model/Bookmark.groovy",
    "content": "package zhou.gank.io.model;\n\nimport groovy.transform.CompileStatic\n\n@CompileStatic\npublic class Bookmark implements Serializable {\n\n    public String url\n    public String title\n    public Date time\n\n    Bookmark(String url, String title, Date time) {\n        this.url = url\n        this.title = title\n        this.time = time\n    }\n\n    Bookmark(String url, String title) {\n        this.url = url\n        this.title = title\n        this.time = new Date()\n    }\n\n    Bookmark() {\n    }\n\n\n    @Override\n    public String toString() {\n        return \"Bookmark{\" +\n                \"url='\" + url + '\\'' +\n                \", title='\" + title + '\\'' +\n                \", time=\" + time +\n                '}';\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/model/Gank.groovy",
    "content": "package zhou.gank.io.model\n\nimport groovy.transform.CompileStatic\nimport groovy.transform.EqualsAndHashCode\nimport groovy.transform.ToString;\n\n@ToString\n@EqualsAndHashCode\n@CompileStatic\nclass Gank implements Serializable{\n\n    public String who\n    public String desc\n    public String type\n    public String url\n    public String objectId\n    public boolean used\n    public Date publishedAt\n    public Date createdAt\n    public Date updatedAt\n\n    Gank(String who, String desc, String type, String url, String objectId, boolean used, Date publishedAt, Date createdAt, Date updatedAt) {\n        this.who = who\n        this.desc = desc\n        this.type = type\n        this.url = url\n        this.objectId = objectId\n        this.used = used\n        this.publishedAt = publishedAt\n        this.createdAt = createdAt\n        this.updatedAt = updatedAt\n    }\n\n    Gank(String desc, String url, Date createdAt) {\n        this.desc = desc\n        this.url = url\n        this.createdAt = createdAt\n    }\n\n    Gank() {\n    }\n\n\n    @Override\n    public String toString() {\n        return \"Gank{\" +\n                \"who='\" + who + '\\'' +\n                \", desc='\" + desc + '\\'' +\n                \", type='\" + type + '\\'' +\n                \", url='\" + url + '\\'' +\n                \", objectId='\" + objectId + '\\'' +\n                \", used=\" + used +\n                \", publishedAt=\" + publishedAt +\n                \", createdAt=\" + createdAt +\n                \", updatedAt=\" + updatedAt +\n                '}';\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/model/GankDaily.groovy",
    "content": "package zhou.gank.io.model\n\nimport groovy.transform.CompileStatic\nimport groovy.transform.ToString;\n\n@CompileStatic\n@ToString(includeNames = true)\nclass GankDaily implements Serializable {\n\n    public List<String> types;\n    public List<List<Gank>> ganks;\n\n    int size() {\n        return types.size();\n    }\n\n    boolean isEmpty() {\n        return types == null ? true : types.isEmpty() || ganks == null ? true : ganks.isEmpty()\n    }\n\n    String getType(int index) {\n        return types.get(index);\n    }\n\n    List<Gank> getGanhuo(int index) {\n        return ganks.get(index);\n    }\n\n    GankDaily(List<String> types, List<List<Gank>> ganks) {\n        this.types = types\n        this.ganks = ganks\n    }\n\n    GankDaily() {\n    }\n\n\n    @Override\n    public String toString() {\n        return \"GankDaily{\" +\n                \"types=\" + types +\n                \", ganks=\" + ganks +\n                '}';\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/model/Result.groovy",
    "content": "package zhou.gank.io.model\n\nimport groovy.transform.CompileStatic;\n\n@CompileStatic\nclass Result extends BaseResult {\n\n    public List<Gank> results\n\n    Result(boolean error, List<Gank> results) {\n        this.error = error\n        this.results = results\n    }\n\n    Result() {\n    }\n\n\n    @Override\n    public String toString() {\n        return \"Result{\" +\n                \"error=\" + error +\n                \", results=\" + results +\n                '}';\n    }\n\n    @Override\n    boolean isSuccess() {\n        !error\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/model/ResultDaily.groovy",
    "content": "package zhou.gank.io.model\n\nimport groovy.transform.CompileStatic\nimport groovy.transform.ToString;\n\n@CompileStatic\n@ToString\nclass ResultDaily extends BaseResult {\n\n    public GankDaily results;\n\n    ResultDaily(boolean error, GankDaily results) {\n        this.error = error\n        this.results = results\n    }\n\n    ResultDaily() {\n    }\n\n    @Override\n    public String toString() {\n        return \"ResultDaily{\" +\n                \"error=\" + error +\n                \", results=\" + results +\n                '}';\n    }\n\n    @Override\n    boolean isSuccess() {\n        !error\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/net/NetworkManager.groovy",
    "content": "package zhou.gank.io.net\n\nimport android.content.Context\nimport android.net.ConnectivityManager\nimport android.net.NetworkInfo\nimport android.os.Handler\nimport android.os.Looper\nimport android.util.Log\nimport com.google.gson.Gson\nimport com.squareup.okhttp.Callback\nimport com.squareup.okhttp.OkHttpClient\nimport com.squareup.okhttp.Request\nimport com.squareup.okhttp.Response\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.model.Result\nimport zhou.gank.io.util.LogKit\n\nimport java.lang.reflect.Type\nimport java.util.concurrent.TimeUnit\n\n//@CompileStatic\nclass NetworkManager {\n\n    OkHttpClient client\n    Gson gson\n    Handler handler\n    Closure defaultHandle\n    Context context\n\n    private static NetworkManager networkManager;\n\n    static NetworkManager getInstance() {\n        return networkManager\n    }\n\n    static void init(Context context, Gson gson) {\n        networkManager = new NetworkManager(context, gson)\n    }\n\n    private NetworkManager(Context context, Gson gson) {\n        client = new OkHttpClient()\n        client.setConnectTimeout(5, TimeUnit.SECONDS)\n        client.setReadTimeout(5, TimeUnit.SECONDS)\n        client.setWriteTimeout(5, TimeUnit.SECONDS)\n        this.gson = gson;\n        this.context = context\n        handler = new Handler(Looper.getMainLooper())\n    }\n\n    void requestString(Request r, Closure closure) {\n        client.newCall(r).enqueue(new Callback() {\n            @Override\n            void onFailure(Request request, IOException e) {\n                handler.post({\n                    closure(e)\n                })\n            }\n\n            @Override\n            void onResponse(Response response) throws IOException {\n                String body = response.body().string();\n                LogKit.d(\"requestString\", body)\n                handler.post({\n                    closure(body)\n                })\n            }\n        })\n    }\n\n    public <T> void request(Request r, Closure closure, Class<T> aClass) {\n        client.newCall(r).enqueue(new Callback() {\n            @Override\n            void onFailure(Request request, IOException e) {\n                handler.post({\n                    closure(defaultHandle?.call(e))\n                })\n            }\n\n            @Override\n            void onResponse(Response response) throws IOException {\n                String body = response.body().string()\n                Log.d(\"success\", body)\n                def result = gson.fromJson(body, aClass);\n                handler.post({\n                    closure(result)\n                })\n            }\n        })\n        Log.d(\"request\", r.urlString())\n    }\n\n    public <T> void request(Request r, Closure closure, Type type) {\n        client.newCall(r).enqueue(new Callback() {\n            @Override\n            void onFailure(Request request, IOException e) {\n                handler.post({\n                    closure(defaultHandle?.call(e))\n                })\n            }\n\n            @Override\n            void onResponse(Response response) throws IOException {\n                String body = response.body().string()\n                Log.d(\"success\", body)\n                def result = gson.fromJson(body, type)\n                handler.post({\n                    closure(result)\n                })\n            }\n        })\n    }\n\n    boolean isNetworkConnected() {\n        ConnectivityManager connectivityManager = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager\n        NetworkInfo networkInfo = connectivityManager.getActiveNetworkInfo()\n        networkInfo != null && networkInfo.isAvailable()\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/CollectActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.os.Bundle\nimport android.support.annotation.Nullable;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.ui.fragment.GankFragment\n\n@CompileStatic\npublic class CollectActivity extends ToolbarActivity {\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        if (App.themeIsLight()) {\n            setTheme(R.style.AppTheme_Tab)\n        } else {\n            setTheme(R.style.AppTheme_TabDark)\n        }\n        super.onCreate(savedInstanceState)\n        quickFinish()\n        setTitle(R.string.nav_collect)\n\n        add(GankFragment.newInstance(null, true, false, true))\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/DailyActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.design.widget.CoordinatorLayout\nimport android.support.v4.app.Fragment\nimport android.support.v7.app.AppCompatActivity\nimport com.fourmob.datetimepicker.date.DatePickerDialog\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.fragment.DailyFragment\nimport zhou.gank.io.util.Notifier\nimport zhou.gank.io.util.TimeKit\n\n@CompileStatic\npublic class DailyActivity extends AppCompatActivity implements Notifier {\n\n    CoordinatorLayout coordinatorLayout;\n    Fragment currFragment\n    int year, month, day\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        App.setTheme(this)\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_compat)\n\n        def i = getIntent()\n        def times = TimeKit.getTime()\n        year = i.getIntExtra(Config.Static.YEAR, times[0])\n        month = i.getIntExtra(Config.Static.MONTH, times[1])\n        day = i.getIntExtra(Config.Static.DAY, times[2])\n\n        add(DailyFragment.newInstance(year, month, day))\n    }\n\n    def add(Fragment f) {\n        getSupportFragmentManager().beginTransaction().add(R.id.container, f).commit();\n        this.currFragment = f;\n    }\n\n    def replace(Fragment f) {\n        if (currFragment == f) {\n            return\n        }\n        coordinatorLayout.removeAllViews()\n        getSupportFragmentManager().beginTransaction().remove(currFragment).add(R.id.container, f).commit()\n        this.currFragment = f\n    }\n\n    @Override\n    void notice(int noticeId) {\n        switch (noticeId) {\n            case Config.Action.FINISH:\n                finish()\n                break\n            case Config.Action.CHANGE_DATE:\n                DatePickerDialog dialog = DatePickerDialog.newInstance({ datePickerDialog, year, month, day ->\n                    Intent i = new Intent(this, DailyActivity.class)\n                    i.putExtra(Config.Static.YEAR, year as int)\n                    i.putExtra(Config.Static.MONTH, (month as int) + 1)\n                    i.putExtra(Config.Static.DAY, day as int)\n                    startActivity(i)\n                }, year, month - 1, day)\n                dialog.setVibrate(false)\n                dialog.show(getSupportFragmentManager(), \"time\")\n//                DatePickerDialog dialog = new DatePickerDialog(this, { picker, year, month, day ->\n//                    Intent i = new Intent(this, DailyActivity.class)\n//                    i.putExtra(Config.Static.YEAR, year as int)\n//                    i.putExtra(Config.Static.MONTH, (month as int) + 1)\n//                    i.putExtra(Config.Static.DAY, day as int)\n//                    startActivity(i)\n//                }, year, month - 1, day)\n//                dialog.show()\n//                DatePickerDialog dialog = DatePickerDialog.newInstance(this, times[0], times[1] - 1, times[2])\n//                dialog.vibrate(false)\n//                dialog.show(getFragmentManager(), \"date\")\n                break\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/HomeActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.design.widget.CoordinatorLayout\nimport android.support.design.widget.NavigationView\nimport android.support.v4.app.Fragment\nimport android.support.v4.view.GravityCompat\nimport android.support.v4.widget.DrawerLayout\nimport android.support.v7.app.AppCompatActivity\nimport android.view.MenuItem\nimport com.fourmob.datetimepicker.date.DatePickerDialog\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.dialog.InfoDialog\nimport zhou.gank.io.ui.fragment.DailyFragment\nimport zhou.gank.io.util.Notifier\nimport zhou.gank.io.util.TextKit\nimport zhou.gank.io.util.TimeKit\n\n@CompileStatic\nclass HomeActivity extends AppCompatActivity implements Notifier {\n\n    static int needRecreate\n\n    DrawerLayout drawerLayout;\n    NavigationView navigationView;\n    CoordinatorLayout coordinatorLayout;\n\n    private DailyFragment dailyFragment;\n    private Fragment currFragment;\n    private boolean isRecreate\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        App.setTheme(this)\n        super.onCreate(savedInstanceState);\n        setContentView(R.layout.activity_home);\n\n        initView();\n\n        dailyFragment = DailyFragment.newInstance(-1, -1, -1, true)\n\n        add(dailyFragment)\n\n        App.addNotifier(this)\n    }\n\n    def initView() {\n        drawerLayout = findViewById(R.id.drawer_layout) as DrawerLayout\n        navigationView = findViewById(R.id.nav_view) as NavigationView\n        coordinatorLayout = findViewById(R.id.container) as CoordinatorLayout\n\n        navigationView.setNavigationItemSelectedListener({ item ->\n            def i = item as MenuItem\n            drawerLayout.closeDrawers()\n            switch (i.getItemId()) {\n                case R.id.nav_daily:\n                    replace(dailyFragment)\n                    return true\n                case R.id.nav_type:\n                    Intent intent = new Intent(this, TabActivity.class)\n                    intent.putExtra(Config.Static.IS_RANDOM, false)\n                    App.getInstance().getMainHandler().postDelayed({\n                        startActivity(intent)\n                    }, 250)\n                    return true\n                case R.id.nav_random:\n                    Intent intent = new Intent(this, TabActivity.class)\n                    intent.putExtra(Config.Static.IS_RANDOM, true)\n                    App.getInstance().getMainHandler().postDelayed({\n                        startActivity(intent)\n                    }, 250)\n                    return true\n                case R.id.nav_collect:\n                    Intent intent = new Intent(this, CollectActivity.class)\n                    App.getInstance().getMainHandler().postDelayed({\n                        startActivity(intent)\n                    }, 250)\n                    return true\n                case R.id.nav_info:\n                    def info = InfoDialog.newInstance(getString(R.string.nav_info), TextKit.getInfo())\n                    info.show(getSupportFragmentManager(), \"info\")\n                    return true\n                case R.id.nav_setting:\n                    def intent1 = new Intent(this, SettingActivity.class)\n                    App.getInstance().getMainHandler().postDelayed({\n                        startActivity(intent1)\n                    }, 200)\n                    return true\n            }\n            return false\n        })\n\n    }\n\n    def add(Fragment f) {\n        getSupportFragmentManager().beginTransaction().add(R.id.container, f).commit();\n        this.currFragment = f;\n    }\n\n    def replace(Fragment f) {\n        if (currFragment == f) {\n            return\n        }\n        coordinatorLayout.removeAllViews()\n        getSupportFragmentManager().beginTransaction().remove(currFragment).add(R.id.container, f).commit()\n        this.currFragment = f\n    }\n\n    def remove() {\n        if (currFragment) {\n            getSupportFragmentManager().beginTransaction().remove(currFragment).commit()\n            coordinatorLayout.removeAllViews()\n            this.currFragment = null\n        }\n    }\n\n    @Override\n    void notice(int noticeId) {\n        switch (noticeId) {\n            case Config.Action.OPEN_DRAWER_LAYOUT:\n                drawerLayout.openDrawer(GravityCompat.START)\n                break\n            case Config.Action.CHANGE_DATE:\n                def times = TimeKit.getTime()\n                DatePickerDialog dialog = DatePickerDialog.newInstance({ picker, year, month, day ->\n                    Intent i = new Intent(this, DailyActivity.class)\n                    i.putExtra(Config.Static.YEAR, year as int)\n                    i.putExtra(Config.Static.MONTH, (month as int) + 1)\n                    i.putExtra(Config.Static.DAY, day as int)\n                    startActivity(i)\n                }, times[0], times[1] - 1, times[2])\n                dialog.setVibrate(false)\n                dialog.show(getSupportFragmentManager(), \"date\")\n                break\n            case Config.Action.RESTART:\n                needRecreate = 1\n                break\n        }\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy()\n        App.removeNotifier(this)\n    }\n\n    @Override\n    protected void onResume() {\n        super.onResume()\n        if (needRecreate == 1) {\n            remove()\n            recreate()\n            needRecreate++\n            return\n        }\n        if (needRecreate == 2) {\n            App.getInstance().getMainHandler().postDelayed({\n                dailyFragment.requestData()\n            }, 200)\n            needRecreate = 0\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/ImageGalleryActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.fragment.ImageGalleryFragment\n\n@CompileStatic\npublic class ImageGalleryActivity extends ToolbarActivity {\n\n    ArrayList<String> urls\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        quickFinish()\n\n        Intent i = getIntent()\n        urls = i.getStringArrayListExtra(Config.Static.URLS)\n        add(ImageGalleryFragment.newInstance(urls, i.getIntExtra(Config.Static.POSITION, 0)))\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/SettingActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.os.Bundle\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\nimport zhou.gank.io.ui.fragment.SettingFragment\n\n@CompileStatic\npublic class SettingActivity extends ToolbarActivity {\n\n    @Override\n    protected void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        quickFinish()\n        setTitle(R.string.title_setting)\n\n        getFragmentManager().beginTransaction().add(R.id.container, new SettingFragment()).commit()\n    }\n\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/TabActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.design.widget.TabLayout\nimport android.support.v4.app.Fragment\nimport android.support.v4.app.FragmentPagerAdapter\nimport android.support.v4.view.PagerAdapter\nimport android.support.v4.view.ViewPager\nimport android.support.v7.app.ActionBar\nimport android.support.v7.app.AppCompatActivity\nimport android.support.v7.widget.Toolbar\nimport android.view.MenuItem;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.fragment.GankFragment\n\n@CompileStatic\npublic class TabActivity extends AppCompatActivity {\n\n    boolean isRandom\n\n    Toolbar toolbar\n    TabLayout tabLayout\n    ViewPager viewPager\n    int[] ids = [R.string.nav_android, R.string.nav_ios, R.string.nav_recommend, R.string.nav_resource, R.string.nav_welfare, R.string.nav_video] as int[]\n    Fragment[] fragments\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        if (App.themeIsLight()) {\n            setTheme(R.style.AppTheme_Tab)\n        } else {\n            setTheme(R.style.AppTheme_TabDark)\n        }\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_tab)\n\n        Intent intent = getIntent()\n        isRandom = intent.getBooleanExtra(Config.Static.IS_RANDOM, false)\n\n        fragments = new Fragment[6]\n\n        fragments[0] = GankFragment.newInstance(Config.Type.ANDROID, isRandom)\n        fragments[1] = GankFragment.newInstance(Config.Type.IOS, isRandom)\n        fragments[2] = GankFragment.newInstance(Config.Type.RECOMMEND, isRandom)\n        fragments[3] = GankFragment.newInstance(Config.Type.RESOURCES, isRandom)\n        fragments[4] = GankFragment.newInstance(Config.Type.WELFARE, isRandom, true)\n        fragments[5] = GankFragment.newInstance(Config.Type.VIDEO, isRandom)\n\n        initView()\n    }\n\n    void initView() {\n        toolbar = findViewById(R.id.toolbar) as Toolbar\n        setSupportActionBar(toolbar)\n        ActionBar actionBar = getSupportActionBar()\n        actionBar?.setDisplayHomeAsUpEnabled(true)\n\n        tabLayout = findViewById(R.id.tabs) as TabLayout\n        viewPager = findViewById(R.id.viewpager) as ViewPager\n\n        ids.each { tabLayout.addTab(tabLayout.newTab().setText(getString(it as Integer))) }\n\n        PagerAdapter adapter = new FragmentPagerAdapter(getSupportFragmentManager()) {\n            @Override\n            Fragment getItem(int position) {\n                fragments[position]\n            }\n\n            @Override\n            int getCount() {\n                return fragments.length\n            }\n\n            @Override\n            CharSequence getPageTitle(int position) {\n                return getString(ids[position])\n            }\n        }\n        viewPager.setAdapter(adapter)\n        tabLayout.setupWithViewPager(viewPager)\n        tabLayout.setTabsFromPagerAdapter(adapter)\n\n        if (isRandom) {\n            setTitle(R.string.nav_random)\n        } else {\n            setTitle(R.string.nav_type)\n        }\n    }\n\n    @Override\n    boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case android.R.id.home:\n                finish()\n                return true\n        }\n        return super.onOptionsItemSelected(item)\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/ToolbarActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.design.widget.CoordinatorLayout\nimport android.support.v4.app.Fragment\nimport android.support.v7.app.AppCompatActivity\nimport android.support.v7.widget.Toolbar\nimport android.view.KeyEvent\nimport android.view.MenuItem;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.ui.fragment.BaseFragment\n\n@CompileStatic\npublic class ToolbarActivity extends AppCompatActivity {\n\n    Toolbar toolbar\n    CoordinatorLayout coordinatorLayout\n    BaseFragment currFragment\n    boolean quick\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        App.setTheme(this)\n        super.onCreate(savedInstanceState)\n        setContentView(R.layout.activity_toolbar)\n        toolbar = findViewById(R.id.toolbar) as Toolbar\n        coordinatorLayout = findViewById(R.id.container) as CoordinatorLayout\n\n        setSupportActionBar(toolbar)\n    }\n\n    def quickFinish() {\n        def actionBar = getSupportActionBar()\n        actionBar?.setDisplayHomeAsUpEnabled(true)\n        quick = true\n    }\n\n    def add(BaseFragment f) {\n        getSupportFragmentManager().beginTransaction().add(R.id.container, f).commit();\n        currFragment = f\n    }\n\n    def replace(BaseFragment f) {\n        coordinatorLayout.removeAllViews()\n        getSupportFragmentManager().beginTransaction().remove(currFragment).add(R.id.container, f).commit()\n        currFragment = f\n    }\n\n    @Override\n    boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case android.R.id.home:\n                if (quick) {\n                    finish()\n                    return true\n                }\n                break\n        }\n        return super.onOptionsItemSelected(item)\n    }\n\n    @Override\n    boolean onKeyDown(int keyCode, KeyEvent event) {\n        return currFragment?.onKeyDown(keyCode, event) || super.onKeyDown(keyCode, event)\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/activity/WebActivity.groovy",
    "content": "package zhou.gank.io.ui.activity\n\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.fragment.WebFragment\n\n@CompileStatic\npublic class WebActivity extends ToolbarActivity {\n\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        quickFinish()\n        def i = getIntent()\n\n        String title\n        title = i.getStringExtra(Config.Static.TITLE)\n        if (title == null) {\n            title = getString(R.string.app_name)\n        }\n        setTitle(title)\n\n        add(WebFragment.newInstance(i.getStringExtra(Config.Static.URL), title))\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/adapter/BaseAdapter.groovy",
    "content": "package zhou.gank.io.ui.adapter\n\nimport android.support.v7.widget.RecyclerView\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.model.Gank\n\n@CompileStatic\npublic\nabstract class BaseAdapter<T extends RecyclerView.ViewHolder> extends RecyclerView.Adapter<T> {\n\n    List<Gank> ganks\n    Closure clickListener, longClickListener\n\n    void setGanks(List<Gank> ganks) {\n        this.ganks = ganks\n        notifyDataSetChanged()\n    }\n\n    void setClickListener(Closure clickListener) {\n        this.clickListener = clickListener\n    }\n\n    void setLongClickListener(Closure longClickListener) {\n        this.longClickListener = longClickListener\n    }\n\n    void removeItem(int position) {\n\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/adapter/DailyAdapter.groovy",
    "content": "package zhou.gank.io.ui.adapter\n\nimport android.support.v7.widget.CardView\nimport android.support.v7.widget.RecyclerView\nimport android.text.method.LinkMovementMethod\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.TextView\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.model.GankDaily\nimport zhou.gank.io.util.TextKit\n\n@CompileStatic\nclass DailyAdapter extends BaseAdapter<Holder> {\n\n    private GankDaily daily;\n\n    @Override\n    Holder onCreateViewHolder(ViewGroup parent, int viewType) {\n        Holder holder = new Holder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_daily, null));\n        return holder;\n    }\n\n    @Override\n    void onBindViewHolder(Holder holder, int position) {\n        holder.title.setText(daily.getType(position));\n        holder.content.setText(TextKit.generate(daily.getGanhuo(position), App.getInstance().getResources().getColor(R.color.material_lightBlue_500)));\n    }\n\n    @Override\n    int getItemCount() {\n        return daily == null ? 0 : daily.size()\n    }\n\n    static class Holder extends RecyclerView.ViewHolder {\n\n        public TextView title, content;\n\n        public Holder(View itemView) {\n            super(itemView);\n\n            title = (TextView) itemView.findViewById(R.id.title);\n            content = (TextView) itemView.findViewById(R.id.content);\n\n            if (itemView instanceof CardView) {\n                def card = itemView as CardView\n                if (App.themeIsLight()) {\n                    card.setCardBackgroundColor(App.getInstance().getCardLight())\n                    title.setTextColor(App.getInstance().getTextLight())\n                } else {\n                    card.setCardBackgroundColor(App.getInstance().getCardDark())\n                    title.setTextColor(App.getInstance().getTextDark())\n                }\n            }\n\n            content.setMovementMethod(LinkMovementMethod.getInstance());\n        }\n    }\n\n    void setDaily(GankDaily daily) {\n        this.daily = daily;\n        notifyDataSetChanged();\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/adapter/GankAdapter.groovy",
    "content": "package zhou.gank.io.ui.adapter\n\nimport android.support.v7.widget.CardView\nimport android.support.v7.widget.RecyclerView\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.TextView\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.util.TimeKit\n\n@CompileStatic\npublic class GankAdapter extends BaseAdapter<Holder> {\n\n    List<Gank> ganks\n\n    @Override\n    Holder onCreateViewHolder(ViewGroup viewGroup, int i) {\n        def holder = new Holder(LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.item_gank, null))\n        holder.setListener { p ->\n            Gank gank = ganks?.get(p as int)\n            clickListener?.call(gank)\n        }\n        holder.setLongListener { v, p ->\n            Gank gank = ganks?.get(p as int)\n            longClickListener?.call(v, gank, p)\n        }\n        return holder\n    }\n\n    @Override\n    void onBindViewHolder(Holder holder, int i) {\n        Gank gank = ganks.get(i)\n\n        holder.title.setText(gank.desc)\n        holder.user.setText(gank.who)\n        holder.time.setText(TimeKit.format(gank.createdAt))\n    }\n\n    @Override\n    int getItemCount() {\n        return ganks == null ? 0 : ganks.size()\n    }\n\n    static class Holder extends RecyclerView.ViewHolder {\n\n        public TextView title, user, time\n\n        Closure listener, longListener\n\n        Holder(View itemView) {\n            super(itemView)\n\n            title = itemView.findViewById(R.id.title) as TextView\n            user = itemView.findViewById(R.id.user) as TextView\n            time = itemView.findViewById(R.id.time) as TextView\n\n            if (itemView instanceof CardView) {\n                def card = itemView as CardView\n                if (App.themeIsLight()) {\n                    card.setCardBackgroundColor(App.getInstance().getCardLight())\n                } else {\n                    card.setCardBackgroundColor(App.getInstance().getCardDark())\n                }\n            }\n\n            itemView.setOnClickListener({ v ->\n                listener?.call(getAdapterPosition())\n            })\n\n            itemView.setOnLongClickListener({ v ->\n                longListener?.call(itemView, getAdapterPosition())\n            })\n        }\n\n        void setListener(Closure listener) {\n            this.listener = listener\n        }\n    }\n\n    void setGanks(List<Gank> ganks) {\n        this.ganks = ganks\n        notifyDataSetChanged()\n    }\n\n    @Override\n    void removeItem(int position) {\n        ganks.remove(position)\n        notifyItemRemoved(position)\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/adapter/ImageAdapter.groovy",
    "content": "package zhou.gank.io.ui.adapter\n\nimport android.support.v7.widget.CardView\nimport android.support.v7.widget.RecyclerView\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimport android.widget.TextView\nimport com.squareup.picasso.Picasso\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.util.TimeKit\n\n@CompileStatic\npublic class ImageAdapter extends BaseAdapter<Holder> {\n\n    private List<Gank> ganks\n\n    @Override\n    Holder onCreateViewHolder(ViewGroup parent, int viewType) {\n        Holder holder = new Holder(LayoutInflater.from(parent.getContext()).inflate(R.layout.item_image, null))\n        holder.setListener { p ->\n            Gank gank = ganks?.get(p as int)\n            clickListener?.call(gank, p)\n        }\n        return holder\n    }\n\n    @Override\n    void onBindViewHolder(Holder holder, int position) {\n        Gank gank = ganks.get(position)\n\n        Picasso.with(holder.icon.getContext()).load(gank.url).into(holder.icon)\n        holder.who.setText(gank.who)\n        holder.time.setText(TimeKit.format(gank.createdAt))\n    }\n\n    @Override\n    int getItemCount() {\n        return ganks == null ? 0 : ganks.size()\n    }\n\n    public static class Holder extends RecyclerView.ViewHolder {\n\n        ImageView icon\n        TextView who, time\n\n        Closure listener\n\n        Holder(View itemView) {\n            super(itemView)\n\n            icon = itemView.findViewById(R.id.icon) as ImageView\n            who = itemView.findViewById(R.id.who) as TextView\n            time = itemView.findViewById(R.id.time) as TextView\n\n            if (itemView instanceof CardView) {\n                def card = itemView as CardView\n                if (App.themeIsLight()) {\n                    card.setCardBackgroundColor(App.getInstance().getCardLight())\n                } else {\n                    card.setCardBackgroundColor(App.getInstance().getCardDark())\n                }\n            }\n\n            itemView.setOnClickListener({ v ->\n                listener?.call(getAdapterPosition())\n            })\n        }\n\n        void setListener(Closure listener) {\n            this.listener = listener\n        }\n    }\n\n    void setGanks(List<Gank> ganks) {\n        this.ganks = ganks\n        notifyDataSetChanged()\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/adapter/ImageGalleryAdapter.groovy",
    "content": "package zhou.gank.io.ui.adapter\n\nimport android.content.Context\nimport android.support.v4.view.PagerAdapter\nimport android.support.v4.view.ViewPager\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimport android.widget.TextView\nimport com.squareup.picasso.Callback\nimport com.squareup.picasso.Picasso;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\n\n@CompileStatic\npublic class ImageGalleryAdapter extends PagerAdapter {\n\n    List<String> urls\n\n    ImageGalleryAdapter(List<String> urls) {\n        this.urls = urls\n    }\n\n    @Override\n    int getCount() {\n        return urls == null ? 0 : urls.size()\n    }\n\n    @Override\n    boolean isViewFromObject(View view, Object object) {\n        return view.is(object)\n    }\n\n    @Override\n    Object instantiateItem(ViewGroup container, int position) {\n        Context context = container.getContext()\n        View v = LayoutInflater.from(context).inflate(R.layout.layout_gallery, null)\n        ImageView imageView = v.findViewById(R.id.image) as ImageView\n\n        View error = v.findViewById(R.id.error_layout)\n//        View progress = v.findViewById(R.id.progressBar)\n\n        Closure loadImage = { view ->\n//            progress.setVisibility(View.VISIBLE)\n            error.setVisibility(View.GONE)\n            Picasso.with(context).load(urls[position]).into(imageView, new Callback() {\n                @Override\n                void onSuccess() {\n//                    progress.setVisibility(View.GONE)\n                }\n\n                @Override\n                void onError() {\n//                    progress.setVisibility(View.GONE)\n                    error.setVisibility(View.VISIBLE)\n                }\n            })\n        }\n\n//        error.setOnClickListener(loadImage)\n\n        loadImage(null)\n\n        (container as ViewPager).addView(v, 0);\n        return v\n    }\n\n    @Override\n    void destroyItem(ViewGroup container, int position, Object object) {\n        (container as ViewPager).removeView(object as View);\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/dialog/InfoDialog.groovy",
    "content": "package zhou.gank.io.ui.dialog\n\nimport android.app.Dialog\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.v4.app.DialogFragment\nimport android.support.v7.app.AlertController\nimport android.support.v7.app.AlertDialog\nimport android.text.method.LinkMovementMethod\nimport android.view.LayoutInflater\nimport android.widget.TextView;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\n\n@CompileStatic\npublic class InfoDialog extends DialogFragment {\n\n    String title\n    CharSequence content\n\n    @Override\n    void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        Bundle b = getArguments()\n        title = b?.getString(Config.Static.TITLE)\n        content = b?.getCharSequence(Config.Static.CONTENT)\n    }\n\n    @Override\n    Dialog onCreateDialog(Bundle savedInstanceState) {\n        AlertDialog.Builder builder = new AlertDialog.Builder(getActivity())\n        TextView tv = LayoutInflater.from(getActivity()).inflate(R.layout.dialog_text, null) as TextView\n        tv.setText(content)\n        tv.setMovementMethod(LinkMovementMethod.getInstance())\n        builder.setTitle(title).setView(tv).setPositiveButton(R.string.confirm, null)\n        AlertDialog dialog = builder.create()\n        return dialog\n    }\n\n    static InfoDialog newInstance(String title, CharSequence content) {\n        InfoDialog dialog = new InfoDialog()\n        Bundle bundle = new Bundle()\n        bundle.putString(Config.Static.TITLE, title)\n        bundle.putCharSequence(Config.Static.CONTENT, content)\n        dialog.setArguments(bundle)\n        return dialog\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/AdvanceFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.v4.widget.SwipeRefreshLayout\nimport android.support.v7.widget.RecyclerView\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\n\n@CompileStatic\npublic class AdvanceFragment extends BaseFragment {\n\n    SwipeRefreshLayout swipeRefreshLayout\n    RecyclerView recyclerView\n    View error\n\n    @Override\n    View onCreateView(LayoutInflater inflater,\n                      @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View v = inflater.inflate(R.layout.fragment_recyler_view, container, false)\n        initView(v)\n        return v\n    }\n\n    @Override\n    protected void initView(View v) {\n        swipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout) as SwipeRefreshLayout\n        recyclerView = v.findViewById(R.id.recyclerView) as RecyclerView\n\n        swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_purple, android.R.color.holo_blue_bright, android.R.color.holo_orange_light,\n                android.R.color.holo_red_light);\n\n\n        swipeRefreshLayout.setOnRefreshListener(this.&requestRefresh)\n\n        error = v.findViewById(R.id.error)\n\n    }\n\n    protected void onFailure() {\n        swipeRefreshLayout.setRefreshing(false)\n        error.setVisibility(View.VISIBLE)\n    }\n\n    protected void onSuccess() {\n        swipeRefreshLayout.setRefreshing(false)\n        recyclerView.setVisibility(View.VISIBLE)\n        error.setVisibility(View.GONE)\n    }\n\n    protected void requestRefresh(View v = null) {\n        swipeRefreshLayout.setRefreshing(true)\n        error.setVisibility(View.GONE)\n    }\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/BaseFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.app.Activity\nimport android.support.v4.app.Fragment\nimport android.support.v7.app.ActionBar\nimport android.support.v7.app.AppCompatActivity\nimport android.support.v7.widget.Toolbar\nimport android.view.KeyEvent\nimport android.view.View\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.util.Notifier\n\n@CompileStatic\nclass BaseFragment extends Fragment {\n\n    Notifier notifier\n\n    @Override\n    void onAttach(Activity activity) {\n        super.onAttach(activity)\n        if (activity instanceof Notifier) {\n            notifier = activity as Notifier\n        }\n    }\n\n    protected void setSupportActionBar(Toolbar toolbar) {\n        Activity activity = getActivity();\n        if (activity instanceof AppCompatActivity) {\n            AppCompatActivity appCompatActivity = activity as AppCompatActivity;\n            appCompatActivity.setSupportActionBar(toolbar);\n        }\n    }\n\n    protected ActionBar getSupportActionBar() {\n        Activity activity = getActivity();\n        if (activity instanceof AppCompatActivity) {\n            AppCompatActivity appCompatActivity = activity as AppCompatActivity;\n            return appCompatActivity.getSupportActionBar();\n        }\n        return null;\n    }\n\n    protected void noticeActivity(int noticeId) {\n        notifier?.notice(noticeId)\n    }\n\n    protected void initView(View v) {\n\n    }\n\n    protected void setTitle(String title) {\n        getActivity().setTitle(title)\n    }\n\n    protected void setTitle(int res) {\n        getActivity().setTitle(res)\n    }\n\n    boolean onKeyDown(int keyCode, KeyEvent event) {\n        return false\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/DailyFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.design.widget.CollapsingToolbarLayout\nimport android.support.design.widget.FloatingActionButton\nimport android.support.v4.app.Fragment\nimport android.support.v4.app.FragmentPagerAdapter\nimport android.support.v4.view.PagerAdapter\nimport android.support.v4.view.ViewPager\nimport android.support.v7.app.ActionBar\nimport android.support.v7.widget.LinearLayoutManager\nimport android.support.v7.widget.RecyclerView\nimport android.support.v7.widget.Toolbar\nimport android.view.*\nimport android.widget.Toast\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.data.DataManager\nimport zhou.gank.io.data.TimeProvider\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.model.GankDaily\nimport zhou.gank.io.ui.adapter.DailyAdapter\nimport zhou.gank.io.util.TimeKit\n\n@CompileStatic\nclass DailyFragment extends BaseFragment {\n\n    public static final int ID_REFRESH = 0x78901\n\n//    ImageView icon;\n    RecyclerView recyclerView;\n    Toolbar toolbar;\n    CollapsingToolbarLayout collapsingToolbarLayout;\n    TimeProvider provider\n    DailyAdapter dailyAdapter;\n    ViewPager viewPager\n    FloatingActionButton fab\n    View loading, loadingProgress, empty, error\n    boolean isMain = false\n    int year, month, day\n    int count\n    MenuItem refresh\n\n\n    @Override\n    void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setHasOptionsMenu(true);\n        def b = getArguments()\n        List<Integer> time = TimeKit.getTime()\n        year = time[0]\n        month = time[1]\n        day = time[2]\n        if (b) {\n            year = b.getInt(Config.Static.YEAR, year)\n            month = b.getInt(Config.Static.MONTH, month)\n            day = b.getInt(Config.Static.DAY, day)\n            isMain = b.getBoolean(Config.Static.IS_MAIN, false)\n        }\n\n        provider = new TimeProvider(year, month, day)\n        provider.setNoticeable(true)\n    }\n\n    @Nullable\n    @Override\n    View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {\n        View view = inflater.inflate(R.layout.fragment_daily, container, false);\n\n        toolbar = view.findViewById(R.id.toolbar) as Toolbar\n        collapsingToolbarLayout = view.findViewById(R.id.collapsing_toolbar) as CollapsingToolbarLayout\n        recyclerView = view.findViewById(R.id.recyclerView) as RecyclerView\n        viewPager = view.findViewById(R.id.viewpager) as ViewPager\n        fab = view.findViewById(R.id.fab) as FloatingActionButton\n        loading = view.findViewById(R.id.loading)\n        loadingProgress = view.findViewById(R.id.progressBar)\n        empty = view.findViewById(R.id.no_data)\n        error = view.findViewById(R.id.error)\n\n        setSupportActionBar(toolbar);\n        ActionBar ab = getSupportActionBar();\n        if (ab != null) {\n            if (isMain)\n                ab.setHomeAsUpIndicator(R.drawable.ic_menu_white_48px);\n            ab.setDisplayHomeAsUpEnabled(true);\n        }\n\n        toolbar.setTitle(R.string.app_name);\n\n        dailyAdapter = new DailyAdapter();\n\n        recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()))\n        recyclerView.setAdapter(dailyAdapter)\n        requestDaily()\n\n        fab.setOnClickListener({ v ->\n            noticeActivity(Config.Action.CHANGE_DATE)\n        })\n\n        error.setOnClickListener({ v ->\n            requestDaily()\n        })\n\n        return view;\n    }\n\n\n    protected void setUpData(GankDaily daily) {\n        if (daily != null) {\n            if (daily.isEmpty()) {\n                if (isMain) {\n                    //为主页的情况\n                    if (count > Config.Configurable.MAX_iteration) {\n                        //重复加载次数过多(到达了底端)\n                        setTitle(provider.year, provider.month, provider.day)\n                        setEmpty()\n                    } else {\n                        //加载前一天的数据\n                        if (count == 0) {\n                            // 重新加载今天的内容\n                            DataManager.getInstance().update(provider, this.&setUpData)\n                            count++\n                        } else {\n                            count++\n                            provider = provider.getPrevDay()\n                            if (TimeKit.future(provider.year, provider.month, provider.day)) {\n                                //如如果要加载的数据是今天或以后\n                                DataManager.getInstance().update(provider, this.&setUpData)\n                            } else {\n                                DataManager.getInstance().get(provider, this.&setUpData)\n                            }\n                        }\n                    }\n                } else {\n                    // Empty\n                    setTitle(provider.year, provider.month, provider.day)\n                    setEmpty()\n                }\n            } else {\n                // Success\n                setTitle(provider.year, provider.month, provider.day)\n                List<List<Gank>> ganks = daily.ganks\n                List<String> types = daily.types\n                List<Gank> welfares = ganks.get(types.indexOf(Config.Type.WELFARE))\n                int size = welfares?.size()\n                Fragment[] fs = new Fragment[size]\n                size.times {\n                    int index = it as int\n                    fs[index] = ImagePageFragment.newInstance(welfares.get(index).url)\n                }\n\n                PagerAdapter adapter = new FragmentPagerAdapter(getFragmentManager()) {\n                    @Override\n                    Fragment getItem(int i) {\n                        fs[i]\n                    }\n\n                    @Override\n                    int getCount() {\n                        return fs.length\n                    }\n                } as PagerAdapter\n\n                viewPager.setAdapter(adapter)\n\n                dailyAdapter.setDaily(daily)\n\n                setSuccess()\n            }\n        } else {\n            // Error\n            setTitle(provider.year, provider.month, provider.day)\n            setError()\n        }\n        refresh?.setVisible(true)\n    }\n\n    @Override\n    void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        super.onCreateOptionsMenu(menu, inflater)\n        refresh = menu.add(0, ID_REFRESH, 0, R.string.text_refresh)\n        refresh.setIcon(R.drawable.ic_refresh_48px)\n        refresh.setShowAsAction(MenuItem.SHOW_AS_ACTION_ALWAYS)\n        refresh.setVisible(false)\n    }\n\n    @Override\n    boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case android.R.id.home:\n                if (isMain) {\n                    noticeActivity(Config.Action.OPEN_DRAWER_LAYOUT)\n                } else {\n                    noticeActivity(Config.Action.FINISH)\n                }\n                return true;\n            case ID_REFRESH:\n                requestUpdate()\n                return true\n        }\n        return super.onOptionsItemSelected(item);\n    }\n\n    @Override\n    protected void setTitle(String title) {\n        collapsingToolbarLayout.setTitle(title);\n    }\n\n    def requestDaily() {\n        setTitle(getString(R.string.loading))\n        setLoading()\n        refresh?.setVisible(false)\n        requestData()\n    }\n\n    def requestUpdate() {\n        setTitle(getString(R.string.loading))\n        setLoading()\n        refresh?.setVisible(false)\n        DataManager.getInstance().update(provider, {\n            setUpData(it as GankDaily)\n            Toast.makeText(getActivity(),R.string.success_update,Toast.LENGTH_SHORT).show()\n        })\n    }\n\n    def requestData() {\n        DataManager.getInstance().get(provider, this.&setUpData)\n    }\n\n    def setLoading() {\n        loading.setVisibility(View.VISIBLE)\n        loadingProgress.setVisibility(View.VISIBLE)\n        empty.setVisibility(View.GONE)\n        error.setVisibility(View.GONE)\n    }\n\n    def setSuccess() {\n        loading.setVisibility(View.INVISIBLE)\n    }\n\n    def setError() {\n        loading.setVisibility(View.VISIBLE)\n        loadingProgress.setVisibility(View.GONE)\n        empty.setVisibility(View.INVISIBLE)\n        error.setVisibility(View.VISIBLE)\n    }\n\n    def setEmpty() {\n        loading.setVisibility(View.VISIBLE)\n        loadingProgress.setVisibility(View.GONE)\n        empty.setVisibility(View.VISIBLE)\n        error.setVisibility(View.GONE)\n    }\n\n    protected void setTitle(int year, int month, int day) {\n        setTitle(\"${year}${getString(R.string.year)}${month}${getString(R.string.month)}${day}${getString(R.string.day)}\")\n    }\n\n    static DailyFragment newInstance(int year = -1, int month = -1, int day = -1, boolean isMain = false) {\n        DailyFragment fragment = new DailyFragment()\n        Bundle bundle = new Bundle()\n        if (year > 0 && month > 0 && day > 0) {\n            bundle.putInt(Config.Static.YEAR, year)\n            bundle.putInt(Config.Static.MONTH, month)\n            bundle.putInt(Config.Static.DAY, day)\n        }\n        bundle.putBoolean(Config.Static.IS_MAIN, isMain)\n        fragment.setArguments(bundle)\n        return fragment\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/GankFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.v7.widget.LinearLayoutManager\nimport android.support.v7.widget.RecyclerView\nimport android.view.Gravity\nimport android.view.LayoutInflater\nimport android.view.Menu\nimport android.view.MenuItem\nimport android.view.View\nimport android.widget.PopupMenu\nimport android.widget.ProgressBar\nimport android.widget.TextView\nimport android.widget.Toast\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.data.CollectProvider\nimport zhou.gank.io.data.DataManager\nimport zhou.gank.io.data.DataProvider\nimport zhou.gank.io.data.RandomProvider\nimport zhou.gank.io.data.TypeProvider\nimport zhou.gank.io.database.DatabaseManager\nimport zhou.gank.io.model.Bookmark\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.ui.activity.ImageGalleryActivity\nimport zhou.gank.io.ui.activity.WebActivity\nimport zhou.gank.io.ui.adapter.BaseAdapter\nimport zhou.gank.io.ui.adapter.GankAdapter\nimport zhou.gank.io.ui.adapter.ImageAdapter\nimport zhou.gank.io.util.NumKit\nimport zhou.widget.AdvanceAdapter\n\n@CompileStatic\npublic class GankFragment extends AdvanceFragment {\n\n    DataProvider provider\n    String type\n    boolean isRandom, isImage, loadMoreProgress, isBookmark\n    View more\n    LinearLayoutManager manager\n    ProgressBar progressBar\n    TextView moreText\n    private BaseAdapter adapter\n\n    @Override\n    void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        def b = getArguments()\n        if (b) {\n            type = b.getString(Config.Static.TYPE)\n            isRandom = b.getBoolean(Config.Static.IS_RANDOM, false)\n            isImage = b.getBoolean(Config.Static.IS_IMAGE, false)\n            isBookmark = b.getBoolean(Config.Static.IS_BOOKMARK, false)\n        }\n\n        int size = NumKit.getNum(Config.getString(getString(R.string.key_num), \"$Config.Configurable.DEFAULT_SIZE\"), Config.Configurable.DEFAULT_SIZE)\n\n        if (isBookmark) {\n            provider = new CollectProvider()\n        } else {\n            if (isRandom) {\n                provider = new RandomProvider(type, size)\n            } else {\n                provider = new TypeProvider(type, size)\n            }\n        }\n\n        if (isImage) {\n            adapter = new ImageAdapter()\n        } else {\n            adapter = new GankAdapter()\n        }\n\n        adapter.setClickListener { gank, p = null ->\n            def gs = gank as Gank\n            boolean flag = Config.getBoolean(getString(R.string.key_open), true)\n            if (!flag) {\n                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(gs.url))\n                startActivity(intent)\n            } else {\n                Intent intent\n                if (isImage) {\n                    intent = new Intent(getActivity(), ImageGalleryActivity.class)\n                    ArrayList<Gank> ganks = provider.get() as ArrayList<Gank>\n                    ArrayList<String> urls = new ArrayList<>(ganks.size())\n                    ganks.each {\n                        urls << it.url\n                    }\n                    intent.putStringArrayListExtra(Config.Static.URLS, urls)\n                    intent.putExtra(Config.Static.POSITION, p as int)\n                } else {\n                    intent = new Intent(getActivity(), WebActivity.class)\n                    intent.putExtra(Config.Static.URL, gs.url)\n                    intent.putExtra(Config.Static.TITLE, gs.desc)\n                }\n                startActivity(intent)\n            }\n        }\n\n        if (isBookmark) {\n            adapter.setLongClickListener { v, gank, p ->\n                def g = gank as Gank\n                def view = v as View\n                PopupMenu popupMenu = new PopupMenu(getActivity(), view, Gravity.END)\n                Menu menu = popupMenu.getMenu()\n                popupMenu.getMenuInflater().inflate(R.menu.menu_pop, menu)\n                popupMenu.setOnMenuItemClickListener({ item ->\n                    def i = item as MenuItem\n                    switch (i.getItemId()) {\n                        case R.id.menu_delete:\n                            DatabaseManager.getInstance().delete(g.url)\n                            adapter.removeItem(p as int)\n                            Toast.makeText(getActivity(), R.string.success_delete, Toast.LENGTH_SHORT).show()\n                            return true\n                    }\n                    return false\n                })\n                popupMenu.show()\n                return true\n            }\n        } else {\n            adapter.setLongClickListener { v, gank, p ->\n                def g = gank as Gank\n                def view = v as View\n                PopupMenu popupMenu = new PopupMenu(getActivity(), view, Gravity.END)\n                Menu menu = popupMenu.getMenu()\n                if (DatabaseManager.getInstance().isExist(g.url)) {\n                    popupMenu.getMenuInflater().inflate(R.menu.menu_pop_remove, menu)\n                } else {\n                    popupMenu.getMenuInflater().inflate(R.menu.menu_pop_add, menu)\n                }\n                popupMenu.setOnMenuItemClickListener({ item ->\n                    def i = item as MenuItem\n                    switch (i.getItemId()) {\n                        case R.id.menu_add:\n                            DatabaseManager.getInstance().insert(new Bookmark(g.url, g.desc))\n                            Toast.makeText(getActivity(), R.string.success_collect, Toast.LENGTH_SHORT).show()\n                            return true\n                        case R.id.menu_remove:\n                            DatabaseManager.getInstance().delete(g.url)\n                            Toast.makeText(getActivity(), R.string.success_uncollect, Toast.LENGTH_SHORT).show()\n                            return true\n                    }\n                    return false\n                })\n                popupMenu.show()\n                return true\n            }\n        }\n\n\n    }\n\n\n    public void setUpData(List<Gank> ganks) {\n        if (ganks != null) {\n            if (ganks.isEmpty()) {\n                onNoMoreData()\n                Toast.makeText(getActivity(), R.string.no_data, Toast.LENGTH_SHORT).show()\n            } else {\n                onSuccess()\n                adapter.setGanks(ganks)\n                showMore()\n            }\n        } else {\n            onLoadFailure()\n            onFailure()\n        }\n    }\n\n\n    @Override\n    protected void initView(View v) {\n        super.initView(v)\n\n        manager = new LinearLayoutManager(getActivity())\n        recyclerView.setLayoutManager(manager)\n\n        if (!isRandom) {\n            more = LayoutInflater.from(getActivity()).inflate(R.layout.layout_more, null)\n            moreText = more.findViewById(R.id.textView) as TextView\n            progressBar = more.findViewById(R.id.progressBar) as ProgressBar\n\n            AdvanceAdapter advanceAdapter = new AdvanceAdapter(adapter)\n            advanceAdapter.addFooter(more)\n            recyclerView.setAdapter(advanceAdapter)\n\n            recyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() {\n                @Override\n                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {\n                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {\n                        if (more.isShown()) {\n                            more()\n                        }\n//                        if (manager.findLastVisibleItemPosition() == advanceAdapter.getItemCount() - 1) {\n//                            more();\n//                        }\n                    }\n                }\n\n                @Override\n                public void onScrolled(RecyclerView recyclerView, int dx, int dy) {\n                }\n            });\n\n            more.setVisibility(View.GONE)\n            more.setClickable(false)\n\n            more.setOnClickListener(this.&more)\n\n        } else {\n            recyclerView.setAdapter(adapter)\n        }\n\n        if (isBookmark) {\n            swipeRefreshLayout.setEnabled(false)\n        }\n\n        swipeRefreshLayout.setRefreshing(true)\n        provider.setNoticeable(true)\n        DataManager.getInstance().get(provider, this.&setUpData)\n\n        error.setOnClickListener({ view ->\n            swipeRefreshLayout.setRefreshing(true)\n            error.setVisibility(View.GONE)\n            requestRefresh()\n        })\n\n    }\n\n    @Override\n    void onDestroyView() {\n        super.onDestroyView()\n        provider.setNoticeable(false)\n    }\n\n    @Override\n    void onHiddenChanged(boolean hidden) {\n        super.onHiddenChanged(hidden)\n        provider.setNoticeable(!hidden)\n    }\n\n    @Override\n    protected void requestRefresh() {\n        super.requestRefresh()\n        DataManager.getInstance().update(provider, this.&setUpData)\n    }\n\n    protected void more(View v = null) {\n        if (loadMoreProgress) {\n            return\n        }\n        loadMoreProgress = true\n        onLoading()\n        DataManager.getInstance().more(provider, { ganks ->\n            setUpData(ganks as List<Gank>)\n            loadMoreProgress = false\n        })\n    }\n\n    def onNoMoreData() {\n        moreText?.setText(R.string.more_last)\n        progressBar?.setVisibility(View.INVISIBLE)\n        more?.setClickable(false)\n    }\n\n    def onLoading() {\n        moreText?.setText(R.string.text_loading)\n        progressBar?.setVisibility(View.VISIBLE)\n        more?.setClickable(false)\n    }\n\n    def onLoadFailure() {\n        moreText?.setText(R.string.text_loading_failure)\n        progressBar?.setVisibility(View.VISIBLE)\n        more?.setClickable(true)\n    }\n\n    protected void showMore() {\n        if (manager.getItemCount() > manager.findLastVisibleItemPosition() - manager.findFirstVisibleItemPosition() + 1)\n            more?.setVisibility(View.VISIBLE)\n    }\n\n    static GankFragment newInstance(String type, boolean isRandom = false, boolean isImage = false, boolean isBookmark = false) {\n        GankFragment fragment = new GankFragment()\n        Bundle bundle = new Bundle()\n        bundle.putString(Config.Static.TYPE, type)\n        bundle.putBoolean(Config.Static.IS_RANDOM, isRandom)\n        bundle.putBoolean(Config.Static.IS_IMAGE, isImage)\n        bundle.putBoolean(Config.Static.IS_BOOKMARK, isBookmark)\n        fragment.setArguments(bundle)\n        fragment\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/ImageFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.v7.widget.LinearLayoutManager\nimport android.view.View\nimport android.widget.Toast\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.data.DataProvider\nimport zhou.gank.io.data.RandomProvider\nimport zhou.gank.io.data.TypeProvider\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.ui.adapter.ImageAdapter\n\n@CompileStatic\npublic class ImageFragment extends AdvanceFragment {\n\n    ImageAdapter adapter\n    LinearLayoutManager manager\n    DataProvider provider\n    boolean isRandom\n    String type\n    View more\n\n    @Override\n    void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n\n        def b = getArguments()\n        if (b) {\n            type = b.getString(Config.Static.TYPE)\n            isRandom = b.getBoolean(Config.Static.IS_RANDOM, false)\n        }\n\n        if (isRandom) {\n            provider = new RandomProvider(type, Config.Configurable.DEFAULT_SIZE)\n        } else {\n            provider = new TypeProvider(type, Config.Configurable.DEFAULT_SIZE)\n        }\n        adapter = new ImageAdapter()\n    }\n\n    public void setUpData(List<Gank> ganks) {\n        if (ganks != null) {\n            if (ganks.isEmpty()) {\n                hiddenMore()\n                Toast.makeText(getActivity(), \"empty\", Toast.LENGTH_SHORT).show()\n            } else {\n                onSuccess()\n                adapter.setGanks(ganks)\n            }\n        } else {\n            onFailure()\n        }\n    }\n\n    protected void hiddenMore() {\n        more?.setVisibility(View.GONE)\n    }\n\n    @Override\n    protected void initView(View v) {\n        super.initView(v)\n\n        manager = new LinearLayoutManager(getActivity())\n        recyclerView.setLayoutManager(manager)\n\n\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/ImageGalleryFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.content.Intent\nimport android.graphics.Bitmap\nimport android.graphics.drawable.Drawable\nimport android.net.Uri\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.v4.view.ViewPager\nimport android.view.LayoutInflater\nimport android.view.Menu\nimport android.view.MenuInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.Toast\nimport com.squareup.picasso.Picasso\nimport com.squareup.picasso.Target;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.adapter.ImageGalleryAdapter\nimport zhou.gank.io.util.FileKit\n\n@CompileStatic\npublic class ImageGalleryFragment extends BaseFragment {\n\n    public static final int ID_SHARE = 0x23456\n    public static final int ID_SAVE = 0x34567\n\n    List<String> urls\n    int position\n    ViewPager viewPager\n\n    @Override\n    void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        setHasOptionsMenu(true)\n        def b = getArguments()\n        urls = b?.getStringArrayList(Config.Static.URLS)\n        position = b?.getInt(Config.Static.POSITION, 0)\n        setTitle(\"${position + 1}/${urls == null ? 0 : urls.size()}\")\n    }\n\n    @Override\n    View onCreateView(LayoutInflater inflater,\n                      @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        viewPager = inflater.inflate(R.layout.fragment_viewpager, container, false) as ViewPager\n        ImageGalleryAdapter adapter = new ImageGalleryAdapter(urls)\n        viewPager.setAdapter(adapter)\n        viewPager.setCurrentItem(position, false)\n\n        viewPager.addOnPageChangeListener(new ViewPager.SimpleOnPageChangeListener() {\n            @Override\n            void onPageSelected(int position) {\n                setTitle(\"${position + 1}/${urls == null ? 0 : urls.size()}\")\n            }\n        })\n        return viewPager\n    }\n\n    @Override\n    void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        super.onCreateOptionsMenu(menu, inflater)\n        menu.add(0, ID_SHARE, 0, R.string.share)\n        menu.add(0, ID_SAVE, 0, R.string.save)\n    }\n\n    @Override\n    boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case ID_SHARE:\n                String url = urls?.get(viewPager.getCurrentItem())\n                Picasso.with(getActivity()).load(url).into(new Target() {\n                    @Override\n                    void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {\n                        File file = new File(App.getInstance().getExternalCacheDir(), \"temp.jpg\")\n                        FileKit.saveBitmapFile(bitmap, file)\n                        Intent intent = new Intent(Intent.ACTION_SEND)\n                        intent.setType(\"image/*\")\n                        intent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(file))\n                        startActivity(intent)\n                    }\n\n                    @Override\n                    void onBitmapFailed(Drawable errorDrawable) {\n                        Toast.makeText(getActivity(), R.string.error_get_image, Toast.LENGTH_SHORT).show()\n                    }\n\n                    @Override\n                    void onPrepareLoad(Drawable placeHolderDrawable) {\n\n                    }\n                })\n                return true\n            case ID_SAVE:\n                String url = urls?.get(viewPager.getCurrentItem())\n                File file = new File(App.SAVE_PATH, FileKit.getFileRealName(url))\n                Picasso.with(getActivity()).load(url).into(new Target() {\n                    @Override\n                    void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {\n                        FileKit.saveBitmapFile(bitmap, file)\n                        Toast.makeText(getActivity(), \"图片保存在:${file.getAbsolutePath()}\", Toast.LENGTH_LONG).show()\n                    }\n\n                    @Override\n                    void onBitmapFailed(Drawable errorDrawable) {\n                        Toast.makeText(getActivity(), R.string.error_get_image, Toast.LENGTH_SHORT).show()\n                    }\n\n                    @Override\n                    void onPrepareLoad(Drawable placeHolderDrawable) {\n\n                    }\n                })\n                return true\n        }\n        return super.onOptionsItemSelected(item)\n    }\n\n    static ImageGalleryFragment newInstance(ArrayList<String> urls, int position = 0) {\n        ImageGalleryFragment fragment = new ImageGalleryFragment()\n        Bundle bundle = new Bundle()\n        bundle.putStringArrayList(Config.Static.URLS, urls)\n        bundle.putInt(Config.Static.POSITION, position)\n        fragment.setArguments(bundle)\n        return fragment\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/ImagePageFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.content.Intent\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.v4.app.Fragment\nimport android.view.LayoutInflater\nimport android.view.View\nimport android.view.ViewGroup\nimport android.widget.ImageView\nimport com.squareup.picasso.Picasso;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.activity.ImageGalleryActivity\n\n@CompileStatic\npublic class ImagePageFragment extends Fragment {\n\n    @Override\n    View onCreateView(LayoutInflater inflater,\n                      @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        ImageView icon = inflater.inflate(R.layout.fragment_image_page, container, false) as ImageView\n        icon.setClickable(true)\n        def b = getArguments()\n        if (b) {\n            String url = b.getString(Config.Static.URL)\n            Picasso.with(getActivity()).load(url).into(icon)\n            icon.setOnClickListener({ v ->\n                if (icon.getDrawable()) {\n                    ArrayList<String> urls = new ArrayList<>(1)\n                    urls << url\n                    Intent intent = new Intent(getActivity(), ImageGalleryActivity.class)\n                    intent.putStringArrayListExtra(Config.Static.URLS, urls)\n                    intent.putExtra(Config.Static.POSITION, 0)\n                    startActivity(intent)\n                }\n            })\n        }\n        return icon\n    }\n\n\n    static ImagePageFragment newInstance(String url) {\n        ImagePageFragment imagePageFragment = new ImagePageFragment()\n        Bundle bundle = new Bundle()\n        bundle.putString(Config.Static.URL, url)\n        imagePageFragment.setArguments(bundle)\n        return imagePageFragment\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/SettingFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.os.Bundle\nimport android.preference.ListPreference\nimport android.preference.Preference\nimport android.preference.PreferenceFragment\nimport android.preference.PreferenceScreen\nimport android.widget.Toast;\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\n\n@CompileStatic\npublic class SettingFragment extends PreferenceFragment {\n\n    @Override\n    void onCreate(Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        addPreferencesFromResource(R.xml.setting)\n\n        ListPreference themes = findPreference(getString(R.string.key_theme)) as ListPreference\n        themes.setOnPreferenceChangeListener({ preference, o ->\n            App.themeChanged()\n            getActivity().recreate()\n            Toast.makeText(getActivity(), \"设置成功\", Toast.LENGTH_SHORT).show()\n            return true\n        })\n    }\n\n    @Override\n    boolean onPreferenceTreeClick(PreferenceScreen preferenceScreen, Preference preference) {\n        switch (preference.getKey()) {\n            case getString(R.string.key_clear):\n                def g = App.cacheFile().deleteDir()\n                if (g) {\n                    App.toast(R.string.success_clear)\n                }\n        }\n        return super.onPreferenceTreeClick(preferenceScreen, preference)\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/fragment/WebFragment.groovy",
    "content": "package zhou.gank.io.ui.fragment\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Bundle\nimport android.support.annotation.Nullable\nimport android.support.v4.widget.SwipeRefreshLayout\nimport android.view.KeyEvent\nimport android.view.LayoutInflater\nimport android.view.Menu\nimport android.view.MenuInflater\nimport android.view.MenuItem\nimport android.view.View\nimport android.view.ViewGroup\nimport android.webkit.WebChromeClient\nimport android.webkit.WebSettings\nimport android.webkit.WebView\nimport android.webkit.WebViewClient\nimport android.widget.ProgressBar\nimport android.widget.Toast\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.database.DatabaseManager\nimport zhou.gank.io.model.Bookmark\nimport zhou.gank.io.util.LogKit\n\n@CompileStatic\npublic class WebFragment extends BaseFragment {\n\n    WebView webView\n    String url, title\n    ProgressBar progressBar\n    SwipeRefreshLayout swipeRefreshLayout\n    MenuItem itemCollect\n\n    @Override\n    void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState)\n        setHasOptionsMenu(true)\n    }\n\n    @Override\n    View onCreateView(LayoutInflater inflater,\n                      @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        View v = inflater.inflate(R.layout.fragment_web, container, false)\n        initView(v)\n        return v\n    }\n\n    @Override\n    protected void initView(View v) {\n        webView = v.findViewById(R.id.web_view) as WebView\n        progressBar = v.findViewById(R.id.progressBar) as ProgressBar\n        swipeRefreshLayout = v.findViewById(R.id.swipeRefreshLayout) as SwipeRefreshLayout\n\n        swipeRefreshLayout.setColorSchemeResources(android.R.color.holo_purple, android.R.color.holo_blue_bright, android.R.color.holo_orange_light,\n                android.R.color.holo_red_light);\n\n        webView.getSettings().setJavaScriptEnabled(true)\n\n        Bundle bundle = getArguments()\n        url = bundle?.getString(Config.Static.URL)\n        title = bundle?.getString(Config.Static.TITLE)\n\n        webView.loadUrl(url)\n\n        webView.setWebChromeClient(new WebChromeClient() {\n            @Override\n            public void onProgressChanged(WebView view, int newProgress) {\n                if (newProgress == 100) {\n                    // 网页加载完成\n                    progressBar.setVisibility(View.GONE)\n                    progressBar.setProgress(0)\n                    swipeRefreshLayout.setRefreshing(false)\n                } else {\n                    // 加载中\n                    progressBar.setVisibility(View.VISIBLE)\n                    progressBar.setProgress(newProgress)\n                }\n            }\n\n            @Override\n            void onReceivedTitle(WebView view, String title) {\n                super.onReceivedTitle(view, title)\n                getActivity()?.setTitle(title)\n            }\n        });\n\n        webView.setWebViewClient(new WebViewClient() {\n\n            @Override\n            boolean shouldOverrideUrlLoading(WebView view, String url) {\n                webView.loadUrl(url)\n                return true\n            }\n        })\n\n        webView.getSettings().setCacheMode(WebSettings.LOAD_CACHE_ELSE_NETWORK);\n        webView.getSettings().setSupportZoom(true)\n        webView.getSettings().setDisplayZoomControls(true)\n\n        swipeRefreshLayout.setOnRefreshListener({\n            webView.reload()\n        })\n    }\n\n    @Override\n    boolean onKeyDown(int keyCode, KeyEvent event) {\n        if (keyCode == KeyEvent.KEYCODE_BACK) {\n            if (webView.canGoBack()) {\n                webView.goBack()//返回上一页面\n                return true\n            } else {\n                getActivity().finish()\n                return true\n            }\n        }\n        return super.onKeyDown(keyCode, event);\n    }\n\n    @Override\n    void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {\n        super.onCreateOptionsMenu(menu, inflater)\n        inflater.inflate(R.menu.menu_web, menu)\n        itemCollect = menu.findItem(R.id.menu_collect)\n        if (DatabaseManager.getInstance().isExist(url)) {\n            itemCollect.setTitle(R.string.cancel_collect)\n        } else {\n            itemCollect.setTitle(R.string.menu_collect)\n        }\n    }\n\n    @Override\n    boolean onOptionsItemSelected(MenuItem item) {\n        switch (item.getItemId()) {\n            case R.id.menu_copy:\n                App.copyUri(Uri.parse(url))\n                App.toast(R.string.success_copy)\n                return true\n            case R.id.menu_open:\n                Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url))\n                startActivity(intent)\n                return true\n            case R.id.menu_collect:\n                collect()\n                return true\n        }\n        return super.onOptionsItemSelected(item)\n    }\n\n    def collect() {\n        if (DatabaseManager.getInstance().isExist(url)) {\n            try {\n                DatabaseManager.getInstance().delete(url)\n                Toast.makeText(getActivity(), R.string.success_uncollect, Toast.LENGTH_SHORT).show()\n                itemCollect.setTitle(R.string.menu_collect)\n            } catch (Exception e) {\n                LogKit.d(\"uncollect\", \"failure\", e)\n                Toast.makeText(getActivity(), R.string.failure_uncollect, Toast.LENGTH_SHORT).show()\n            }\n        } else {\n            try {\n                DatabaseManager.getInstance().insert(new Bookmark(url, title == getString(R.string.app_name) ? webView.getTitle() : title))\n                Toast.makeText(getActivity(), R.string.success_collect, Toast.LENGTH_SHORT).show()\n                itemCollect.setTitle(R.string.cancel_collect)\n            } catch (Exception e) {\n                LogKit.d(\"collect\", \"failure\", e)\n                Toast.makeText(getActivity(), R.string.failure_collect, Toast.LENGTH_SHORT).show()\n            }\n        }\n    }\n\n    static WebFragment newInstance(String url, String title = null) {\n        WebFragment webFragment = new WebFragment()\n        Bundle bundle = new Bundle()\n        bundle.putString(Config.Static.URL, url)\n        bundle.putString(Config.Static.TITLE, title)\n        webFragment.setArguments(bundle)\n        return webFragment\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/weiget/SwipeToRefreshLayout.groovy",
    "content": "package zhou.gank.io.ui.weiget\n\nimport android.content.Context\nimport android.support.v4.widget.SwipeRefreshLayout\nimport android.util.AttributeSet;\nimport groovy.transform.CompileStatic\n\n@CompileStatic\npublic class SwipeToRefreshLayout extends SwipeRefreshLayout{\n\n    SwipeToRefreshLayout(Context context) {\n        super(context)\n    }\n\n    SwipeToRefreshLayout(Context context, AttributeSet attrs) {\n        super(context, attrs)\n    }\n\n    private boolean mMeasured = false;\n    private boolean mPreMeasureRefreshing = false;\n\n    @Override\n    public void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        super.onMeasure(widthMeasureSpec, heightMeasureSpec);\n        if (!mMeasured) {\n            mMeasured = true\n            setRefreshing(mPreMeasureRefreshing)\n        }\n    }\n\n\n    @Override\n    public void setRefreshing(boolean refreshing) {\n        if (mMeasured) {\n            super.setRefreshing(refreshing)\n        } else {\n            mPreMeasureRefreshing = refreshing\n        }\n    }\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/weiget/TouchImageView.java",
    "content": "package zhou.gank.io.ui.weiget;\n\n\n/*\n * TouchImageView.java\n * By: Michael Ortiz\n * Updated By: Patrick Lackemacher\n * Updated By: Babay88\n * Updated By: @ipsilondev\n * Updated By: hank-cp\n * Updated By: singpolyma\n * -------------------\n * Extends Android ImageView to include pinch zooming, panning, fling and double tap zoom.\n */\n\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.res.Configuration;\nimport android.graphics.Bitmap;\nimport android.graphics.Canvas;\nimport android.graphics.Matrix;\nimport android.graphics.PointF;\nimport android.graphics.RectF;\nimport android.graphics.drawable.Drawable;\nimport android.net.Uri;\nimport android.os.Build.VERSION;\nimport android.os.Build.VERSION_CODES;\nimport android.os.Bundle;\nimport android.os.Parcelable;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.GestureDetector;\nimport android.view.MotionEvent;\nimport android.view.ScaleGestureDetector;\nimport android.view.View;\nimport android.view.animation.AccelerateDecelerateInterpolator;\nimport android.widget.ImageView;\nimport android.widget.OverScroller;\nimport android.widget.Scroller;\n\npublic class TouchImageView extends ImageView {\n\n    private static final String DEBUG = \"DEBUG\";\n\n    //\n    // SuperMin and SuperMax multipliers. Determine how much the image can be\n    // zoomed below or above the zoom boundaries, before animating back to the\n    // min/max zoom boundary.\n    //\n    private static final float SUPER_MIN_MULTIPLIER = .75f;\n    private static final float SUPER_MAX_MULTIPLIER = 1.25f;\n\n    //\n    // Scale of image ranges from minScale to maxScale, where minScale == 1\n    // when the image is stretched to fit view.\n    //\n    private float normalizedScale;\n\n    //\n    // Matrix applied to image. MSCALE_X and MSCALE_Y should always be equal.\n    // MTRANS_X and MTRANS_Y are the other values used. prevMatrix is the matrix\n    // saved prior to the screen rotating.\n    //\n    private Matrix matrix, prevMatrix;\n\n    private enum State {NONE, DRAG, ZOOM, FLING, ANIMATE_ZOOM}\n\n    private State state;\n\n    private float minScale;\n    private float maxScale;\n    private float superMinScale;\n    private float superMaxScale;\n    private float[] m;\n\n    private Context context;\n    private Fling fling;\n\n    private ScaleType mScaleType;\n\n    private boolean imageRenderedAtLeastOnce;\n    private boolean onDrawReady;\n\n    private ZoomVariables delayedZoomVariables;\n\n    //\n    // Size of view and previous view size (ie before rotation)\n    //\n    private int viewWidth, viewHeight, prevViewWidth, prevViewHeight;\n\n    //\n    // Size of image when it is stretched to fit view. Before and After rotation.\n    //\n    private float matchViewWidth, matchViewHeight, prevMatchViewWidth, prevMatchViewHeight;\n\n    private ScaleGestureDetector mScaleDetector;\n    private GestureDetector mGestureDetector;\n    private GestureDetector.OnDoubleTapListener doubleTapListener = null;\n    private OnTouchListener userTouchListener = null;\n    private OnTouchImageViewListener touchImageViewListener = null;\n\n    public TouchImageView(Context context) {\n        super(context);\n        sharedConstructing(context);\n    }\n\n    public TouchImageView(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        sharedConstructing(context);\n    }\n\n    public TouchImageView(Context context, AttributeSet attrs, int defStyle) {\n        super(context, attrs, defStyle);\n        sharedConstructing(context);\n    }\n\n    private void sharedConstructing(Context context) {\n        super.setClickable(true);\n        this.context = context;\n        mScaleDetector = new ScaleGestureDetector(context, new ScaleListener());\n        mGestureDetector = new GestureDetector(context, new GestureListener());\n        matrix = new Matrix();\n        prevMatrix = new Matrix();\n        m = new float[9];\n        normalizedScale = 1;\n        if (mScaleType == null) {\n            mScaleType = ScaleType.FIT_CENTER;\n        }\n        minScale = 1;\n        maxScale = 3;\n        superMinScale = SUPER_MIN_MULTIPLIER * minScale;\n        superMaxScale = SUPER_MAX_MULTIPLIER * maxScale;\n        setImageMatrix(matrix);\n        setScaleType(ScaleType.MATRIX);\n        setState(State.NONE);\n        onDrawReady = false;\n        super.setOnTouchListener(new PrivateOnTouchListener());\n    }\n\n    @Override\n    public void setOnTouchListener(OnTouchListener l) {\n        userTouchListener = l;\n    }\n\n    public void setOnTouchImageViewListener(OnTouchImageViewListener l) {\n        touchImageViewListener = l;\n    }\n\n    public void setOnDoubleTapListener(GestureDetector.OnDoubleTapListener l) {\n        doubleTapListener = l;\n    }\n\n    @Override\n    public void setImageResource(int resId) {\n        super.setImageResource(resId);\n        savePreviousImageValues();\n        fitImageToView();\n    }\n\n    @Override\n    public void setImageBitmap(Bitmap bm) {\n        super.setImageBitmap(bm);\n        savePreviousImageValues();\n        fitImageToView();\n    }\n\n    @Override\n    public void setImageDrawable(Drawable drawable) {\n        super.setImageDrawable(drawable);\n        savePreviousImageValues();\n        fitImageToView();\n    }\n\n    @Override\n    public void setImageURI(Uri uri) {\n        super.setImageURI(uri);\n        savePreviousImageValues();\n        fitImageToView();\n    }\n\n    @Override\n    public void setScaleType(ScaleType type) {\n        if (type == ScaleType.FIT_START || type == ScaleType.FIT_END) {\n            throw new UnsupportedOperationException(\"TouchImageView does not support FIT_START or FIT_END\");\n        }\n        if (type == ScaleType.MATRIX) {\n            super.setScaleType(ScaleType.MATRIX);\n\n        } else {\n            mScaleType = type;\n            if (onDrawReady) {\n                //\n                // If the image is already rendered, scaleType has been called programmatically\n                // and the TouchImageView should be updated with the new scaleType.\n                //\n                setZoom(this);\n            }\n        }\n    }\n\n    @Override\n    public ScaleType getScaleType() {\n        return mScaleType;\n    }\n\n    /**\n     * Returns false if image is in initial, unzoomed state. False, otherwise.\n     *\n     * @return true if image is zoomed\n     */\n    public boolean isZoomed() {\n        return normalizedScale != 1;\n    }\n\n    /**\n     * Return a Rect representing the zoomed image.\n     *\n     * @return rect representing zoomed image\n     */\n    public RectF getZoomedRect() {\n        if (mScaleType == ScaleType.FIT_XY) {\n            throw new UnsupportedOperationException(\"getZoomedRect() not supported with FIT_XY\");\n        }\n        PointF topLeft = transformCoordTouchToBitmap(0, 0, true);\n        PointF bottomRight = transformCoordTouchToBitmap(viewWidth, viewHeight, true);\n\n        float w = getDrawable().getIntrinsicWidth();\n        float h = getDrawable().getIntrinsicHeight();\n        return new RectF(topLeft.x / w, topLeft.y / h, bottomRight.x / w, bottomRight.y / h);\n    }\n\n    /**\n     * Save the current matrix and view dimensions\n     * in the prevMatrix and prevView variables.\n     */\n    private void savePreviousImageValues() {\n        if (matrix != null && viewHeight != 0 && viewWidth != 0) {\n            matrix.getValues(m);\n            prevMatrix.setValues(m);\n            prevMatchViewHeight = matchViewHeight;\n            prevMatchViewWidth = matchViewWidth;\n            prevViewHeight = viewHeight;\n            prevViewWidth = viewWidth;\n        }\n    }\n\n    @Override\n    public Parcelable onSaveInstanceState() {\n        Bundle bundle = new Bundle();\n        bundle.putParcelable(\"instanceState\", super.onSaveInstanceState());\n        bundle.putFloat(\"saveScale\", normalizedScale);\n        bundle.putFloat(\"matchViewHeight\", matchViewHeight);\n        bundle.putFloat(\"matchViewWidth\", matchViewWidth);\n        bundle.putInt(\"viewWidth\", viewWidth);\n        bundle.putInt(\"viewHeight\", viewHeight);\n        matrix.getValues(m);\n        bundle.putFloatArray(\"matrix\", m);\n        bundle.putBoolean(\"imageRendered\", imageRenderedAtLeastOnce);\n        return bundle;\n    }\n\n    @Override\n    public void onRestoreInstanceState(Parcelable state) {\n        if (state instanceof Bundle) {\n            Bundle bundle = (Bundle) state;\n            normalizedScale = bundle.getFloat(\"saveScale\");\n            m = bundle.getFloatArray(\"matrix\");\n            prevMatrix.setValues(m);\n            prevMatchViewHeight = bundle.getFloat(\"matchViewHeight\");\n            prevMatchViewWidth = bundle.getFloat(\"matchViewWidth\");\n            prevViewHeight = bundle.getInt(\"viewHeight\");\n            prevViewWidth = bundle.getInt(\"viewWidth\");\n            imageRenderedAtLeastOnce = bundle.getBoolean(\"imageRendered\");\n            super.onRestoreInstanceState(bundle.getParcelable(\"instanceState\"));\n            return;\n        }\n\n        super.onRestoreInstanceState(state);\n    }\n\n    @Override\n    protected void onDraw(Canvas canvas) {\n        onDrawReady = true;\n        imageRenderedAtLeastOnce = true;\n        if (delayedZoomVariables != null) {\n            setZoom(delayedZoomVariables.scale, delayedZoomVariables.focusX, delayedZoomVariables.focusY, delayedZoomVariables.scaleType);\n            delayedZoomVariables = null;\n        }\n        super.onDraw(canvas);\n    }\n\n    @Override\n    public void onConfigurationChanged(Configuration newConfig) {\n        super.onConfigurationChanged(newConfig);\n        savePreviousImageValues();\n    }\n\n    /**\n     * Get the max zoom multiplier.\n     *\n     * @return max zoom multiplier.\n     */\n    public float getMaxZoom() {\n        return maxScale;\n    }\n\n    /**\n     * Set the max zoom multiplier. Default value: 3.\n     *\n     * @param max max zoom multiplier.\n     */\n    public void setMaxZoom(float max) {\n        maxScale = max;\n        superMaxScale = SUPER_MAX_MULTIPLIER * maxScale;\n    }\n\n    /**\n     * Get the min zoom multiplier.\n     *\n     * @return min zoom multiplier.\n     */\n    public float getMinZoom() {\n        return minScale;\n    }\n\n    /**\n     * Get the current zoom. This is the zoom relative to the initial\n     * scale, not the original resource.\n     *\n     * @return current zoom multiplier.\n     */\n    public float getCurrentZoom() {\n        return normalizedScale;\n    }\n\n    /**\n     * Set the min zoom multiplier. Default value: 1.\n     *\n     * @param min min zoom multiplier.\n     */\n    public void setMinZoom(float min) {\n        minScale = min;\n        superMinScale = SUPER_MIN_MULTIPLIER * minScale;\n    }\n\n    /**\n     * Reset zoom and translation to initial state.\n     */\n    public void resetZoom() {\n        normalizedScale = 1;\n        fitImageToView();\n    }\n\n    /**\n     * Set zoom to the specified scale. Image will be centered by default.\n     *\n     * @param scale\n     */\n    public void setZoom(float scale) {\n        setZoom(scale, 0.5f, 0.5f);\n    }\n\n    /**\n     * Set zoom to the specified scale. Image will be centered around the point\n     * (focusX, focusY). These floats range from 0 to 1 and denote the focus point\n     * as a fraction from the left and top of the view. For example, the top left\n     * corner of the image would be (0, 0). And the bottom right corner would be (1, 1).\n     *\n     * @param scale\n     * @param focusX\n     * @param focusY\n     */\n    public void setZoom(float scale, float focusX, float focusY) {\n        setZoom(scale, focusX, focusY, mScaleType);\n    }\n\n    /**\n     * Set zoom to the specified scale. Image will be centered around the point\n     * (focusX, focusY). These floats range from 0 to 1 and denote the focus point\n     * as a fraction from the left and top of the view. For example, the top left\n     * corner of the image would be (0, 0). And the bottom right corner would be (1, 1).\n     *\n     * @param scale\n     * @param focusX\n     * @param focusY\n     * @param scaleType\n     */\n    public void setZoom(float scale, float focusX, float focusY, ScaleType scaleType) {\n        //\n        // setZoom can be called before the image is on the screen, but at this point,\n        // image and view sizes have not yet been calculated in onMeasure. Thus, we should\n        // delay calling setZoom until the view has been measured.\n        //\n        if (!onDrawReady) {\n            delayedZoomVariables = new ZoomVariables(scale, focusX, focusY, scaleType);\n            return;\n        }\n\n        if (scaleType != mScaleType) {\n            setScaleType(scaleType);\n        }\n        resetZoom();\n        scaleImage(scale, viewWidth / 2, viewHeight / 2, true);\n        matrix.getValues(m);\n        m[Matrix.MTRANS_X] = -((focusX * getImageWidth()) - (viewWidth * 0.5f));\n        m[Matrix.MTRANS_Y] = -((focusY * getImageHeight()) - (viewHeight * 0.5f));\n        matrix.setValues(m);\n        fixTrans();\n        setImageMatrix(matrix);\n    }\n\n    /**\n     * Set zoom parameters equal to another TouchImageView. Including scale, position,\n     * and ScaleType.\n     *\n     * @param TouchImageView\n     */\n    public void setZoom(TouchImageView img) {\n        PointF center = img.getScrollPosition();\n        setZoom(img.getCurrentZoom(), center.x, center.y, img.getScaleType());\n    }\n\n    /**\n     * Return the point at the center of the zoomed image. The PointF coordinates range\n     * in value between 0 and 1 and the focus point is denoted as a fraction from the left\n     * and top of the view. For example, the top left corner of the image would be (0, 0).\n     * And the bottom right corner would be (1, 1).\n     *\n     * @return PointF representing the scroll position of the zoomed image.\n     */\n    public PointF getScrollPosition() {\n        Drawable drawable = getDrawable();\n        if (drawable == null) {\n            return null;\n        }\n        int drawableWidth = drawable.getIntrinsicWidth();\n        int drawableHeight = drawable.getIntrinsicHeight();\n\n        PointF point = transformCoordTouchToBitmap(viewWidth / 2, viewHeight / 2, true);\n        point.x /= drawableWidth;\n        point.y /= drawableHeight;\n        return point;\n    }\n\n    /**\n     * Set the focus point of the zoomed image. The focus points are denoted as a fraction from the\n     * left and top of the view. The focus points can range in value between 0 and 1.\n     *\n     * @param focusX\n     * @param focusY\n     */\n    public void setScrollPosition(float focusX, float focusY) {\n        setZoom(normalizedScale, focusX, focusY);\n    }\n\n    /**\n     * Performs boundary checking and fixes the image matrix if it\n     * is out of bounds.\n     */\n    private void fixTrans() {\n        matrix.getValues(m);\n        float transX = m[Matrix.MTRANS_X];\n        float transY = m[Matrix.MTRANS_Y];\n\n        float fixTransX = getFixTrans(transX, viewWidth, getImageWidth());\n        float fixTransY = getFixTrans(transY, viewHeight, getImageHeight());\n\n        if (fixTransX != 0 || fixTransY != 0) {\n            matrix.postTranslate(fixTransX, fixTransY);\n        }\n    }\n\n    /**\n     * When transitioning from zooming from focus to zoom from center (or vice versa)\n     * the image can become unaligned within the view. This is apparent when zooming\n     * quickly. When the content size is less than the view size, the content will often\n     * be centered incorrectly within the view. fixScaleTrans first calls fixTrans() and\n     * then makes sure the image is centered correctly within the view.\n     */\n    private void fixScaleTrans() {\n        fixTrans();\n        matrix.getValues(m);\n        if (getImageWidth() < viewWidth) {\n            m[Matrix.MTRANS_X] = (viewWidth - getImageWidth()) / 2;\n        }\n\n        if (getImageHeight() < viewHeight) {\n            m[Matrix.MTRANS_Y] = (viewHeight - getImageHeight()) / 2;\n        }\n        matrix.setValues(m);\n    }\n\n    private float getFixTrans(float trans, float viewSize, float contentSize) {\n        float minTrans, maxTrans;\n\n        if (contentSize <= viewSize) {\n            minTrans = 0;\n            maxTrans = viewSize - contentSize;\n\n        } else {\n            minTrans = viewSize - contentSize;\n            maxTrans = 0;\n        }\n\n        if (trans < minTrans)\n            return -trans + minTrans;\n        if (trans > maxTrans)\n            return -trans + maxTrans;\n        return 0;\n    }\n\n    private float getFixDragTrans(float delta, float viewSize, float contentSize) {\n        if (contentSize <= viewSize) {\n            return 0;\n        }\n        return delta;\n    }\n\n    private float getImageWidth() {\n        return matchViewWidth * normalizedScale;\n    }\n\n    private float getImageHeight() {\n        return matchViewHeight * normalizedScale;\n    }\n\n    @Override\n    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {\n        Drawable drawable = getDrawable();\n        if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0) {\n            setMeasuredDimension(0, 0);\n            return;\n        }\n\n        int drawableWidth = drawable.getIntrinsicWidth();\n        int drawableHeight = drawable.getIntrinsicHeight();\n        int widthSize = MeasureSpec.getSize(widthMeasureSpec);\n        int widthMode = MeasureSpec.getMode(widthMeasureSpec);\n        int heightSize = MeasureSpec.getSize(heightMeasureSpec);\n        int heightMode = MeasureSpec.getMode(heightMeasureSpec);\n        viewWidth = setViewSize(widthMode, widthSize, drawableWidth);\n        viewHeight = setViewSize(heightMode, heightSize, drawableHeight);\n\n        //\n        // Set view dimensions\n        //\n        setMeasuredDimension(viewWidth, viewHeight);\n\n        //\n        // Fit content within view\n        //\n        fitImageToView();\n    }\n\n    /**\n     * If the normalizedScale is equal to 1, then the image is made to fit the screen. Otherwise,\n     * it is made to fit the screen according to the dimensions of the previous image matrix. This\n     * allows the image to maintain its zoom after rotation.\n     */\n    private void fitImageToView() {\n        Drawable drawable = getDrawable();\n        if (drawable == null || drawable.getIntrinsicWidth() == 0 || drawable.getIntrinsicHeight() == 0) {\n            return;\n        }\n        if (matrix == null || prevMatrix == null) {\n            return;\n        }\n\n        int drawableWidth = drawable.getIntrinsicWidth();\n        int drawableHeight = drawable.getIntrinsicHeight();\n\n        //\n        // Scale image for view\n        //\n        float scaleX = (float) viewWidth / drawableWidth;\n        float scaleY = (float) viewHeight / drawableHeight;\n\n        switch (mScaleType) {\n            case CENTER:\n                scaleX = scaleY = 1;\n                break;\n\n            case CENTER_CROP:\n                scaleX = scaleY = Math.max(scaleX, scaleY);\n                break;\n\n            case CENTER_INSIDE:\n                scaleX = scaleY = Math.min(1, Math.min(scaleX, scaleY));\n\n            case FIT_CENTER:\n                scaleX = scaleY = Math.min(scaleX, scaleY);\n                break;\n\n            case FIT_XY:\n                break;\n\n            default:\n                //\n                // FIT_START and FIT_END not supported\n                //\n                throw new UnsupportedOperationException(\"TouchImageView does not support FIT_START or FIT_END\");\n\n        }\n\n        //\n        // Center the image\n        //\n        float redundantXSpace = viewWidth - (scaleX * drawableWidth);\n        float redundantYSpace = viewHeight - (scaleY * drawableHeight);\n        matchViewWidth = viewWidth - redundantXSpace;\n        matchViewHeight = viewHeight - redundantYSpace;\n        if (!isZoomed() && !imageRenderedAtLeastOnce) {\n            //\n            // Stretch and center image to fit view\n            //\n            matrix.setScale(scaleX, scaleY);\n            matrix.postTranslate(redundantXSpace / 2, redundantYSpace / 2);\n            normalizedScale = 1;\n\n        } else {\n            //\n            // These values should never be 0 or we will set viewWidth and viewHeight\n            // to NaN in translateMatrixAfterRotate. To avoid this, call savePreviousImageValues\n            // to set them equal to the current values.\n            //\n            if (prevMatchViewWidth == 0 || prevMatchViewHeight == 0) {\n                savePreviousImageValues();\n            }\n\n            prevMatrix.getValues(m);\n\n            //\n            // Rescale Matrix after rotation\n            //\n            m[Matrix.MSCALE_X] = matchViewWidth / drawableWidth * normalizedScale;\n            m[Matrix.MSCALE_Y] = matchViewHeight / drawableHeight * normalizedScale;\n\n            //\n            // TransX and TransY from previous matrix\n            //\n            float transX = m[Matrix.MTRANS_X];\n            float transY = m[Matrix.MTRANS_Y];\n\n            //\n            // Width\n            //\n            float prevActualWidth = prevMatchViewWidth * normalizedScale;\n            float actualWidth = getImageWidth();\n            translateMatrixAfterRotate(Matrix.MTRANS_X, transX, prevActualWidth, actualWidth, prevViewWidth, viewWidth, drawableWidth);\n\n            //\n            // Height\n            //\n            float prevActualHeight = prevMatchViewHeight * normalizedScale;\n            float actualHeight = getImageHeight();\n            translateMatrixAfterRotate(Matrix.MTRANS_Y, transY, prevActualHeight, actualHeight, prevViewHeight, viewHeight, drawableHeight);\n\n            //\n            // Set the matrix to the adjusted scale and translate values.\n            //\n            matrix.setValues(m);\n        }\n        fixTrans();\n        setImageMatrix(matrix);\n    }\n\n    /**\n     * Set view dimensions based on layout params\n     *\n     * @param mode\n     * @param size\n     * @param drawableWidth\n     * @return\n     */\n    private int setViewSize(int mode, int size, int drawableWidth) {\n        int viewSize;\n        switch (mode) {\n            case MeasureSpec.EXACTLY:\n                viewSize = size;\n                break;\n\n            case MeasureSpec.AT_MOST:\n                viewSize = Math.min(drawableWidth, size);\n                break;\n\n            case MeasureSpec.UNSPECIFIED:\n                viewSize = drawableWidth;\n                break;\n\n            default:\n                viewSize = size;\n                break;\n        }\n        return viewSize;\n    }\n\n    /**\n     * After rotating, the matrix needs to be translated. This function finds the area of image\n     * which was previously centered and adjusts translations so that is again the center, post-rotation.\n     *\n     * @param axis          Matrix.MTRANS_X or Matrix.MTRANS_Y\n     * @param trans         the value of trans in that axis before the rotation\n     * @param prevImageSize the width/height of the image before the rotation\n     * @param imageSize     width/height of the image after rotation\n     * @param prevViewSize  width/height of view before rotation\n     * @param viewSize      width/height of view after rotation\n     * @param drawableSize  width/height of drawable\n     */\n    private void translateMatrixAfterRotate(int axis, float trans, float prevImageSize, float imageSize, int prevViewSize, int viewSize, int drawableSize) {\n        if (imageSize < viewSize) {\n            //\n            // The width/height of image is less than the view's width/height. Center it.\n            //\n            m[axis] = (viewSize - (drawableSize * m[Matrix.MSCALE_X])) * 0.5f;\n\n        } else if (trans > 0) {\n            //\n            // The image is larger than the view, but was not before rotation. Center it.\n            //\n            m[axis] = -((imageSize - viewSize) * 0.5f);\n\n        } else {\n            //\n            // Find the area of the image which was previously centered in the view. Determine its distance\n            // from the left/top side of the view as a fraction of the entire image's width/height. Use that percentage\n            // to calculate the trans in the new view width/height.\n            //\n            float percentage = (Math.abs(trans) + (0.5f * prevViewSize)) / prevImageSize;\n            m[axis] = -((percentage * imageSize) - (viewSize * 0.5f));\n        }\n    }\n\n    private void setState(State state) {\n        this.state = state;\n    }\n\n    public boolean canScrollHorizontallyFroyo(int direction) {\n        return canScrollHorizontally(direction);\n    }\n\n    @Override\n    public boolean canScrollHorizontally(int direction) {\n        matrix.getValues(m);\n        float x = m[Matrix.MTRANS_X];\n\n        if (getImageWidth() < viewWidth) {\n            return false;\n\n        } else if (x >= -1 && direction < 0) {\n            return false;\n\n        } else if (Math.abs(x) + viewWidth + 1 >= getImageWidth() && direction > 0) {\n            return false;\n        }\n\n        return true;\n    }\n\n    /**\n     * Gesture Listener detects a single click or long click and passes that on\n     * to the view's listener.\n     *\n     * @author Ortiz\n     */\n    private class GestureListener extends GestureDetector.SimpleOnGestureListener {\n\n        @Override\n        public boolean onSingleTapConfirmed(MotionEvent e) {\n            if (doubleTapListener != null) {\n                return doubleTapListener.onSingleTapConfirmed(e);\n            }\n            return performClick();\n        }\n\n        @Override\n        public void onLongPress(MotionEvent e) {\n            performLongClick();\n        }\n\n        @Override\n        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {\n            if (fling != null) {\n                //\n                // If a previous fling is still active, it should be cancelled so that two flings\n                // are not run simultaenously.\n                //\n                fling.cancelFling();\n            }\n            fling = new Fling((int) velocityX, (int) velocityY);\n            compatPostOnAnimation(fling);\n            return super.onFling(e1, e2, velocityX, velocityY);\n        }\n\n        @Override\n        public boolean onDoubleTap(MotionEvent e) {\n            boolean consumed = false;\n            if (doubleTapListener != null) {\n                consumed = doubleTapListener.onDoubleTap(e);\n            }\n            if (state == State.NONE) {\n                float targetZoom = (normalizedScale == minScale) ? maxScale : minScale;\n                DoubleTapZoom doubleTap = new DoubleTapZoom(targetZoom, e.getX(), e.getY(), false);\n                compatPostOnAnimation(doubleTap);\n                consumed = true;\n            }\n            return consumed;\n        }\n\n        @Override\n        public boolean onDoubleTapEvent(MotionEvent e) {\n            return doubleTapListener != null && doubleTapListener.onDoubleTapEvent(e);\n        }\n    }\n\n    public interface OnTouchImageViewListener {\n        public void onMove();\n    }\n\n    /**\n     * Responsible for all touch events. Handles the heavy lifting of drag and also sends\n     * touch events to Scale Detector and Gesture Detector.\n     *\n     * @author Ortiz\n     */\n    private class PrivateOnTouchListener implements OnTouchListener {\n\n        //\n        // Remember last point position for dragging\n        //\n        private PointF last = new PointF();\n\n        @Override\n        public boolean onTouch(View v, MotionEvent event) {\n            mScaleDetector.onTouchEvent(event);\n            mGestureDetector.onTouchEvent(event);\n            PointF curr = new PointF(event.getX(), event.getY());\n\n            if (state == State.NONE || state == State.DRAG || state == State.FLING) {\n                switch (event.getAction()) {\n                    case MotionEvent.ACTION_DOWN:\n                        last.set(curr);\n                        if (fling != null)\n                            fling.cancelFling();\n                        setState(State.DRAG);\n                        break;\n\n                    case MotionEvent.ACTION_MOVE:\n                        if (state == State.DRAG) {\n                            float deltaX = curr.x - last.x;\n                            float deltaY = curr.y - last.y;\n                            float fixTransX = getFixDragTrans(deltaX, viewWidth, getImageWidth());\n                            float fixTransY = getFixDragTrans(deltaY, viewHeight, getImageHeight());\n                            matrix.postTranslate(fixTransX, fixTransY);\n                            fixTrans();\n                            last.set(curr.x, curr.y);\n                        }\n                        break;\n\n                    case MotionEvent.ACTION_UP:\n                    case MotionEvent.ACTION_POINTER_UP:\n                        setState(State.NONE);\n                        break;\n                }\n            }\n\n            setImageMatrix(matrix);\n\n            //\n            // User-defined OnTouchListener\n            //\n            if (userTouchListener != null) {\n                userTouchListener.onTouch(v, event);\n            }\n\n            //\n            // OnTouchImageViewListener is set: TouchImageView dragged by user.\n            //\n            if (touchImageViewListener != null) {\n                touchImageViewListener.onMove();\n            }\n\n            //\n            // indicate event was handled\n            //\n            return true;\n        }\n    }\n\n    /**\n     * ScaleListener detects user two finger scaling and scales image.\n     *\n     * @author Ortiz\n     */\n    private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {\n        @Override\n        public boolean onScaleBegin(ScaleGestureDetector detector) {\n            setState(State.ZOOM);\n            return true;\n        }\n\n        @Override\n        public boolean onScale(ScaleGestureDetector detector) {\n            scaleImage(detector.getScaleFactor(), detector.getFocusX(), detector.getFocusY(), true);\n\n            //\n            // OnTouchImageViewListener is set: TouchImageView pinch zoomed by user.\n            //\n            if (touchImageViewListener != null) {\n                touchImageViewListener.onMove();\n            }\n            return true;\n        }\n\n        @Override\n        public void onScaleEnd(ScaleGestureDetector detector) {\n            super.onScaleEnd(detector);\n            setState(State.NONE);\n            boolean animateToZoomBoundary = false;\n            float targetZoom = normalizedScale;\n            if (normalizedScale > maxScale) {\n                targetZoom = maxScale;\n                animateToZoomBoundary = true;\n\n            } else if (normalizedScale < minScale) {\n                targetZoom = minScale;\n                animateToZoomBoundary = true;\n            }\n\n            if (animateToZoomBoundary) {\n                DoubleTapZoom doubleTap = new DoubleTapZoom(targetZoom, viewWidth / 2, viewHeight / 2, true);\n                compatPostOnAnimation(doubleTap);\n            }\n        }\n    }\n\n    private void scaleImage(double deltaScale, float focusX, float focusY, boolean stretchImageToSuper) {\n\n        float lowerScale, upperScale;\n        if (stretchImageToSuper) {\n            lowerScale = superMinScale;\n            upperScale = superMaxScale;\n\n        } else {\n            lowerScale = minScale;\n            upperScale = maxScale;\n        }\n\n        float origScale = normalizedScale;\n        normalizedScale *= deltaScale;\n        if (normalizedScale > upperScale) {\n            normalizedScale = upperScale;\n            deltaScale = upperScale / origScale;\n        } else if (normalizedScale < lowerScale) {\n            normalizedScale = lowerScale;\n            deltaScale = lowerScale / origScale;\n        }\n\n        matrix.postScale((float) deltaScale, (float) deltaScale, focusX, focusY);\n        fixScaleTrans();\n    }\n\n    /**\n     * DoubleTapZoom calls a series of runnables which apply\n     * an animated zoom in/out graphic to the image.\n     *\n     * @author Ortiz\n     */\n    private class DoubleTapZoom implements Runnable {\n\n        private long startTime;\n        private static final float ZOOM_TIME = 500;\n        private float startZoom, targetZoom;\n        private float bitmapX, bitmapY;\n        private boolean stretchImageToSuper;\n        private AccelerateDecelerateInterpolator interpolator = new AccelerateDecelerateInterpolator();\n        private PointF startTouch;\n        private PointF endTouch;\n\n        DoubleTapZoom(float targetZoom, float focusX, float focusY, boolean stretchImageToSuper) {\n            setState(State.ANIMATE_ZOOM);\n            startTime = System.currentTimeMillis();\n            this.startZoom = normalizedScale;\n            this.targetZoom = targetZoom;\n            this.stretchImageToSuper = stretchImageToSuper;\n            PointF bitmapPoint = transformCoordTouchToBitmap(focusX, focusY, false);\n            this.bitmapX = bitmapPoint.x;\n            this.bitmapY = bitmapPoint.y;\n\n            //\n            // Used for translating image during scaling\n            //\n            startTouch = transformCoordBitmapToTouch(bitmapX, bitmapY);\n            endTouch = new PointF(viewWidth / 2, viewHeight / 2);\n        }\n\n        @Override\n        public void run() {\n            float t = interpolate();\n            double deltaScale = calculateDeltaScale(t);\n            scaleImage(deltaScale, bitmapX, bitmapY, stretchImageToSuper);\n            translateImageToCenterTouchPosition(t);\n            fixScaleTrans();\n            setImageMatrix(matrix);\n\n            //\n            // OnTouchImageViewListener is set: double tap runnable updates listener\n            // with every frame.\n            //\n            if (touchImageViewListener != null) {\n                touchImageViewListener.onMove();\n            }\n\n            if (t < 1f) {\n                //\n                // We haven't finished zooming\n                //\n                compatPostOnAnimation(this);\n\n            } else {\n                //\n                // Finished zooming\n                //\n                setState(State.NONE);\n            }\n        }\n\n        /**\n         * Interpolate between where the image should start and end in order to translate\n         * the image so that the point that is touched is what ends up centered at the end\n         * of the zoom.\n         *\n         * @param t\n         */\n        private void translateImageToCenterTouchPosition(float t) {\n            float targetX = startTouch.x + t * (endTouch.x - startTouch.x);\n            float targetY = startTouch.y + t * (endTouch.y - startTouch.y);\n            PointF curr = transformCoordBitmapToTouch(bitmapX, bitmapY);\n            matrix.postTranslate(targetX - curr.x, targetY - curr.y);\n        }\n\n        /**\n         * Use interpolator to get t\n         *\n         * @return\n         */\n        private float interpolate() {\n            long currTime = System.currentTimeMillis();\n            float elapsed = (currTime - startTime) / ZOOM_TIME;\n            elapsed = Math.min(1f, elapsed);\n            return interpolator.getInterpolation(elapsed);\n        }\n\n        /**\n         * Interpolate the current targeted zoom and get the delta\n         * from the current zoom.\n         *\n         * @param t\n         * @return\n         */\n        private double calculateDeltaScale(float t) {\n            double zoom = startZoom + t * (targetZoom - startZoom);\n            return zoom / normalizedScale;\n        }\n    }\n\n    /**\n     * This function will transform the coordinates in the touch event to the coordinate\n     * system of the drawable that the imageview contain\n     *\n     * @param x            x-coordinate of touch event\n     * @param y            y-coordinate of touch event\n     * @param clipToBitmap Touch event may occur within view, but outside image content. True, to clip return value\n     *                     to the bounds of the bitmap size.\n     * @return Coordinates of the point touched, in the coordinate system of the original drawable.\n     */\n    private PointF transformCoordTouchToBitmap(float x, float y, boolean clipToBitmap) {\n        matrix.getValues(m);\n        float origW = getDrawable().getIntrinsicWidth();\n        float origH = getDrawable().getIntrinsicHeight();\n        float transX = m[Matrix.MTRANS_X];\n        float transY = m[Matrix.MTRANS_Y];\n        float finalX = ((x - transX) * origW) / getImageWidth();\n        float finalY = ((y - transY) * origH) / getImageHeight();\n\n        if (clipToBitmap) {\n            finalX = Math.min(Math.max(finalX, 0), origW);\n            finalY = Math.min(Math.max(finalY, 0), origH);\n        }\n\n        return new PointF(finalX, finalY);\n    }\n\n    /**\n     * Inverse of transformCoordTouchToBitmap. This function will transform the coordinates in the\n     * drawable's coordinate system to the view's coordinate system.\n     *\n     * @param bx x-coordinate in original bitmap coordinate system\n     * @param by y-coordinate in original bitmap coordinate system\n     * @return Coordinates of the point in the view's coordinate system.\n     */\n    private PointF transformCoordBitmapToTouch(float bx, float by) {\n        matrix.getValues(m);\n        float origW = getDrawable().getIntrinsicWidth();\n        float origH = getDrawable().getIntrinsicHeight();\n        float px = bx / origW;\n        float py = by / origH;\n        float finalX = m[Matrix.MTRANS_X] + getImageWidth() * px;\n        float finalY = m[Matrix.MTRANS_Y] + getImageHeight() * py;\n        return new PointF(finalX, finalY);\n    }\n\n    /**\n     * Fling launches sequential runnables which apply\n     * the fling graphic to the image. The values for the translation\n     * are interpolated by the Scroller.\n     *\n     * @author Ortiz\n     */\n    private class Fling implements Runnable {\n\n        CompatScroller scroller;\n        int currX, currY;\n\n        Fling(int velocityX, int velocityY) {\n            setState(State.FLING);\n            scroller = new CompatScroller(context);\n            matrix.getValues(m);\n\n            int startX = (int) m[Matrix.MTRANS_X];\n            int startY = (int) m[Matrix.MTRANS_Y];\n            int minX, maxX, minY, maxY;\n\n            if (getImageWidth() > viewWidth) {\n                minX = viewWidth - (int) getImageWidth();\n                maxX = 0;\n\n            } else {\n                minX = maxX = startX;\n            }\n\n            if (getImageHeight() > viewHeight) {\n                minY = viewHeight - (int) getImageHeight();\n                maxY = 0;\n\n            } else {\n                minY = maxY = startY;\n            }\n\n            scroller.fling(startX, startY, (int) velocityX, (int) velocityY, minX,\n                    maxX, minY, maxY);\n            currX = startX;\n            currY = startY;\n        }\n\n        public void cancelFling() {\n            if (scroller != null) {\n                setState(State.NONE);\n                scroller.forceFinished(true);\n            }\n        }\n\n        @Override\n        public void run() {\n\n            //\n            // OnTouchImageViewListener is set: TouchImageView listener has been flung by user.\n            // Listener runnable updated with each frame of fling animation.\n            //\n            if (touchImageViewListener != null) {\n                touchImageViewListener.onMove();\n            }\n\n            if (scroller.isFinished()) {\n                scroller = null;\n                return;\n            }\n\n            if (scroller.computeScrollOffset()) {\n                int newX = scroller.getCurrX();\n                int newY = scroller.getCurrY();\n                int transX = newX - currX;\n                int transY = newY - currY;\n                currX = newX;\n                currY = newY;\n                matrix.postTranslate(transX, transY);\n                fixTrans();\n                setImageMatrix(matrix);\n                compatPostOnAnimation(this);\n            }\n        }\n    }\n\n    @TargetApi(VERSION_CODES.GINGERBREAD)\n    private class CompatScroller {\n        Scroller scroller;\n        OverScroller overScroller;\n        boolean isPreGingerbread;\n\n        public CompatScroller(Context context) {\n            if (VERSION.SDK_INT < VERSION_CODES.GINGERBREAD) {\n                isPreGingerbread = true;\n                scroller = new Scroller(context);\n\n            } else {\n                isPreGingerbread = false;\n                overScroller = new OverScroller(context);\n            }\n        }\n\n        public void fling(int startX, int startY, int velocityX, int velocityY, int minX, int maxX, int minY, int maxY) {\n            if (isPreGingerbread) {\n                scroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);\n            } else {\n                overScroller.fling(startX, startY, velocityX, velocityY, minX, maxX, minY, maxY);\n            }\n        }\n\n        public void forceFinished(boolean finished) {\n            if (isPreGingerbread) {\n                scroller.forceFinished(finished);\n            } else {\n                overScroller.forceFinished(finished);\n            }\n        }\n\n        public boolean isFinished() {\n            if (isPreGingerbread) {\n                return scroller.isFinished();\n            } else {\n                return overScroller.isFinished();\n            }\n        }\n\n        public boolean computeScrollOffset() {\n            if (isPreGingerbread) {\n                return scroller.computeScrollOffset();\n            } else {\n                overScroller.computeScrollOffset();\n                return overScroller.computeScrollOffset();\n            }\n        }\n\n        public int getCurrX() {\n            if (isPreGingerbread) {\n                return scroller.getCurrX();\n            } else {\n                return overScroller.getCurrX();\n            }\n        }\n\n        public int getCurrY() {\n            if (isPreGingerbread) {\n                return scroller.getCurrY();\n            } else {\n                return overScroller.getCurrY();\n            }\n        }\n    }\n\n    @TargetApi(VERSION_CODES.JELLY_BEAN)\n    private void compatPostOnAnimation(Runnable runnable) {\n        if (VERSION.SDK_INT >= VERSION_CODES.JELLY_BEAN) {\n            postOnAnimation(runnable);\n\n        } else {\n            postDelayed(runnable, 1000 / 60);\n        }\n    }\n\n    private class ZoomVariables {\n        public float scale;\n        public float focusX;\n        public float focusY;\n        public ScaleType scaleType;\n\n        public ZoomVariables(float scale, float focusX, float focusY, ScaleType scaleType) {\n            this.scale = scale;\n            this.focusX = focusX;\n            this.focusY = focusY;\n            this.scaleType = scaleType;\n        }\n    }\n\n    private void printMatrixInfo() {\n        float[] n = new float[9];\n        matrix.getValues(n);\n        Log.d(DEBUG, \"Scale: \" + n[Matrix.MSCALE_X] + \" TransX: \" + n[Matrix.MTRANS_X] + \" TransY: \" + n[Matrix.MTRANS_Y]);\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/ui/weiget/URLSpanNoUnderline.groovy",
    "content": "package zhou.gank.io.ui.weiget\n\nimport android.content.Intent\nimport android.net.Uri\nimport android.os.Parcel\nimport android.support.annotation.NonNull\nimport android.text.SpannableStringBuilder\nimport android.text.TextPaint\nimport android.text.style.URLSpan\nimport android.view.View\nimport android.widget.TextView\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.R\nimport zhou.gank.io.comment.Config\nimport zhou.gank.io.ui.activity.WebActivity\nimport zhou.gank.io.util.LogKit;\n\n@CompileStatic\nclass URLSpanNoUnderline extends URLSpan {\n    URLSpanNoUnderline(String url) {\n        super(url)\n    }\n\n    URLSpanNoUnderline(Parcel src) {\n        super(src)\n    }\n\n    @Override\n    public void updateDrawState(@NonNull TextPaint ds) {\n        super.updateDrawState(ds);\n        ds.setUnderlineText(false);\n    }\n\n    @Override\n    void onClick(View widget) {\n        def open = Config.getBoolean(widget.getResources().getString(R.string.key_open), Config.Configurable.HANDLE_BY_ME);\n        if (open) {\n            Intent intent = new Intent(widget.getContext(), WebActivity.class)\n            intent.putExtra(Config.Static.URL, getURL())\n            widget.getContext().startActivity(intent)\n        } else {\n            super.onClick(widget)\n        }\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/FileKit.java",
    "content": "package zhou.gank.io.util;\n\nimport android.graphics.Bitmap;\nimport android.util.Log;\n\nimport java.io.BufferedOutputStream;\nimport java.io.BufferedReader;\nimport java.io.BufferedWriter;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileNotFoundException;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.io.OutputStreamWriter;\nimport java.text.DecimalFormat;\n\n/**\n * Created by 州 on 2015/7/4 0004.\n * 文件操作相关工具类\n */\npublic class FileKit {\n\n    public static DecimalFormat decimalFormat = new DecimalFormat(\".00\");\n\n    /**\n     * 判断文件是否存在\n     *\n     * @param path 文件的全路径\n     * @return 文件是否存在\n     */\n    @SuppressWarnings(\"unused\")\n    public static boolean isFileExists(String path) {\n        File file = new File(path);\n        return file.exists();\n    }\n\n    @SuppressWarnings(\"unused\")\n    public static boolean isFileExists(File parent, String name) {\n        File file = new File(parent, name);\n        return file.exists();\n    }\n\n    /**\n     * 获取文件的后缀名\n     *\n     * @param path 文件全路径\n     * @return 后缀名\n     */\n    @SuppressWarnings(\"unused\")\n    public static String getFileExtension(String path) {\n        return path == null ? null : path.substring(path.lastIndexOf(\".\") + 1);\n    }\n\n    /**\n     * 去掉路径的后缀名\n     *\n     * @param path 文件全路径\n     * @return 去后缀名后的文件名\n     */\n    @SuppressWarnings(\"unused\")\n    public static String getPathWithoutExtension(String path) {\n        return path == null ? null : path.substring(0, path.lastIndexOf(\".\"));\n    }\n\n    /**\n     * 将对象写入指定路径的文件中\n     *\n     * @param path 文件路径\n     * @param obj  需要被写入的对象\n     */\n    @SuppressWarnings(\"unused\")\n    public static void writeObject(String path, Object obj) {\n        File file = new File(path);\n        writeObject(file, obj);\n    }\n\n    /**\n     * 写入对象到文件中\n     *\n     * @param file 文件对象\n     * @param obj  需要写入文件的对象\n     */\n    @SuppressWarnings(\"unused\")\n    public static void writeObject(File file, Object obj) {\n        if (null == file || obj == null) {\n            return;\n        }\n        FileOutputStream fileOutputStream = null;\n        ObjectOutputStream objectOutputStream = null;\n\n        try {\n            fileOutputStream = new FileOutputStream(file);\n            objectOutputStream = new ObjectOutputStream(fileOutputStream);\n\n            objectOutputStream.writeObject(obj);\n            objectOutputStream.flush();\n        } catch (IOException e) {\n            Log.d(\"writeObject\", e.getMessage());\n        } finally {\n            try {\n                if (objectOutputStream != null) {\n                    objectOutputStream.close();\n                }\n                if (fileOutputStream != null) {\n                    fileOutputStream.close();\n                }\n            } catch (IOException e) {\n                Log.d(\"writeObject\", e.getMessage());\n            }\n        }\n    }\n\n    /**\n     * 从指定路径的文件中读取对象\n     *\n     * @param path 文件路径\n     * @return 读取到的对象\n     */\n    @SuppressWarnings(\"unused\")\n    public static Object readObject(String path) {\n        File file = new File(path);\n        return readObject(file);\n    }\n\n    /**\n     * 从文件中读取对象\n     *\n     * @param file 文件对象\n     * @return 读取到的对象\n     */\n    public static Object readObject(File file) {\n        Object obj = null;\n        if (file != null && file.exists()) {\n            FileInputStream fileInputStream = null;\n            ObjectInputStream objectInputStream = null;\n\n            try {\n                fileInputStream = new FileInputStream(file);\n                objectInputStream = new ObjectInputStream(fileInputStream);\n\n                obj = objectInputStream.readObject();\n            } catch (IOException | ClassNotFoundException e) {\n                Log.d(\"readObject\", e.getMessage());\n            } finally {\n                try {\n                    if (objectInputStream != null) {\n                        objectInputStream.close();\n                    }\n                    if (fileInputStream != null) {\n                        fileInputStream.close();\n                    }\n                } catch (IOException e) {\n                    Log.d(\"readObject\", e.getMessage());\n                }\n\n            }\n        }\n        return obj;\n    }\n\n    public static void writeString(File file, String content) {\n        FileOutputStream fileOutputStream = null;\n        OutputStreamWriter outputStreamWriter = null;\n        BufferedWriter bufferedWriter = null;\n\n        try {\n            fileOutputStream = new FileOutputStream(file);\n            outputStreamWriter = new OutputStreamWriter(fileOutputStream);\n            bufferedWriter = new BufferedWriter(outputStreamWriter);\n\n            bufferedWriter.write(content);\n\n        } catch (IOException e) {\n            Log.d(\"writeString\", \"error\", e);\n        } finally {\n            try {\n                if (bufferedWriter != null) {\n                    bufferedWriter.close();\n                }\n                if (outputStreamWriter != null) {\n                    outputStreamWriter.close();\n                }\n                if (fileOutputStream != null) {\n                    fileOutputStream.close();\n                }\n            } catch (IOException e) {\n                Log.d(\"writeString\", \"error final\", e);\n            }\n        }\n    }\n\n    public static String readString(File file) {\n        FileInputStream fileInputStream = null;\n        InputStreamReader inputStreamReader = null;\n        BufferedReader bufferedReader = null;\n\n        String content = null;\n\n        try {\n            fileInputStream = new FileInputStream(file);\n            inputStreamReader = new InputStreamReader(fileInputStream);\n            bufferedReader = new BufferedReader(inputStreamReader);\n\n            String line;\n            StringBuilder sb = new StringBuilder();\n            while ((line = bufferedReader.readLine()) != null) {\n                sb.append(line).append(\"\\n\");\n            }\n            sb.deleteCharAt(sb.length() - 1);\n            content = sb.toString();\n        } catch (FileNotFoundException e) {\n            Log.d(\"readString\", \"error\", e);\n        } catch (IOException e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                if (bufferedReader != null) {\n                    bufferedReader.close();\n                }\n                if (inputStreamReader != null) {\n                    inputStreamReader.close();\n                }\n                if (fileInputStream != null) {\n                    fileInputStream.close();\n                }\n            } catch (IOException e) {\n                Log.d(\"readString\", \"error final\", e);\n            }\n        }\n        return content;\n    }\n\n    /**\n     * 格式化文件大小以字符串输出\n     *\n     * @param size 大小\n     * @return B、KB、MB类型的字符串\n     */\n    @SuppressWarnings(\"unused\")\n    public static String formatSize(int size) {\n        if (size < 1024 * 0.6) {\n            return size + \"B\";\n        } else if (size < 1024 * 1024 * 0.6) {\n            return decimalFormat.format((float) size / 1024) + \"KB\";\n        } else {\n            return decimalFormat.format((float) size / (1024 * 1024)) + \"MB\";\n        }\n    }\n\n    public static void saveBitmapFile(Bitmap bitmap, File file) {\n        FileOutputStream fileOutputStream = null;\n        BufferedOutputStream bufferedOutputStream = null;\n        try {\n            fileOutputStream = new FileOutputStream(file);\n            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);\n            bitmap.compress(Bitmap.CompressFormat.JPEG, 100, bufferedOutputStream);\n            bufferedOutputStream.flush();\n            bufferedOutputStream.close();\n        } catch (IOException e) {\n            LogKit.d(\"saveBitmapFile\", \"error\", e);\n        } finally {\n            try {\n                if (bufferedOutputStream != null) {\n                    bufferedOutputStream.close();\n                }\n                if (fileOutputStream != null) {\n                    fileOutputStream.close();\n                }\n            } catch (IOException e) {\n                LogKit.d(\"saveBitmapFile\", \"error\", e);\n            }\n        }\n    }\n\n    public static String getFileRealName(String path) {\n        return path.substring(path.lastIndexOf(\"/\") + 1);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/HashKit.java",
    "content": "package zhou.gank.io.util;\n\nimport java.security.MessageDigest;\n\n/**\n * Created by zzhoujay on 2015/7/31 0031.\n * 加密相关工具类\n */\npublic class HashKit {\n\n    private static java.security.SecureRandom random = new java.security.SecureRandom();\n\n    public static String md5(String srcStr){\n        return hash(\"MD5\", srcStr);\n    }\n\n    public static String sha1(String srcStr){\n        return hash(\"SHA-1\", srcStr);\n    }\n\n    public static String sha256(String srcStr){\n        return hash(\"SHA-256\", srcStr);\n    }\n\n    public static String sha384(String srcStr){\n        return hash(\"SHA-384\", srcStr);\n    }\n\n    public static String sha512(String srcStr){\n        return hash(\"SHA-512\", srcStr);\n    }\n\n    public static String hash(String algorithm, String srcStr) {\n        try {\n            StringBuilder result = new StringBuilder();\n            MessageDigest md = MessageDigest.getInstance(algorithm);\n            byte[] bytes = md.digest(srcStr.getBytes(\"utf-8\"));\n            for (byte b : bytes) {\n                String hex = Integer.toHexString(b&0xFF);\n                if (hex.length() == 1)\n                    result.append(\"0\");\n                result.append(hex);\n            }\n            return result.toString();\n        }\n        catch (Exception e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    private static String toHex(byte[] bytes) {\n        StringBuilder result = new StringBuilder();\n        for (byte b : bytes) {\n            String hex = Integer.toHexString(b&0xFF);\n            if (hex.length() == 1)\n                result.append(\"0\");\n            result.append(hex);\n        }\n        return result.toString();\n    }\n\n    /**\n     * md5 128bit 16bytes\n     * sha1 160bit 20bytes\n     * sha256 256bit 32bytes\n     * sha384 384bit 48bites\n     * sha512 512bit 64bites\n     */\n    public static String generateSalt(int numberOfBytes) {\n        byte[] salt = new byte[numberOfBytes];\n        random.nextBytes(salt);\n        return toHex(salt);\n    }\n}\n"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/JsonKit.groovy",
    "content": "package zhou.gank.io.util\n\nimport com.google.gson.Gson\nimport com.google.gson.JsonArray\nimport com.google.gson.JsonElement\nimport com.google.gson.JsonObject\nimport com.google.gson.JsonParser\nimport com.google.gson.reflect.TypeToken\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.model.GankDaily\nimport zhou.gank.io.model.ResultDaily\n\n@CompileStatic\nclass JsonKit {\n\n    public static ResultDaily generate(String json, Gson gson) {\n        JsonParser parser = new JsonParser();\n        JsonElement element = parser.parse(json);\n        JsonObject root = element.getAsJsonObject();\n        JsonArray category = root.getAsJsonArray(\"category\");\n        Iterator<JsonElement> iterator = category.iterator();\n        JsonObject results = root.getAsJsonObject(\"results\");\n        boolean error = root.get(\"error\").getAsBoolean();\n        ArrayList<String> types = new ArrayList<>(category.size());\n        ArrayList<List<Gank>> ghs = new ArrayList<>(category.size());\n        while (iterator.hasNext()) {\n            JsonElement type = iterator.next();\n            String t = type.getAsString();\n            types.add(t);\n            String e = results.get(t).toString();\n            ghs.add(gson.fromJson(e, new TypeToken<List<Gank>>() {\n            }.getType()) as List<Gank>);\n        }\n\n        ghs.sort { a, b ->\n            def aa = a as List<Gank>\n            def bb = b as List<Gank>\n            return aa.get(0).type.compareTo(bb.get(0).type)\n        }\n        types.sort()\n\n        return new ResultDaily(error, new GankDaily(types, ghs));\n    }\n\n    public static\n    final String test = \"{\\\"error\\\":false,\\\"results\\\":{\\\"iOS\\\":[{\\\"who\\\":\\\"CallMeWhy\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.070Z\\\",\\\"desc\\\":\\\"LLVM 简介\\\",\\\"type\\\":\\\"iOS\\\",\\\"url\\\":\\\"http://adriansampson.net/blog/llvm.html\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c40ac360b2c9d32a67ca25\\\",\\\"createdAt\\\":\\\"2015-08-07T01:32:51.588Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.384Z\\\"},{\\\"who\\\":\\\"鲍永章\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:47.242Z\\\",\\\"desc\\\":\\\"基于TextKit的UILabel，支持超链接和自定义表达式。\\\",\\\"type\\\":\\\"iOS\\\",\\\"url\\\":\\\"https://github.com/molon/MLLabel\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c372fe60b2f809e41eb388\\\",\\\"createdAt\\\":\\\"2015-08-06T14:45:18.733Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.536Z\\\"},{\\\"who\\\":\\\"CallMeWhy\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.083Z\\\",\\\"desc\\\":\\\"Swift 和 C 函数\\\",\\\"type\\\":\\\"iOS\\\",\\\"url\\\":\\\"http://chris.eidhof.nl/posts/swift-c-interop.html\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c40aea00b025867b19c9af\\\",\\\"createdAt\\\":\\\"2015-08-07T01:33:30.871Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.408Z\\\"},{\\\"who\\\":\\\"CallMeWhy\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.174Z\\\",\\\"desc\\\":\\\"Arrays Linked Lists 和性能比较\\\",\\\"type\\\":\\\"iOS\\\",\\\"url\\\":\\\"http://airspeedvelocity.net/2015/08/03/arrays-linked-lists-and-performance/\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c40b0800b0fac2c2809acc\\\",\\\"createdAt\\\":\\\"2015-08-07T01:34:00.984Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:55.105Z\\\"}],\\\"Android\\\":[{\\\"who\\\":\\\"mthli\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.045Z\\\",\\\"desc\\\":\\\"类似Link Bubble的悬浮式操作设计\\\",\\\"type\\\":\\\"Android\\\",\\\"url\\\":\\\"https://github.com/recruit-lifestyle/FloatingView\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c309a800b00045333db517\\\",\\\"createdAt\\\":\\\"2015-08-06T07:15:52.065Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:55.098Z\\\"},{\\\"who\\\":\\\"lxxself\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:47.317Z\\\",\\\"desc\\\":\\\"Android开发中，有哪些让你觉得相见恨晚的方法、类或接口？\\\",\\\"type\\\":\\\"Android\\\",\\\"url\\\":\\\"http://www.zhihu.com/question/33636939\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c40ad340ac7d0a9507b324\\\",\\\"createdAt\\\":\\\"2015-08-07T01:33:07.815Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.407Z\\\"},{\\\"who\\\":\\\"鲍永章\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.076Z\\\",\\\"desc\\\":\\\"使用注解来处理Activity的状态恢复\\\",\\\"type\\\":\\\"Android\\\",\\\"url\\\":\\\"https://github.com/tom91136/Akatsuki\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c3769660b2750766971ce6\\\",\\\"createdAt\\\":\\\"2015-08-06T15:00:38.350Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.866Z\\\"},{\\\"who\\\":\\\"有时放纵\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.142Z\\\",\\\"desc\\\":\\\"Android Lollipop联系人之PinnedListView简单使用\\\",\\\"type\\\":\\\"Android\\\",\\\"url\\\":\\\"https://git.oschina.net/way/PinnedHeaderListView\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c415c060b2d140ca882eac\\\",\\\"createdAt\\\":\\\"2015-08-07T02:19:44.342Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:55.020Z\\\"},{\\\"who\\\":\\\"鲍永章\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.073Z\\\",\\\"desc\\\":\\\"图片可以自动滚动的ImageView，可以实现视差效果。\\\",\\\"type\\\":\\\"Android\\\",\\\"url\\\":\\\"https://github.com/Q42/AndroidScrollingImageView\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c3761400b00045334480d2\\\",\\\"createdAt\\\":\\\"2015-08-06T14:58:28.171Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:55.123Z\\\"}],\\\"瞎推荐\\\":[{\\\"who\\\":\\\"lxxself\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.084Z\\\",\\\"desc\\\":\\\"程序员的电台FmM，这个页面chrome插件有问题啊哭，我写了回删除不了啊\\\",\\\"type\\\":\\\"瞎推荐\\\",\\\"url\\\":\\\"https://cmd.fm/\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c40f5e00b00045334934b4\\\",\\\"createdAt\\\":\\\"2015-08-07T01:52:30.267Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.383Z\\\"}],\\\"拓展资源\\\":[{\\\"who\\\":\\\"lxxself\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.081Z\\\",\\\"desc\\\":\\\"Display GitHub code in tree format\\\",\\\"type\\\":\\\"拓展资源\\\",\\\"url\\\":\\\"https://github.com/buunguyen/octotree\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c40b8600b08484a7f3a032\\\",\\\"createdAt\\\":\\\"2015-08-07T01:36:06.932Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.382Z\\\"}],\\\"福利\\\":[{\\\"who\\\":\\\"张涵宇\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:47.310Z\\\",\\\"desc\\\":\\\"8.7——（1）\\\",\\\"type\\\":\\\"福利\\\",\\\"url\\\":\\\"http://ww2.sinaimg.cn/large/7a8aed7bgw1eutscfcqtcj20dw0i0q4l.jpg\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c4080240ac7d0a9507905e\\\",\\\"createdAt\\\":\\\"2015-08-07T01:21:06.112Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.765Z\\\"},{\\\"who\\\":\\\"张涵宇\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:47.229Z\\\",\\\"desc\\\":\\\"8.7——（2）\\\",\\\"type\\\":\\\"福利\\\",\\\"url\\\":\\\"http://ww2.sinaimg.cn/large/7a8aed7bgw1eutsd0pgiwj20go0p0djn.jpg\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c4081d60b2c9d32a67a92e\\\",\\\"createdAt\\\":\\\"2015-08-07T01:21:33.518Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.843Z\\\"}],\\\"休息视频\\\":[{\\\"who\\\":\\\"lxxself\\\",\\\"publishedAt\\\":\\\"2015-08-07T03:57:48.104Z\\\",\\\"desc\\\":\\\"听到就心情大好的歌，简直妖魔哈哈哈哈哈，原地址\\\\nhttp://v.youku.com/v_show/id_XMTQxODA5NDM2.html\\\",\\\"type\\\":\\\"休息视频\\\",\\\"url\\\":\\\"http://www.zhihu.com/question/21778055/answer/19905413?utm_source=weibo&utm_medium=weibo_share&utm_content=share_answer&utm_campaign=share_button\\\",\\\"used\\\":true,\\\"objectId\\\":\\\"55c35bc960b2750766954ec3\\\",\\\"createdAt\\\":\\\"2015-08-06T13:06:17.211Z\\\",\\\"updatedAt\\\":\\\"2015-08-15T03:15:54.872Z\\\"}]},\\\"category\\\":[\\\"iOS\\\",\\\"Android\\\",\\\"瞎推荐\\\",\\\"拓展资源\\\",\\\"福利\\\",\\\"休息视频\\\"]}\";\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/LogKit.java",
    "content": "package zhou.gank.io.util;\n\nimport android.util.Log;\n\n/**\n * Created by zzhoujay on 2015/8/22 0022.\n * LogKit 可以设置日志级别\n */\npublic class LogKit {\n\n    /**\n     * Priority constant for the println method; use Log.v.\n     */\n    public static final int VERBOSE = 2;\n\n    /**\n     * Priority constant for the println method; use Log.d.\n     */\n    public static final int DEBUG = 3;\n\n    /**\n     * Priority constant for the println method; use Log.i.\n     */\n    public static final int INFO = 4;\n\n    /**\n     * Priority constant for the println method; use Log.w.\n     */\n    public static final int WARN = 5;\n\n    /**\n     * Priority constant for the println method; use Log.e.\n     */\n    public static final int ERROR = 6;\n\n    /**\n     * Priority constant for the println method.\n     */\n    public static final int ASSERT = 7;\n\n    public static int level = VERBOSE;\n\n    public static void v(String tag, String msg) {\n        if (level <= VERBOSE) {\n            Log.v(tag, msg);\n        }\n    }\n\n    public static void v(String tag, String msg, Throwable e) {\n        if (level <= VERBOSE) {\n            Log.v(tag, msg, e);\n        }\n    }\n\n    public static void v(String tag, Object msg) {\n        v(tag, msg.toString());\n    }\n\n    public static void d(String tag, String msg) {\n        if (level <= DEBUG) {\n            Log.d(tag, msg);\n        }\n    }\n\n    public static void d(String tag, String msg, Throwable e) {\n        if (level <= DEBUG) {\n            Log.d(tag, msg, e);\n        }\n    }\n\n    public static void d(String tag, Object msg) {\n        d(tag, msg.toString());\n    }\n\n    public static void i(String tag, String msg) {\n        if (level <= INFO) {\n            Log.i(tag, msg);\n        }\n    }\n\n    public static void i(String tag, String msg, Throwable e) {\n        if (level <= INFO) {\n            Log.i(tag, msg, e);\n        }\n    }\n\n    public static void i(String tag, Object msg) {\n        i(tag, msg.toString());\n    }\n\n    public static void w(String tag, String msg) {\n        if (level <= WARN) {\n            Log.w(tag, msg);\n        }\n    }\n\n    public static void w(String tag, String msg, Throwable e) {\n        if (level <= WARN) {\n            Log.w(tag, msg, e);\n        }\n    }\n\n    public static void w(String tag, Throwable e) {\n        if (level <= WARN) {\n            Log.w(tag, e);\n        }\n    }\n\n    public static void w(String tag, Object msg) {\n        w(tag, msg.toString());\n    }\n\n    public static void e(String tag, String msg) {\n        if (level <= ERROR) {\n            Log.e(tag, msg);\n        }\n    }\n\n    public static void e(String tag, String msg, Throwable e) {\n        if (level <= ERROR) {\n            Log.e(tag, msg, e);\n        }\n    }\n\n    public static void e(String tag, Object msg) {\n        e(tag, msg.toString());\n    }\n}\n"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/NetworkKit.groovy",
    "content": "package zhou.gank.io.util\n\nimport com.squareup.okhttp.Request\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.App\nimport zhou.gank.io.model.Result\nimport zhou.gank.io.net.NetworkManager\n\n@CompileStatic\nclass NetworkKit {\n\n    static void time(int year, int month, int day, Closure closure) {\n        Request request = new Request.Builder().get().url(\"$App.TIME_URL/$year/$month/$day\").build()\n        NetworkManager.getInstance().requestString(request, { result ->\n            try{\n                closure(JsonKit.generate(result as String, App.getInstance().getGson()))\n            }catch (Exception e){\n                LogKit.d(\"JsonKit\",\"error\",e)\n                closure()\n            }\n        })\n    }\n\n    static void type(String type, int pageSize, int pageNo, Closure closure) {\n        Request request = new Request.Builder().get().url(\"$App.TYPE_URL/$type/$pageSize/$pageNo\").build()\n        NetworkManager.getInstance().request(request, closure, Result.class)\n    }\n\n    static void random(String type, int size, Closure closure) {\n        Request request = new Request.Builder().get().url(\"$App.RANDOM_URL/$type/$size\").build()\n        NetworkManager.getInstance().request(request, closure, Result.class)\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/Notifier.groovy",
    "content": "package zhou.gank.io.util;\n\nimport groovy.transform.CompileStatic\n\n@CompileStatic\npublic interface Notifier {\n\n    void notice(int noticeId)\n\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/NumKit.groovy",
    "content": "package zhou.gank.io.util;\n\nimport groovy.transform.CompileStatic\n\n@CompileStatic\npublic class NumKit {\n\n\n    public static int getNum(String str, int num) {\n        def gg\n        try {\n            gg = Integer.valueOf(str)\n        } catch (Exception e) {\n            gg = num\n        }\n        return gg\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/Pageable.groovy",
    "content": "package zhou.gank.io.util\n\nimport groovy.transform.CompileStatic;\n\n@CompileStatic\nclass Pageable implements Serializable {\n\n    public int pageNo\n    public int pageSize\n\n    Pageable(int pageNo, int pageSize) {\n        this.pageNo = pageNo\n        this.pageSize = pageSize\n    }\n\n    Pageable() {\n    }\n\n    def next() {\n        pageNo++\n    }\n\n    def prev() {\n        pageNo--\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/TextKit.groovy",
    "content": "package zhou.gank.io.util\n\nimport android.graphics.Typeface\nimport android.text.SpannableStringBuilder\nimport android.text.Spanned\nimport android.text.style.ForegroundColorSpan\nimport android.text.style.StyleSpan\nimport groovy.transform.CompileStatic\nimport zhou.gank.io.model.Gank\nimport zhou.gank.io.ui.weiget.URLSpanNoUnderline;\n\n@CompileStatic\nclass TextKit {\n\n    public static SpannableStringBuilder generate(List<Gank> ganHuos, int color) {\n        SpannableStringBuilder builder = new SpannableStringBuilder();\n        int start;\n        for (Gank gh : ganHuos) {\n            start = builder.length();\n            builder.append(\" • \");\n            builder.setSpan(new StyleSpan(Typeface.BOLD), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);\n            start = builder.length();\n            builder.append(gh.desc);\n            builder.setSpan(new URLSpanNoUnderline(gh.url), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);\n            builder.setSpan(new ForegroundColorSpan(color), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);\n            builder.append(\"（\");\n            builder.append(gh.who);\n            builder.append(\"）\\n\");\n        }\n        return builder;\n    }\n\n    public static CharSequence getInfo() {\n        SpannableStringBuilder builder = new SpannableStringBuilder();\n        int start = 0\n        builder.append(\"Gank.IO Android 客户端\\n\")\n        builder.setSpan(new StyleSpan(Typeface.BOLD), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)\n        builder.append(\"项目地址：\")\n        start = builder.length()\n        builder.append(\"git@osc\")\n        builder.setSpan(new URLSpanNoUnderline(\"https://git.oschina.net/zzhoujay/Gank4Android\"), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)\n        builder.append(\"、\")\n        start = builder.length()\n        builder.append(\"github\")\n        builder.setSpan(new URLSpanNoUnderline(\"https://github.com/zzhoujay/Gank4Android\"), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)\n        builder.append(\"\\n\")\n        start = builder.length()\n        builder.append(\"by zzhoujay\")\n        builder.setSpan(new StyleSpan(Typeface.ITALIC), start, builder.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)\n        return builder\n    }\n}"
  },
  {
    "path": "app/src/main/groovy/zhou/gank/io/util/TimeKit.groovy",
    "content": "package zhou.gank.io.util;\n\nimport groovy.transform.CompileStatic\n\nimport java.text.SimpleDateFormat\n\n@CompileStatic\npublic class TimeKit {\n\n    public static final SimpleDateFormat simpleDateFormat = new SimpleDateFormat(\"yyyy年MM月dd日\")\n\n    public static String format(Date data) {\n        simpleDateFormat.format(data)\n    }\n\n    public static List<Integer> getTime() {\n        Calendar calendar = Calendar.getInstance()\n        return [calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH) + 1, calendar.get(Calendar.DAY_OF_MONTH)]\n    }\n\n    public static boolean future(int year, int month, int day) {\n        Calendar now = Calendar.getInstance()\n        Calendar calendar = Calendar.getInstance()\n        calendar.set(Calendar.YEAR, year)\n        calendar.set(Calendar.MONTH, month - 1)\n        calendar.set(Calendar.DAY_OF_MONTH, day)\n        return calendar.compareTo(now) >= 0\n    }\n}"
  },
  {
    "path": "app/src/main/res/drawable/ic_bookmark_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:better=\"http://schemas.android.com/apk/res-auto\"\n    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:width=\"48dp\"\n    android:height=\"48dp\"\n    android:viewportHeight=\"48\"\n    android:viewportWidth=\"48\"\n    better:viewportHeight=\"48\"\n    better:viewportWidth=\"48\"\n    tools:ignore=\"NewApi\">\n    <path\n        android:fillColor=\"#000000\"\n        android:pathData=\"M34 6L14 6c-2.21 0 -3.98 1.79 -3.98 4L10 42 24 36 38 42 38 10C38 7.79 36.21 6 34 6Z\"\n        better:fillColor=\"#000000\"\n        better:pathData=\"M34 6L14 6c-2.21 0 -3.98 1.79 -3.98 4L10 42 24 36 38 42 38 10C38 7.79 36.21 6 34 6Z\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_cloud_off_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M38.71 20.07C37.35 13.19 31.28 8 24 8 21.05 8 18.3 8.87 15.98 10.34l2.92 2.92C20.43 12.47 22.16 12 24 12c6.08 0 11 4.92 11 11l0 1 3 0c3.31 0 6 2.69 6 6 0 2.27 -1.27 4.22 -3.13 5.24l2.9 2.9C46.32 36.33 48 33.37 48 30 48 24.72 43.89 20.44 38.71 20.07ZM6 10.55L11.5 16.03C5.12 16.3 0 21.55 0 28 0 34.63 5.37 40 12 40l23.45 0 4 4L42 41.46 8.55 8 6 10.55ZM15.45 20L31.45 36 12 36C7.58 36 4 32.42 4 28 4 23.58 7.58 20 12 20l3.45 0z\"\n        better:pathData=\"M38.71 20.07C37.35 13.19 31.28 8 24 8 21.05 8 18.3 8.87 15.98 10.34l2.92 2.92C20.43 12.47 22.16 12 24 12c6.08 0 11 4.92 11 11l0 1 3 0c3.31 0 6 2.69 6 6 0 2.27 -1.27 4.22 -3.13 5.24l2.9 2.9C46.32 36.33 48 33.37 48 30 48 24.72 43.89 20.44 38.71 20.07ZM6 10.55L11.5 16.03C5.12 16.3 0 21.55 0 28 0 34.63 5.37 40 12 40l23.45 0 4 4L42 41.46 8.55 8 6 10.55ZM15.45 20L31.45 36 12 36C7.58 36 4 32.42 4 28 4 23.58 7.58 20 12 20l3.45 0z\"\n        android:fillColor=\"#ffffff\"\n        better:fillColor=\"#ffffff\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_cloud_queue_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M38.71 20.07C37.35 13.19 31.28 8 24 8 18.22 8 13.21 11.28 10.7 16.07 4.69 16.72 0 21.81 0 28 0 34.63 5.37 40 12 40l26 0c5.52 0 10 -4.48 10 -10 0 -5.28 -4.11 -9.56 -9.29 -9.93zM38 36L12 36C7.58 36 4 32.42 4 28 4 23.58 7.58 20 12 20l1.42 0c1.31 -4.61 5.54 -8 10.58 -8 6.08 0 11 4.92 11 11l0 1 3 0c3.31 0 6 2.69 6 6 0 3.31 -2.69 6 -6 6z\"\n        better:pathData=\"M38.71 20.07C37.35 13.19 31.28 8 24 8 18.22 8 13.21 11.28 10.7 16.07 4.69 16.72 0 21.81 0 28 0 34.63 5.37 40 12 40l26 0c5.52 0 10 -4.48 10 -10 0 -5.28 -4.11 -9.56 -9.29 -9.93zM38 36L12 36C7.58 36 4 32.42 4 28 4 23.58 7.58 20 12 20l1.42 0c1.31 -4.61 5.54 -8 10.58 -8 6.08 0 11 4.92 11 11l0 1 3 0c3.31 0 6 2.69 6 6 0 3.31 -2.69 6 -6 6z\"\n        android:fillColor=\"#ffffff\"\n        better:fillColor=\"#ffffff\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_dashboard_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M6 26L22 26 22 6 6 6 6 26Zm0 16l16 0 0 -12 -16 0 0 12zm20 0l16 0 0 -20 -16 0 0 20zM26 6L26 18 42 18 42 6 26 6Z\"\n        better:pathData=\"M6 26L22 26 22 6 6 6 6 26Zm0 16l16 0 0 -12 -16 0 0 12zm20 0l16 0 0 -20 -16 0 0 20zM26 6L26 18 42 18 42 6 26 6Z\"\n        android:fillColor=\"#000000\"\n        better:fillColor=\"#000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_event_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M34 24l-10 0 0 10 10 0 0 -10zM32 2L32 6 16 6 16 2 12 2 12 6 10 6C7.79 6 6.02 7.79 6.02 10L6 38c0 2.21 1.79 4 4 4l28 0c2.21 0 4 -1.79 4 -4L42 10C42 7.79 40.21 6 38 6l-2 0 0 -4 -4 0zm6 36l-28 0 0 -22 28 0 0 22z\"\n        better:pathData=\"M34 24l-10 0 0 10 10 0 0 -10zM32 2L32 6 16 6 16 2 12 2 12 6 10 6C7.79 6 6.02 7.79 6.02 10L6 38c0 2.21 1.79 4 4 4l28 0c2.21 0 4 -1.79 4 -4L42 10C42 7.79 40.21 6 38 6l-2 0 0 -4 -4 0zm6 36l-28 0 0 -22 28 0 0 22z\"\n        android:fillColor=\"#000000\"\n        better:fillColor=\"#000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_extension_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M41 22l-3 0 0 -8c0 -2.21 -1.79 -4 -4 -4l-8 0 0 -3C26 4.24 23.76 2 21 2 18.24 2 16 4.24 16 7l0 3 -8 0c-2.21 0 -3.98 1.79 -3.98 4l-0.01 7.6 2.99 0c2.98 0 5.4 2.42 5.4 5.4 0 2.98 -2.42 5.4 -5.4 5.4L4.01 32.4 4 40c0 2.21 1.79 4 4 4l7.6 0 0 -3c0 -2.98 2.42 -5.4 5.4 -5.4 2.98 0 5.4 2.42 5.4 5.4l0 3 7.6 0c2.21 0 4 -1.79 4 -4l0 -8 3 0c2.76 0 5 -2.24 5 -5 0 -2.76 -2.24 -5 -5 -5z\"\n        better:pathData=\"M41 22l-3 0 0 -8c0 -2.21 -1.79 -4 -4 -4l-8 0 0 -3C26 4.24 23.76 2 21 2 18.24 2 16 4.24 16 7l0 3 -8 0c-2.21 0 -3.98 1.79 -3.98 4l-0.01 7.6 2.99 0c2.98 0 5.4 2.42 5.4 5.4 0 2.98 -2.42 5.4 -5.4 5.4L4.01 32.4 4 40c0 2.21 1.79 4 4 4l7.6 0 0 -3c0 -2.98 2.42 -5.4 5.4 -5.4 2.98 0 5.4 2.42 5.4 5.4l0 3 7.6 0c2.21 0 4 -1.79 4 -4l0 -8 3 0c2.76 0 5 -2.24 5 -5 0 -2.76 -2.24 -5 -5 -5z\"\n        android:fillColor=\"#000000\"\n        better:fillColor=\"#000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_favorite_white_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"24\"\n    better:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    better:viewportHeight=\"24\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M12 21.35L10.55 20.03C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3 9.24 3 10.91 3.81 12 5.09 13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78 -3.4 6.86 -8.55 11.54L12 21.35Z\"\n        better:pathData=\"M12 21.35L10.55 20.03C5.4 15.36 2 12.28 2 8.5 2 5.42 4.42 3 7.5 3 9.24 3 10.91 3.81 12 5.09 13.09 3.81 14.76 3 16.5 3 19.58 3 22 5.42 22 8.5c0 3.78 -3.4 6.86 -8.55 11.54L12 21.35Z\"\n        android:fillColor=\"#FFFFFF\"\n        better:fillColor=\"#FFFFFF\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_info_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M24 4C12.95 4 4 12.95 4 24 4 35.05 12.95 44 24 44 35.05 44 44 35.05 44 24 44 12.95 35.05 4 24 4Zm2 30l-4 0 0 -12 4 0 0 12zm0 -16l-4 0 0 -4 4 0 0 4z\"\n        better:pathData=\"M24 4C12.95 4 4 12.95 4 24 4 35.05 12.95 44 24 44 35.05 44 44 35.05 44 24 44 12.95 35.05 4 24 4Zm2 30l-4 0 0 -12 4 0 0 12zm0 -16l-4 0 0 -4 4 0 0 4z\"\n        android:fillColor=\"#000000\"\n        better:fillColor=\"#000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_insert_emoticon_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M23.99 4C12.94 4 4 12.95 4 24 4 35.05 12.94 44 23.99 44 35.04 44 44 35.05 44 24 44 12.95 35.04 4 23.99 4ZM24 40C15.16 40 8 32.84 8 24 8 15.16 15.16 8 24 8c8.84 0 16 7.16 16 16 0 8.84 -7.16 16 -16 16zm7 -18c1.66 0 3 -1.34 3 -3 0 -1.66 -1.34 -3 -3 -3 -1.66 0 -3 1.34 -3 3 0 1.66 1.34 3 3 3zm-14 0c1.66 0 3 -1.34 3 -3 0 -1.66 -1.34 -3 -3 -3 -1.66 0 -3 1.34 -3 3 0 1.66 1.34 3 3 3zm7 13c4.66 0 8.61 -2.91 10.21 -7l-20.42 0c1.6 4.09 5.55 7 10.21 7z\"\n        better:pathData=\"M23.99 4C12.94 4 4 12.95 4 24 4 35.05 12.94 44 23.99 44 35.04 44 44 35.05 44 24 44 12.95 35.04 4 23.99 4ZM24 40C15.16 40 8 32.84 8 24 8 15.16 15.16 8 24 8c8.84 0 16 7.16 16 16 0 8.84 -7.16 16 -16 16zm7 -18c1.66 0 3 -1.34 3 -3 0 -1.66 -1.34 -3 -3 -3 -1.66 0 -3 1.34 -3 3 0 1.66 1.34 3 3 3zm-14 0c1.66 0 3 -1.34 3 -3 0 -1.66 -1.34 -3 -3 -3 -1.66 0 -3 1.34 -3 3 0 1.66 1.34 3 3 3zm7 13c4.66 0 8.61 -2.91 10.21 -7l-20.42 0c1.6 4.09 5.55 7 10.21 7z\"\n        android:fillColor=\"#ffffff\"\n        better:fillColor=\"#ffffff\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_menu_white_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"24\"\n    better:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    better:viewportHeight=\"24\"\n    android:width=\"24dp\"\n    android:height=\"24dp\">\n    <path\n        android:pathData=\"M3 18l18 0 0 -2 -18 0 0 2zm0 -5l18 0 0 -2 -18 0 0 2zM3 6L3 8 21 8 21 6 3 6Z\"\n        better:pathData=\"M3 18l18 0 0 -2 -18 0 0 2zm0 -5l18 0 0 -2 -18 0 0 2zM3 6L3 8 21 8 21 6 3 6Z\"\n        android:fillColor=\"#FFFFFF\"\n        better:fillColor=\"#FFFFFF\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_refresh_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M35.3 12.7C32.41 9.8 28.42 8 24 8 15.16 8 8.02 15.16 8.02 24c0 8.84 7.14 16 15.98 16 7.45 0 13.69 -5.1 15.46 -12l-4.16 0c-1.65 4.66 -6.07 8 -11.3 8 -6.63 0 -12 -5.37 -12 -12 0 -6.63 5.37 -12 12 -12 3.31 0 6.28 1.38 8.45 3.55L26 22 40 22 40 8 35.3 12.7Z\"\n        better:pathData=\"M35.3 12.7C32.41 9.8 28.42 8 24 8 15.16 8 8.02 15.16 8.02 24c0 8.84 7.14 16 15.98 16 7.45 0 13.69 -5.1 15.46 -12l-4.16 0c-1.65 4.66 -6.07 8 -11.3 8 -6.63 0 -12 -5.37 -12 -12 0 -6.63 5.37 -12 12 -12 3.31 0 6.28 1.38 8.45 3.55L26 22 40 22 40 8 35.3 12.7Z\"\n        android:fillColor=\"#ffffff\"\n        better:fillColor=\"#ffffff\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_settings_black_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"24\"\n    better:viewportWidth=\"24\"\n    android:viewportHeight=\"24\"\n    better:viewportHeight=\"24\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M19.43 12.98c0.04 -0.32 0.07 -0.64 0.07 -0.98 0 -0.34 -0.03 -0.66 -0.07 -0.98l2.11 -1.65c0.19 -0.15 0.24 -0.42 0.12 -0.64l-2 -3.46C19.54 5.05 19.27 4.97 19.05 5.05l-2.49 1C16.04 5.65 15.48 5.32 14.87 5.07L14.49 2.42C14.46 2.18 14.25 2 14 2L10 2C9.75 2 9.54 2.18 9.51 2.42L9.13 5.07C8.52 5.32 7.96 5.66 7.44 6.05l-2.49 -1C4.72 4.96 4.46 5.05 4.34 5.27l-2 3.46C2.21 8.95 2.27 9.22 2.46 9.37l2.11 1.65C4.53 11.34 4.5 11.67 4.5 12c0 0.33 0.03 0.66 0.07 0.98l-2.11 1.65c-0.19 0.15 -0.24 0.42 -0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49 -1c0.52 0.4 1.08 0.73 1.69 0.98l0.38 2.65C9.54 21.82 9.75 22 10 22l4 0c0.25 0 0.46 -0.18 0.49 -0.42l0.38 -2.65c0.61 -0.25 1.17 -0.59 1.69 -0.98l2.49 1c0.23 0.09 0.49 0 0.61 -0.22l2 -3.46c0.12 -0.22 0.07 -0.49 -0.12 -0.64L19.43 12.98ZM12 15.5c-1.93 0 -3.5 -1.57 -3.5 -3.5 0 -1.93 1.57 -3.5 3.5 -3.5 1.93 0 3.5 1.57 3.5 3.5 0 1.93 -1.57 3.5 -3.5 3.5z\"\n        better:pathData=\"M19.43 12.98c0.04 -0.32 0.07 -0.64 0.07 -0.98 0 -0.34 -0.03 -0.66 -0.07 -0.98l2.11 -1.65c0.19 -0.15 0.24 -0.42 0.12 -0.64l-2 -3.46C19.54 5.05 19.27 4.97 19.05 5.05l-2.49 1C16.04 5.65 15.48 5.32 14.87 5.07L14.49 2.42C14.46 2.18 14.25 2 14 2L10 2C9.75 2 9.54 2.18 9.51 2.42L9.13 5.07C8.52 5.32 7.96 5.66 7.44 6.05l-2.49 -1C4.72 4.96 4.46 5.05 4.34 5.27l-2 3.46C2.21 8.95 2.27 9.22 2.46 9.37l2.11 1.65C4.53 11.34 4.5 11.67 4.5 12c0 0.33 0.03 0.66 0.07 0.98l-2.11 1.65c-0.19 0.15 -0.24 0.42 -0.12 0.64l2 3.46c0.12 0.22 0.39 0.3 0.61 0.22l2.49 -1c0.52 0.4 1.08 0.73 1.69 0.98l0.38 2.65C9.54 21.82 9.75 22 10 22l4 0c0.25 0 0.46 -0.18 0.49 -0.42l0.38 -2.65c0.61 -0.25 1.17 -0.59 1.69 -0.98l2.49 1c0.23 0.09 0.49 0 0.61 -0.22l2 -3.46c0.12 -0.22 0.07 -0.49 -0.12 -0.64L19.43 12.98ZM12 15.5c-1.93 0 -3.5 -1.57 -3.5 -3.5 0 -1.93 1.57 -3.5 3.5 -3.5 1.93 0 3.5 1.57 3.5 3.5 0 1.93 -1.57 3.5 -3.5 3.5z\"\n        android:fillColor=\"#000000\"\n        better:fillColor=\"#000000\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable/ic_view_module_48px.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<vector xmlns:android=\"http://schemas.android.com/apk/res/android\" xmlns:better=\"http://schemas.android.com/apk/res-auto\" xmlns:tools=\"http://schemas.android.com/tools\"\n    tools:ignore=\"NewApi\"\n    android:viewportWidth=\"48\"\n    better:viewportWidth=\"48\"\n    android:viewportHeight=\"48\"\n    better:viewportHeight=\"48\"\n    android:width=\"48dp\"\n    android:height=\"48dp\">\n    <path\n        android:pathData=\"M8 22l10 0 0 -12 -10 0 0 12zm0 14l10 0 0 -12 -10 0 0 12zm12 0l10 0 0 -12 -10 0 0 12zm12 0l10 0 0 -12 -10 0 0 12zm-12 -14l10 0 0 -12 -10 0 0 12zm12 -12l0 12 10 0 0 -12 -10 0z\"\n        better:pathData=\"M8 22l10 0 0 -12 -10 0 0 12zm0 14l10 0 0 -12 -10 0 0 12zm12 0l10 0 0 -12 -10 0 0 12zm12 0l10 0 0 -12 -10 0 0 12zm-12 -14l10 0 0 -12 -10 0 0 12zm12 -12l0 12 10 0 0 -12 -10 0z\"\n        android:fillColor=\"#ffffff\"\n        better:fillColor=\"#ffffff\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/layout/activity_compat.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/container\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\" />"
  },
  {
    "path": "app/src/main/res/layout/activity_home.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v4.widget.DrawerLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/drawer_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fitsSystemWindows=\"true\">\n\n    <android.support.design.widget.CoordinatorLayout\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:fitsSystemWindows=\"true\" />\n\n    <android.support.design.widget.NavigationView\n        android:id=\"@+id/nav_view\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"match_parent\"\n        android:layout_gravity=\"start\"\n        android:fitsSystemWindows=\"true\"\n        app:headerLayout=\"@layout/nav_header\"\n        app:menu=\"@menu/drawer_view\" />\n\n</android.support.v4.widget.DrawerLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/background\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"?attr/colorAccent\"\n    android:fitsSystemWindows=\"true\">\n\n    <android.support.design.widget.FloatingActionButton\n        android:id=\"@+id/fab\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:clickable=\"false\"\n        android:fitsSystemWindows=\"true\"\n        app:backgroundTint=\"?attr/colorPrimary\" />\n\n\n    <TextView\n        android:id=\"@+id/textView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_gravity=\"center\"\n        android:fitsSystemWindows=\"true\"\n        android:text=\"@string/app_name\"\n        android:textAppearance=\"?android:attr/textAppearanceLarge\"\n        android:textColor=\"@color/material_purple_50\"\n        android:textSize=\"@dimen/material_display_3\"\n        android:visibility=\"gone\" />\n\n\n</android.support.design.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_tab.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/main_content\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fitsSystemWindows=\"true\">\n\n    <android.support.design.widget.AppBarLayout\n        android:id=\"@+id/appbar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n        <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            android:background=\"?attr/colorPrimary\"\n            app:layout_scrollFlags=\"scroll|enterAlways\"\n            app:popupTheme=\"@style/ThemeOverlay.AppCompat.Light\" />\n\n        <android.support.design.widget.TabLayout\n            android:id=\"@+id/tabs\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            app:tabMode=\"scrollable\" />\n\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.v4.view.ViewPager\n        android:id=\"@+id/viewpager\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\" />\n\n    <!--<android.support.design.widget.FloatingActionButton-->\n    <!--android:id=\"@+id/fab\"-->\n    <!--android:layout_width=\"wrap_content\"-->\n    <!--android:layout_height=\"wrap_content\"-->\n    <!--android:layout_gravity=\"end|bottom\"-->\n    <!--android:layout_margin=\"@dimen/fab_margin\" />-->\n\n</android.support.design.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/activity_toolbar.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/main_content\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fitsSystemWindows=\"true\">\n\n    <android.support.design.widget.AppBarLayout\n        android:id=\"@+id/appbar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n        <android.support.v7.widget.Toolbar\n            android:id=\"@+id/toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"?attr/actionBarSize\"\n            android:background=\"?attr/colorPrimary\"\n            app:layout_scrollFlags=\"scroll|enterAlways\"\n            app:popupTheme=\"@style/ThemeOverlay.AppCompat.Light\" />\n\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.design.widget.CoordinatorLayout\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\" />\n\n</android.support.design.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/dialog_text.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<TextView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/textView2\"\n    android:layout_width=\"wrap_content\"\n    android:layout_height=\"wrap_content\"\n    android:gravity=\"start\"\n    android:text=\"@string/test_title\"\n    android:lineSpacingMultiplier=\"1.5\"\n    android:padding=\"30dp\"\n    android:textAppearance=\"?android:attr/textAppearanceLarge\"\n    android:textSize=\"@dimen/material_sub_head\" />\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_daily.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/main_content\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fitsSystemWindows=\"true\">\n\n\n    <android.support.design.widget.AppBarLayout\n        android:id=\"@+id/appbar\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/detail_backdrop_height\"\n        android:fitsSystemWindows=\"true\"\n        android:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n        <android.support.design.widget.CollapsingToolbarLayout\n            android:id=\"@+id/collapsing_toolbar\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:fitsSystemWindows=\"true\"\n            app:contentScrim=\"?attr/colorPrimary\"\n            app:expandedTitleMarginEnd=\"64dp\"\n            app:expandedTitleMarginStart=\"48dp\"\n            app:layout_scrollFlags=\"scroll|exitUntilCollapsed\">\n\n            <android.support.v4.view.ViewPager\n                android:id=\"@+id/viewpager\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"\n                android:fitsSystemWindows=\"true\"\n                app:layout_collapseMode=\"parallax\" />\n\n            <!--<ImageView-->\n            <!--android:id=\"@+id/icon\"-->\n            <!--android:layout_width=\"match_parent\"-->\n            <!--android:layout_height=\"match_parent\"-->\n            <!--android:fitsSystemWindows=\"true\"-->\n            <!--android:scaleType=\"centerCrop\"-->\n            <!--app:layout_collapseMode=\"parallax\" />-->\n\n            <android.support.v7.widget.Toolbar\n                android:id=\"@+id/toolbar\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"?attr/actionBarSize\"\n                app:layout_collapseMode=\"pin\"\n                app:popupTheme=\"@style/ThemeOverlay.AppCompat.Light\" />\n\n        </android.support.design.widget.CollapsingToolbarLayout>\n\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.v7.widget.RecyclerView\n        android:id=\"@+id/recyclerView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\" />\n\n    <android.support.design.widget.FloatingActionButton\n        android:id=\"@+id/fab\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_margin=\"@dimen/fab_margin\"\n        android:clickable=\"true\"\n        android:src=\"@drawable/ic_view_module_48px\"\n        app:layout_anchor=\"@id/appbar\"\n        app:layout_anchorGravity=\"bottom|right|end\" />\n\n    <FrameLayout\n        android:id=\"@+id/loading\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/loading_background\">\n\n        <ProgressBar\n            android:id=\"@+id/progressBar\"\n            style=\"?android:attr/progressBarStyleLarge\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\" />\n\n        <LinearLayout\n            android:id=\"@+id/no_data\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:orientation=\"vertical\"\n            android:visibility=\"gone\">\n\n            <ImageView\n                android:layout_width=\"60dp\"\n                android:layout_height=\"60dp\"\n                android:layout_gravity=\"center\"\n                android:scaleType=\"centerCrop\"\n                android:src=\"@drawable/ic_cloud_queue_48px\" />\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_margin=\"10dp\"\n                android:text=\"@string/text_no_data\"\n                android:textColor=\"@color/material_grey_50\"\n                android:textSize=\"@dimen/material_sub_head\" />\n        </LinearLayout>\n\n        <LinearLayout\n            android:id=\"@+id/error\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:clickable=\"true\"\n            android:orientation=\"vertical\"\n            android:visibility=\"gone\">\n\n            <ImageView\n                android:layout_width=\"60dp\"\n                android:layout_height=\"60dp\"\n                android:layout_gravity=\"center\"\n                android:scaleType=\"centerCrop\"\n                android:src=\"@drawable/ic_cloud_off_48px\" />\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:layout_margin=\"10dp\"\n                android:text=\"@string/text_error\"\n                android:textColor=\"@color/material_grey_50\"\n                android:textSize=\"@dimen/material_sub_head\" />\n        </LinearLayout>\n\n    </FrameLayout>\n\n\n</android.support.design.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_image_page.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<ImageView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/icon\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:scaleType=\"centerCrop\" />"
  },
  {
    "path": "app/src/main/res/layout/fragment_recyler_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/main_content\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <zhou.gank.io.ui.weiget.SwipeToRefreshLayout\n        android:id=\"@+id/swipeRefreshLayout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <android.support.v7.widget.RecyclerView\n            android:id=\"@+id/recyclerView\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\" />\n\n    </zhou.gank.io.ui.weiget.SwipeToRefreshLayout>\n\n    <LinearLayout\n        android:id=\"@+id/error\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/loading_background\"\n        android:clickable=\"true\"\n        android:gravity=\"center\"\n        android:orientation=\"vertical\"\n        android:visibility=\"gone\">\n\n        <ImageView\n            android:layout_width=\"70dp\"\n            android:layout_height=\"70dp\"\n            android:layout_margin=\"10dp\"\n            android:scaleType=\"centerCrop\"\n            android:src=\"@drawable/ic_cloud_off_48px\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_margin=\"15dp\"\n            android:text=\"@string/text_error\"\n            android:textColor=\"@color/material_grey_50\"\n            android:textSize=\"@dimen/material_sub_head\" />\n    </LinearLayout>\n\n</android.support.design.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/fragment_viewpager.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v4.view.ViewPager\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\" />"
  },
  {
    "path": "app/src/main/res/layout/fragment_web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n    <zhou.gank.io.ui.weiget.SwipeToRefreshLayout\n        android:id=\"@+id/swipeRefreshLayout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n        <WebView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n            android:id=\"@+id/web_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\" />\n\n    </zhou.gank.io.ui.weiget.SwipeToRefreshLayout>\n\n    <ProgressBar\n        android:id=\"@+id/progressBar\"\n        style=\"?android:attr/progressBarStyleHorizontal\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"8dp\"\n        android:layout_alignParentTop=\"true\"\n        android:layout_centerHorizontal=\"true\"\n        android:layout_margin=\"0dp\"\n        android:max=\"100\"\n        android:padding=\"0dp\" />\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/layout/item_daily.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v7.widget.CardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:clickable=\"true\"\n    android:foreground=\"?android:selectableItemBackground\"\n    android:padding=\"5dp\"\n    app:cardUseCompatPadding=\"true\">\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <TextView\n            android:id=\"@+id/title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentEnd=\"true\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_alignParentStart=\"true\"\n            android:layout_margin=\"10dp\"\n            android:padding=\"5dp\"\n            android:text=\"@string/nav_android\"\n            android:textColor=\"@color/material_grey_1000\"\n            android:textSize=\"@dimen/material_title\" />\n\n        <TextView\n            android:id=\"@+id/content\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_below=\"@id/title\"\n            android:layout_margin=\"10dp\"\n            android:lineSpacingMultiplier=\"1.5\"\n            android:padding=\"5dp\"\n            android:textSize=\"@dimen/material_body\" />\n\n    </RelativeLayout>\n</android.support.v7.widget.CardView>"
  },
  {
    "path": "app/src/main/res/layout/item_gank.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v7.widget.CardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:layout_marginLeft=\"10dp\"\n    android:layout_marginRight=\"10dp\"\n    android:clickable=\"true\"\n    android:foreground=\"?android:selectableItemBackground\"\n    android:padding=\"5dp\"\n    app:cardUseCompatPadding=\"true\">\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n\n        <TextView\n            android:id=\"@+id/title\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentLeft=\"true\"\n            android:layout_alignParentStart=\"true\"\n            android:layout_margin=\"5dp\"\n            android:gravity=\"start\"\n            android:padding=\"5dp\"\n            android:text=\"@string/test_title\"\n            android:textColor=\"@color/material_lightBlue_500\"\n            android:textSize=\"@dimen/material_sub_head\" />\n\n        <TextView\n            android:id=\"@+id/user\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignParentEnd=\"true\"\n            android:layout_alignParentRight=\"true\"\n            android:layout_below=\"@id/title\"\n            android:layout_centerVertical=\"true\"\n            android:layout_margin=\"8dp\"\n            android:text=\"@string/test_user\"\n            android:textSize=\"@dimen/material_caption\" />\n\n        <TextView\n            android:id=\"@+id/time\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_below=\"@id/title\"\n            android:layout_margin=\"8dp\"\n            android:text=\"@string/test_time\"\n            android:textColor=\"@color/material_grey_500\"\n            android:textSize=\"@dimen/material_caption\" />\n    </RelativeLayout>\n\n</android.support.v7.widget.CardView>"
  },
  {
    "path": "app/src/main/res/layout/item_image.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.v7.widget.CardView xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:clickable=\"true\"\n    android:foreground=\"?android:selectableItemBackground\"\n    android:padding=\"5dp\"\n    app:cardUseCompatPadding=\"true\">\n\n    <RelativeLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\">\n\n        <ImageView\n            android:id=\"@+id/icon\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"wrap_content\"\n            android:layout_margin=\"5dp\"\n            android:minHeight=\"200dp\"\n            android:scaleType=\"centerCrop\" />\n\n        <TextView\n            android:id=\"@+id/time\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignBottom=\"@id/icon\"\n            android:layout_alignLeft=\"@id/icon\"\n            android:layout_alignStart=\"@id/icon\"\n            android:textColor=\"@color/material_grey_600\"\n            android:layout_margin=\"5dp\"\n            android:textSize=\"@dimen/material_body\" />\n\n        <TextView\n            android:id=\"@+id/who\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_alignBottom=\"@id/icon\"\n            android:layout_alignEnd=\"@id/icon\"\n            android:layout_alignRight=\"@id/icon\"\n            android:layout_margin=\"5dp\"\n            android:text=\"@string/test_user\"\n            android:textColor=\"@color/material_grey_500\"\n            android:textSize=\"@dimen/material_caption\" />\n    </RelativeLayout>\n\n</android.support.v7.widget.CardView>"
  },
  {
    "path": "app/src/main/res/layout/layout_gallery.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.CoordinatorLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:background=\"#000000\">\n\n    <zhou.gank.io.ui.weiget.TouchImageView\n        android:id=\"@+id/image\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_gravity=\"center\"\n        android:scaleType=\"fitCenter\" />\n\n    <RelativeLayout\n        android:id=\"@+id/error_layout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:background=\"@color/loading_background\"\n        android:visibility=\"gone\">\n\n        <ImageView\n            android:id=\"@+id/error\"\n            android:layout_width=\"70dp\"\n            android:layout_height=\"70dp\"\n            android:layout_centerInParent=\"true\"\n            android:layout_margin=\"10dp\"\n            android:scaleType=\"centerCrop\"\n            android:src=\"@drawable/ic_cloud_off_48px\" />\n\n        <TextView\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_below=\"@id/error\"\n            android:layout_centerHorizontal=\"true\"\n            android:layout_margin=\"10dp\"\n            android:text=\"@string/image_error\"\n            android:textColor=\"@color/material_grey_50\"\n            android:textSize=\"@dimen/material_sub_head\" />\n\n    </RelativeLayout>\n\n    <!--<ProgressBar-->\n    <!--android:id=\"@+id/progressBar\"-->\n    <!--style=\"?android:attr/progressBarStyleLarge\"-->\n    <!--android:layout_width=\"wrap_content\"-->\n    <!--android:layout_height=\"wrap_content\"-->\n    <!--android:layout_gravity=\"center\" />-->\n\n\n</android.support.design.widget.CoordinatorLayout>"
  },
  {
    "path": "app/src/main/res/layout/layout_more.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<FrameLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        android:layout_gravity=\"center\"\n        android:gravity=\"center\"\n        android:minHeight=\"60dp\"\n        android:orientation=\"horizontal\"\n        android:paddingLeft=\"40dp\"\n        android:paddingRight=\"40dp\">\n\n\n        <ProgressBar\n            android:id=\"@+id/progressBar\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center\"\n            android:layout_marginLeft=\"20dp\"\n            android:layout_marginStart=\"20dp\"\n            android:layout_weight=\"5\"\n            android:gravity=\"end\" />\n\n        <TextView\n            android:id=\"@+id/textView\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:layout_gravity=\"center_vertical\"\n            android:layout_weight=\"6\"\n            android:gravity=\"start\"\n            android:text=\"@string/text_loading\"\n            android:textSize=\"@dimen/material_sub_head\" />\n\n\n    </LinearLayout>\n\n</FrameLayout>\n\n"
  },
  {
    "path": "app/src/main/res/layout/nav_header.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"200dp\"\n    android:background=\"?attr/colorPrimaryDark\"\n    android:orientation=\"vertical\"\n    android:padding=\"16dp\"\n    android:theme=\"@style/ThemeOverlay.AppCompat.Dark\">\n\n    <ImageView\n        android:id=\"@+id/icon\"\n        android:layout_width=\"100dp\"\n        android:layout_height=\"100dp\"\n        android:layout_centerInParent=\"true\"\n        android:scaleType=\"centerCrop\"\n        android:src=\"@drawable/ic_insert_emoticon_48px\" />\n\n    <!--<TextView-->\n        <!--android:layout_width=\"match_parent\"-->\n        <!--android:layout_height=\"wrap_content\"-->\n        <!--android:layout_alignParentBottom=\"true\"-->\n        <!--android:layout_below=\"@id/icon\"-->\n        <!--android:layout_margin=\"5dp\"-->\n        <!--android:text=\"@string/app_name\"-->\n        <!--android:textAppearance=\"@style/TextAppearance.AppCompat.Display2\" />-->\n\n</RelativeLayout>"
  },
  {
    "path": "app/src/main/res/menu/drawer_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:title=\"@string/app_name\">\n        <menu>\n            <group android:checkableBehavior=\"single\">\n                <item\n                    android:id=\"@+id/nav_daily\"\n                    android:icon=\"@drawable/ic_event_48px\"\n                    android:title=\"@string/nav_daily\" />\n                <item\n                    android:id=\"@+id/nav_type\"\n                    android:icon=\"@drawable/ic_dashboard_48px\"\n                    android:title=\"@string/nav_type\" />\n                <item\n                    android:id=\"@+id/nav_random\"\n                    android:icon=\"@drawable/ic_extension_48px\"\n                    android:title=\"@string/nav_random\" />\n                <item\n                    android:id=\"@+id/nav_collect\"\n                    android:icon=\"@drawable/ic_bookmark_48px\"\n                    android:title=\"@string/nav_collect\" />\n            </group>\n        </menu>\n    </item>\n\n    <item android:title=\"@string/nav_option\">\n        <menu>\n            <item\n                android:id=\"@+id/nav_setting\"\n                android:icon=\"@drawable/ic_settings_black_48px\"\n                android:title=\"@string/nav_setting\" />\n            <item\n                android:id=\"@+id/nav_info\"\n                android:icon=\"@drawable/ic_info_48px\"\n                android:title=\"@string/nav_info\" />\n        </menu>\n    </item>\n\n</menu>\n"
  },
  {
    "path": "app/src/main/res/menu/menu_pop.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:id=\"@+id/menu_delete\"\n        android:title=\"@string/menu_title\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_pop_add.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item android:id=\"@+id/menu_add\"\n        android:title=\"@string/menu_collect\"/>\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_pop_remove.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:id=\"@+id/menu_remove\"\n        android:title=\"@string/cancel_collect\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/menu/menu_web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item\n        android:id=\"@+id/menu_copy\"\n        android:title=\"@string/menu_copy\" />\n    <item\n        android:id=\"@+id/menu_open\"\n        android:title=\"@string/menu_open\" />\n    <item\n        android:id=\"@+id/menu_collect\"\n        android:title=\"@string/menu_collect\" />\n</menu>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <color name=\"loading_background\">#55000000</color>\n\n    <color name=\"light_background\">#fafafa</color>\n    <color name=\"dark_background\">@color/material_grey_800</color>\n\n    <!-- Red -->\n    <color name=\"material_red_50\">#fde0dc</color>\n    <color name=\"material_red_100\">#f9bdbb</color>\n    <color name=\"material_red_200\">#f69988</color>\n    <color name=\"material_red_300\">#f36c60</color>\n    <color name=\"material_red_400\">#e84e40</color>\n    <color name=\"material_red_500\">#e51c23</color>\n    <color name=\"material_red_600\">#dd191d</color>\n    <color name=\"material_red_700\">#d01716</color>\n    <color name=\"material_red_800\">#c41411</color>\n    <color name=\"material_red_900\">#b0120a</color>\n    <color name=\"material_red_A100\">#ff7997</color>\n    <color name=\"material_red_A200\">#ff5177</color>\n    <color name=\"material_red_A400\">#ff2d6f</color>\n    <color name=\"material_red_A700\">#e00032</color>\n    <!-- Pink -->\n    <color name=\"material_pink_50\">#fce4ec</color>\n    <color name=\"material_pink_100\">#f8bbd0</color>\n    <color name=\"material_pink_200\">#f48fb1</color>\n    <color name=\"material_pink_300\">#f06292</color>\n    <color name=\"material_pink_400\">#ec407a</color>\n    <color name=\"material_pink_500\">#e91e63</color>\n    <color name=\"material_pink_600\">#d81b60</color>\n    <color name=\"material_pink_700\">#c2185d</color>\n    <color name=\"material_pink_800\">#ad1457</color>\n    <color name=\"material_pink_900\">#880e4f</color>\n    <color name=\"material_pink_A100\">#ff80ab</color>\n    <color name=\"material_pink_A200\">#ff4081</color>\n    <color name=\"material_pink_A400\">#f50057</color>\n    <color name=\"material_pink_A700\">#c51162</color>\n    <!-- Purple -->\n    <color name=\"material_purple_50\">#f3e5f5</color>\n    <color name=\"material_purple_100\">#e1bee7</color>\n    <color name=\"material_purple_200\">#ce93d8</color>\n    <color name=\"material_purple_300\">#ba68c8</color>\n    <color name=\"material_purple_400\">#ab47bc</color>\n    <color name=\"material_purple_500\">#9c27b0</color>\n    <color name=\"material_purple_600\">#8e24aa</color>\n    <color name=\"material_purple_700\">#7b1fa2</color>\n    <color name=\"material_purple_800\">#6a1b9a</color>\n    <color name=\"material_purple_900\">#4a148c</color>\n    <color name=\"material_purple_A100\">#ea80fc</color>\n    <color name=\"material_purple_A200\">#e040fb</color>\n    <color name=\"material_purple_A400\">#d500f9</color>\n    <color name=\"material_purple_A700\">#aa00ff</color>\n\n    <!-- Deep Purple -->\n    <color name=\"material_deepPurple_50\">#ede7f6</color>\n    <color name=\"material_deepPurple_100\">#d1c4e9</color>\n    <color name=\"material_deepPurple_200\">#b39ddb</color>\n    <color name=\"material_deepPurple_300\">#9575cd</color>\n    <color name=\"material_deepPurple_400\">#7e57c2</color>\n    <color name=\"material_deepPurple_500\">#673ab7</color>\n    <color name=\"material_deepPurple_600\">#5e35b1</color>\n    <color name=\"material_deepPurple_700\">#512da8</color>\n    <color name=\"material_deepPurple_800\">#4527a0</color>\n    <color name=\"material_deepPurple_900\">#311b92</color>\n    <color name=\"material_deepPurple_A100\">#b388ff</color>\n    <color name=\"material_deepPurple_A200\">#7c4dff</color>\n    <color name=\"material_deepPurple_A400\">#651fff</color>\n    <color name=\"material_deepPurple_A700\">#6200ea</color>\n    <!-- Indigo -->\n    <color name=\"material_indigo_50\">#e8eaf6</color>\n    <color name=\"material_indigo_100\">#c5cae9</color>\n    <color name=\"material_indigo_200\">#9fa8da</color>\n    <color name=\"material_indigo_300\">#7986cb</color>\n    <color name=\"material_indigo_400\">#5c5bc0</color>\n    <color name=\"material_indigo_500\">#3f51b5</color>\n    <color name=\"material_indigo_600\">#3949ab</color>\n    <color name=\"material_indigo_700\">#303f9f</color>\n    <color name=\"material_indigo_800\">#283593</color>\n    <color name=\"material_indigo_900\">#1a237e</color>\n    <color name=\"material_indigo_A100\">#8c9eff</color>\n    <color name=\"material_indigo_A200\">#536dfe</color>\n    <color name=\"material_indigo_A400\">#3d5afe</color>\n    <color name=\"material_indigo_A700\">#304ffe</color>\n    <!-- Blue -->\n    <color name=\"material_blue_50\">#e7e9fd</color>\n    <color name=\"material_blue_100\">#d0d9ff</color>\n    <color name=\"material_blue_200\">#afbfff</color>\n    <color name=\"material_blue_300\">#91a7ff</color>\n    <color name=\"material_blue_400\">#738ffe</color>\n    <color name=\"material_blue_500\">#5677fc</color>\n    <color name=\"material_blue_600\">#4e6cef</color>\n    <color name=\"material_blue_700\">#455ede</color>\n    <color name=\"material_blue_800\">#3b50ce</color>\n    <color name=\"material_blue_900\">#2a36b1</color>\n    <color name=\"material_blue_A100\">#a6baff</color>\n    <color name=\"material_blue_A200\">#6889ff</color>\n    <color name=\"material_blue_A400\">#4d73ff</color>\n    <color name=\"material_blue_A700\">#4d69ff</color>\n\n    <!-- Light Blue -->\n    <color name=\"material_lightBlue_50\">#e1f5fe</color>\n    <color name=\"material_lightBlue_100\">#b3e5fc</color>\n    <color name=\"material_lightBlue_200\">#81d4fa</color>\n    <color name=\"material_lightBlue_300\">#4fc3f7</color>\n    <color name=\"material_lightBlue_400\">#29b6f6</color>\n    <color name=\"material_lightBlue_500\">#03a9f4</color>\n    <color name=\"material_lightBlue_600\">#039be5</color>\n    <color name=\"material_lightBlue_700\">#0288d1</color>\n    <color name=\"material_lightBlue_800\">#0277bd</color>\n    <color name=\"material_lightBlue_900\">#01579b</color>\n    <color name=\"material_lightBlue_A100\">#80d8ff</color>\n    <color name=\"material_lightBlue_A200\">#40c4ff</color>\n    <color name=\"material_lightBlue_A400\">#00b0ff</color>\n    <color name=\"material_lightBlue_A700\">#0091ea</color>\n    <!-- Cyan -->\n    <color name=\"material_cyan_50\">#e0f7fa</color>\n    <color name=\"material_cyan_100\">#b2ebf2</color>\n    <color name=\"material_cyan_200\">#80deea</color>\n    <color name=\"material_cyan_300\">#4dd0e1</color>\n    <color name=\"material_cyan_400\">#26c6da</color>\n    <color name=\"material_cyan_500\">#00bcd4</color>\n    <color name=\"material_cyan_600\">#00acc1</color>\n    <color name=\"material_cyan_700\">#0097a7</color>\n    <color name=\"material_cyan_800\">#00838f</color>\n    <color name=\"material_cyan_900\">#006064</color>\n    <color name=\"material_cyan_A100\">#84ffff</color>\n    <color name=\"material_cyan_A200\">#18ffff</color>\n    <color name=\"material_cyan_A400\">#00e5ff</color>\n    <color name=\"material_cyan_A700\">#00b8d4</color>\n    <!-- Teal -->\n    <color name=\"material_teal_50\">#e0f2f1</color>\n    <color name=\"material_teal_100\">#b2dfdb</color>\n    <color name=\"material_teal_200\">#80cbc4</color>\n    <color name=\"material_teal_300\">#4db6ac</color>\n    <color name=\"material_teal_400\">#26a69a</color>\n    <color name=\"material_teal_500\">#009688</color>\n    <color name=\"material_teal_600\">#00897b</color>\n    <color name=\"material_teal_700\">#00796b</color>\n    <color name=\"material_teal_800\">#00695c</color>\n    <color name=\"material_teal_900\">#004d40</color>\n    <color name=\"material_teal_A100\">#a7ffeb</color>\n    <color name=\"material_teal_A200\">#64ffda</color>\n    <color name=\"material_teal_A400\">#1de9b6</color>\n    <color name=\"material_teal_A700\">#00bfa5</color>\n\n    <!-- Green -->\n    <color name=\"material_green_50\">#d0f8ce</color>\n    <color name=\"material_green_100\">#a3e9a4</color>\n    <color name=\"material_green_200\">#72d572</color>\n    <color name=\"material_green_300\">#42bd41</color>\n    <color name=\"material_green_400\">#2baf2b</color>\n    <color name=\"material_green_500\">#259b24</color>\n    <color name=\"material_green_600\">#0a8f08</color>\n    <color name=\"material_green_700\">#0a7e07</color>\n    <color name=\"material_green_800\">#056f00</color>\n    <color name=\"material_green_900\">#0d5302</color>\n    <color name=\"material_green_A100\">#a2f78d</color>\n    <color name=\"material_green_A200\">#5af158</color>\n    <color name=\"material_green_A400\">#14e715</color>\n    <color name=\"material_green_A700\">#12c700</color>\n    <!-- Light Green -->\n    <color name=\"material_lightGreen_50\">#f1f8e9</color>\n    <color name=\"material_lightGreen_100\">#dcedc8</color>\n    <color name=\"material_lightGreen_200\">#c5e1a5</color>\n    <color name=\"material_lightGreen_300\">#aed581</color>\n    <color name=\"material_lightGreen_400\">#9ccc65</color>\n    <color name=\"material_lightGreen_500\">#8bc34a</color>\n    <color name=\"material_lightGreen_600\">#7cb342</color>\n    <color name=\"material_lightGreen_700\">#689f38</color>\n    <color name=\"material_lightGreen_800\">#558b2f</color>\n    <color name=\"material_lightGreen_900\">#33691e</color>\n    <color name=\"material_lightGreen_A100\">#ccff90</color>\n    <color name=\"material_lightGreen_A200\">#b2ff59</color>\n    <color name=\"material_lightGreen_A400\">#76ff03</color>\n    <color name=\"material_lightGreen_A700\">#64dd17</color>\n    <!-- Lime -->\n    <color name=\"material_Lime_50\">#f9fbe7</color>\n    <color name=\"material_Lime_100\">#f0f4c3</color>\n    <color name=\"material_Lime_200\">#e6ee9c</color>\n    <color name=\"material_Lime_300\">#dce775</color>\n    <color name=\"material_Lime_400\">#d4e157</color>\n    <color name=\"material_Lime_500\">#cddc39</color>\n    <color name=\"material_Lime_600\">#c0ca33</color>\n    <color name=\"material_Lime_700\">#afb42b</color>\n    <color name=\"material_Lime_800\">#9e9d24</color>\n    <color name=\"material_Lime_900\">#827717</color>\n    <color name=\"material_Lime_A100\">#f4ff81</color>\n    <color name=\"material_Lime_A200\">#eeff41</color>\n    <color name=\"material_Lime_A400\">#c6ff00</color>\n    <color name=\"material_Lime_A700\">#aeea00</color>\n\n    <!-- Yellow -->\n    <color name=\"material_yellow_50\">#fffde7</color>\n    <color name=\"material_yellow_100\">#fff9c4</color>\n    <color name=\"material_yellow_200\">#fff59d</color>\n    <color name=\"material_yellow_300\">#fff176</color>\n    <color name=\"material_yellow_400\">#ffee58</color>\n    <color name=\"material_yellow_500\">#ffeb3b</color>\n    <color name=\"material_yellow_600\">#fdd835</color>\n    <color name=\"material_yellow_700\">#fbc02d</color>\n    <color name=\"material_yellow_800\">#f9a825</color>\n    <color name=\"material_yellow_900\">#f57f17</color>\n    <color name=\"material_yellow_A100\">#ffff8d</color>\n    <color name=\"material_yellow_A200\">#ffff00</color>\n    <color name=\"material_yellow_A400\">#ffea00</color>\n    <color name=\"material_yellow_A700\">#ffd600</color>\n    <!-- Amber -->\n    <color name=\"material_amber_50\">#fff8e1</color>\n    <color name=\"material_amber_100\">#ffecb3</color>\n    <color name=\"material_amber_200\">#ffe082</color>\n    <color name=\"material_amber_300\">#ffd54f</color>\n    <color name=\"material_amber_400\">#ffca28</color>\n    <color name=\"material_amber_500\">#ffc107</color>\n    <color name=\"material_amber_600\">#ffb300</color>\n    <color name=\"material_amber_700\">#ffa000</color>\n    <color name=\"material_amber_800\">#ff8f00</color>\n    <color name=\"material_amber_900\">#ff6f00</color>\n    <color name=\"material_amber_A100\">#ffe57f</color>\n    <color name=\"material_amber_A200\">#ffd740</color>\n    <color name=\"material_amber_A400\">#ffc400</color>\n    <color name=\"material_amber_A700\">#ffab00</color>\n    <!-- Orange -->\n    <color name=\"material_orange_50\">#fff3e0</color>\n    <color name=\"material_orange_100\">#ffe0b2</color>\n    <color name=\"material_orange_200\">#ffcc80</color>\n    <color name=\"material_orange_300\">#ffb74d</color>\n    <color name=\"material_orange_400\">#ffa726</color>\n    <color name=\"material_orange_500\">#ff9800</color>\n    <color name=\"material_orange_600\">#fb8c00</color>\n    <color name=\"material_orange_700\">#f57c00</color>\n    <color name=\"material_orange_800\">#ef6c00</color>\n    <color name=\"material_orange_900\">#e65100</color>\n    <color name=\"material_orange_A100\">#ffd180</color>\n    <color name=\"material_orange_A200\">#ffab40</color>\n    <color name=\"material_orange_A400\">#ff9100</color>\n    <color name=\"material_orange_A700\">#ff6d00</color>\n\n    <!-- Deep Orange -->\n    <color name=\"material_deepOrange_50\">#fbe9e7</color>\n    <color name=\"material_deepOrange_100\">#ffccbc</color>\n    <color name=\"material_deepOrange_200\">#ffab91</color>\n    <color name=\"material_deepOrange_300\">#ff8a65</color>\n    <color name=\"material_deepOrange_400\">#ff7043</color>\n    <color name=\"material_deepOrange_500\">#ff5722</color>\n    <color name=\"material_deepOrange_600\">#f4511e</color>\n    <color name=\"material_deepOrange_700\">#e64a19</color>\n    <color name=\"material_deepOrange_800\">#d84315</color>\n    <color name=\"material_deepOrange_900\">#bf360c</color>\n    <color name=\"material_deepOrange_A100\">#ff9e80</color>\n    <color name=\"material_deepOrange_A200\">#ff6e40</color>\n    <color name=\"material_deepOrange_A400\">#ff3d00</color>\n    <color name=\"material_deepOrange_A700\">#dd2c00</color>\n    <!-- Brown -->\n    <color name=\"material_brown_50\">#efebe9</color>\n    <color name=\"material_brown_100\">#d7ccc8</color>\n    <color name=\"material_brown_200\">#bcaaa4</color>\n    <color name=\"material_brown_300\">#a1887f</color>\n    <color name=\"material_brown_400\">#8d6e63</color>\n    <color name=\"material_brown_500\">#795548</color>\n    <color name=\"material_brown_600\">#6d4c41</color>\n    <color name=\"material_brown_700\">#5d4037</color>\n    <color name=\"material_brown_800\">#4e342e</color>\n    <color name=\"material_brown_900\">#3e2723</color>\n    <!-- Grey -->\n    <color name=\"material_grey_50\">#fafafa</color>\n    <color name=\"material_grey_100\">#f5f5f5</color>\n    <color name=\"material_grey_200\">#eeeeee</color>\n    <color name=\"material_grey_300\">#e0e0e0</color>\n    <color name=\"material_grey_400\">#dbdbdb</color>\n    <color name=\"material_grey_500\">#9e9e9e</color>\n    <color name=\"material_grey_600\">#757575</color>\n    <color name=\"material_grey_700\">#616161</color>\n    <color name=\"material_grey_800\">#424242</color>\n    <color name=\"material_grey_900\">#212121</color>\n    <color name=\"material_grey_1000\">#000000</color>\n    <color name=\"material_grey_1100\">#ffffff</color>\n\n    <!-- Blue Grey -->\n    <color name=\"material_blueGrey_50\">#eceff1</color>\n    <color name=\"material_blueGrey_100\">#cfd8dc</color>\n    <color name=\"material_blueGrey_200\">#b0bec5</color>\n    <color name=\"material_blueGrey_300\">#90a4ae</color>\n    <color name=\"material_blueGrey_400\">#78909c</color>\n    <color name=\"material_blueGrey_500\">#607d8b</color>\n    <color name=\"material_blueGrey_600\">#546e7a</color>\n    <color name=\"material_blueGrey_700\">#455a64</color>\n    <color name=\"material_blueGrey_800\">#37474f</color>\n    <color name=\"material_blueGrey_900\">#263238</color>\n\n    <!-- Black -->\n    <color name=\"material_black\">#000000</color>\n\n    <!-- White -->\n    <color name=\"material_white\">#ffffff</color>\n\n    <!-- Primary-Indigo -->\n    <color name=\"material_primaryIndigo_100\">#c5cae9</color>\n    <color name=\"material_primaryIndigo_500\">#3f51b5</color>\n    <color name=\"material_primaryIndigo_700\">#303f9f</color>\n\n    <!-- Accent-Pink -->\n    <color name=\"material_accentPink_a100\">#ff80ab</color>\n    <color name=\"material_accentPink_a200\">#ff4081</color>\n    <color name=\"material_accentPink_a400\">#f50057</color>\n\n    <!-- Black-Text -->\n    <color name=\"material_textBlack_black\">#000000</color>\n    <color name=\"material_textBlack_dividers\">#1e000000</color>\n    <color name=\"material_textBlack_disable\">#42000000</color>\n    <color name=\"material_textBlack_secondaryText\">#89000000</color>\n    <color name=\"material_textBlack_text\">#dd000000</color>\n\n    <!-- White-Text -->\n    <color name=\"material_textWhite_black\">#ffffff</color>\n    <color name=\"material_textWhite_dividers\">#1effffff</color>\n    <color name=\"material_textWhite_disable\">#42ffffff</color>\n    <color name=\"material_textWhite_secondaryText\">#89ffffff</color>\n    <color name=\"material_textWhite_text\">#ddffffff</color>\n\n</resources>"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <dimen name=\"fab_margin\">16dp</dimen>\n    <dimen name=\"detail_backdrop_height\">500dp</dimen>\n\n    <dimen name=\"material_display_4\">112sp</dimen>\n    <dimen name=\"material_display_3\">56sp</dimen>\n    <dimen name=\"material_display_2\">45sp</dimen>\n    <dimen name=\"material_display_1\">34sp</dimen>\n    <dimen name=\"material_headline\">24sp</dimen>\n    <dimen name=\"material_title\">21sp</dimen>\n    <dimen name=\"material_sub_head\">17sp</dimen>\n    <dimen name=\"material_body\">15sp</dimen>\n    <dimen name=\"material_caption\">13sp</dimen>\n    <dimen name=\"material_button\">15sp</dimen>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">干货集中营</string>\n\n    <string name=\"loading\">加载中。。。</string>\n    <string name=\"no_data\">没有数据!</string>\n    <string name=\"error\">出错了!</string>\n    <string name=\"text_refresh\">刷新</string>\n\n    <string name=\"text_no_data\" translatable=\"false\">今天没有干货哦</string>\n    <string name=\"text_error\" translatable=\"false\">加载干货失败。。。点击重新加载</string>\n    <string name=\"image_error\">图片加载失败,点击重试</string>\n\n    <string name=\"nav_ios\" translatable=\"false\">iOS</string>\n    <string name=\"nav_android\" translatable=\"false\">Android</string>\n    <string name=\"nav_recommend\" translatable=\"false\">瞎推荐</string>\n    <string name=\"nav_resource\" translatable=\"false\">拓展资源</string>\n    <string name=\"nav_welfare\" translatable=\"false\">福利</string>\n    <string name=\"nav_video\" translatable=\"false\">休息视频</string>\n    <string name=\"nav_daily\">今天</string>\n    <string name=\"nav_random\">试试运气</string>\n    <string name=\"nav_collect\">收藏</string>\n    <string name=\"test_user\" translatable=\"false\">zzhoujay</string>\n    <string name=\"test_title\" translatable=\"false\">测试标题。。。。。。。。。。。。。。。</string>\n    <string name=\"test_time\" translatable=\"false\">2015年9月23日</string>\n    <string name=\"success_update\">更新成功</string>\n\n    <string name=\"error_network\">网络连接不可用，请检查网络连接后重试</string>\n\n    <string name=\"failure_get\">获取数据失败</string>\n    <string name=\"text_loading\" translatable=\"false\">加载中。。。</string>\n    <string name=\"nav_type\">分类浏览</string>\n    <string name=\"nav_option\">操作</string>\n    <string name=\"nav_setting\">设置</string>\n    <string name=\"nav_info\">关于</string>\n    <string name=\"key_theme\" translatable=\"false\">key_theme</string>\n    <string name=\"setting_theme\">主题</string>\n    <string name=\"key_open\" translatable=\"false\">key_open</string>\n    <string name=\"summary_on_open\">使用内置浏览器打开链接</string>\n    <string name=\"summary_off_open\">使用系统浏览器打开链接</string>\n    <string name=\"title_base\">基本</string>\n    <string name=\"title_option\">操作</string>\n    <string name=\"summary_clear\">清除缓存</string>\n    <string name=\"key_clear\" translatable=\"false\">key_clear</string>\n    <string name=\"title_theme\">选择主题</string>\n    <string name=\"title_open\">在本应用内打开链接</string>\n    <string name=\"title_setting\">设置</string>\n    <string name=\"menu_copy\">复制链接</string>\n    <string name=\"menu_open\">在浏览器中打开</string>\n    <string name=\"menu_collect\">收藏</string>\n    <string name=\"success_copy\">链接已复制到剪贴板</string>\n    <string name=\"success_clear\">缓存清除成功</string>\n\n    <string name=\"key_num\" translatable=\"false\">key_num</string>\n    <string name=\"title_num\">显示数量</string>\n    <string name=\"summary_num\">每页显示的数量</string>\n\n    <string name=\"share\">分享</string>\n    <string name=\"save\">保存</string>\n\n    <string name=\"error_get_image\">获取图片失败</string>\n\n    <string name=\"confirm\">确定</string>\n\n    <string name=\"already_collect\">已经收藏过了</string>\n    <string name=\"failure_collect\">收藏失败</string>\n    <string name=\"success_collect\">收藏成功</string>\n    <string name=\"cancel_collect\">取消收藏</string>\n    <string name=\"failure_uncollect\">取消收藏失败</string>\n    <string name=\"success_uncollect\">取消收藏成功</string>\n\n    <string name=\"more_last\">没有更多数据了</string>\n    <string name=\"text_loading_failure\">加载失败,点击重新加载</string>\n\n    <string name=\"menu_title\">删除</string>\n    <string name=\"success_delete\">删除成功</string>\n\n    <string name=\"light\">亮主题</string>\n    <string name=\"dark\">暗主题</string>\n    <string name=\"year\">年</string>\n    <string name=\"month\">月</string>\n    <string name=\"day\">日</string>\n    <string name=\"text_gank\" translatable=\"false\">Gank</string>\n\n    <string-array name=\"pref_theme_list_entries\">\n        <item>@string/light</item>\n        <item>@string/dark</item>\n    </string-array>\n    <string-array name=\"pref_theme_list_values\">\n        <item>light</item>\n        <item>dark</item>\n    </string-array>\n\n    <string-array name=\"entries_num\">\n        <item>少</item>\n        <item>中</item>\n        <item>多</item>\n    </string-array>\n\n    <string-array name=\"values_num\">\n        <item>10</item>\n        <item>20</item>\n        <item>30</item>\n    </string-array>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/styles.xml",
    "content": "<resources>\n\n    <!-- Base application theme. -->\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"colorPrimary\">@color/material_purple_500</item>\n        <item name=\"colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"colorAccent\">@color/material_red_500</item>\n    </style>\n\n    <style name=\"AppThemeDark\" parent=\"Theme.AppCompat.NoActionBar\">\n        <item name=\"colorPrimary\">@color/material_purple_500</item>\n        <item name=\"colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"colorAccent\">@color/material_red_500</item>\n    </style>\n\n    <style name=\"AppTheme.Tab\" parent=\"AppTheme\">\n\n    </style>\n\n    <style name=\"AppTheme.TabDark\" parent=\"AppThemeDark\">\n\n    </style>\n\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-en/strings.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string name=\"app_name\">Gank.IO</string>\n    <string name=\"confirm\">confirm</string>\n    <string name=\"error\">Error!</string>\n    <string name=\"error_network\">The network connection is not available, please check the network connection and try again</string>\n    <string name=\"failure_get\">Failed to get the data</string>\n    <string name=\"loading\">Loading…</string>\n    <string name=\"menu_collect\">Collect</string>\n    <string name=\"menu_copy\">Copy the URL</string>\n    <string name=\"menu_open\">Open in browser</string>\n    <string name=\"nav_setting\">Setting</string>\n    <string name=\"nav_type\">Category</string>\n    <string name=\"no_data\">Empty!</string>\n    <string name=\"setting_theme\">Theme</string>\n    <string name=\"success_clear\">Cache to clear success</string>\n    <string name=\"success_copy\">The URL is copied to the clipboard</string>\n    <string name=\"summary_clear\">Clear the cache</string>\n    <string name=\"summary_num\">The number of each page show</string>\n    <string name=\"summary_off_open\">Using the system browser open the link</string>\n    <string name=\"summary_on_open\">Use the built-in browser open the link</string>\n    <string name=\"title_base\">Base</string>\n    <string name=\"title_num\">Number</string>\n    <string name=\"title_open\">In this application to open URL</string>\n    <string name=\"title_option\">Option</string>\n    <string name=\"title_setting\">Setting</string>\n    <string name=\"title_theme\">Select Theme</string>\n    <string name=\"light\">Light</string>\n    <string name=\"dark\">Dark</string>\n    <string name=\"nav_daily\">Today</string>\n    <string name=\"nav_info\">About</string>\n    <string name=\"nav_option\">Option</string>\n    <string name=\"nav_random\">Luck</string>\n    <string name=\"month\">-</string>\n    <string name=\"year\">-</string>\n    <string name=\"day\">  </string>\n    <string name=\"cancel_collect\">Cancel the collection</string>\n    <string name=\"nav_collect\">Collection</string>\n    <string name=\"more_last\">There is no more data</string>\n    <string name=\"menu_title\">Delete</string>\n    <string name=\"image_error\">Failure load images, click retry</string>\n    <string name=\"failure_uncollect\">Cancel the collection failure</string>\n    <string name=\"failure_collect\">Collection operation fails</string>\n    <string name=\"error_get_image\">Failed to get the picture</string>\n    <string name=\"already_collect\">Collection has been made</string>\n    <string name=\"save\">Save</string>\n    <string name=\"share\">Share</string>\n    <string name=\"success_collect\">Collection of success</string>\n    <string name=\"success_delete\">Deleted successfully</string>\n    <string name=\"success_uncollect\">Cancel the collection success</string>\n    <string name=\"text_loading_failure\">Failure load, click reload</string>\n    <string name=\"text_refresh\">Refresh</string>\n    <string name=\"success_update\">Update successful</string>\n</resources>"
  },
  {
    "path": "app/src/main/res/values-v21/styles.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <style name=\"AppTheme\" parent=\"Theme.AppCompat.Light.NoActionBar\">\n        <item name=\"colorPrimary\">@color/material_purple_500</item>\n        <item name=\"colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"colorAccent\">@color/material_red_500</item>\n        <item name=\"android:colorPrimary\">@color/material_purple_500</item>\n        <item name=\"android:colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"android:colorAccent\">@color/material_red_500</item>\n        <item name=\"android:statusBarColor\">#11000000</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n    </style>\n\n    <style name=\"AppThemeDark\" parent=\"Theme.AppCompat.NoActionBar\">\n        <item name=\"colorPrimary\">@color/material_purple_500</item>\n        <item name=\"colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"colorAccent\">@color/material_red_500</item>\n        <item name=\"android:colorPrimary\">@color/material_purple_500</item>\n        <item name=\"android:colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"android:colorAccent\">@color/material_red_500</item>\n        <item name=\"android:statusBarColor\">#11000000</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n    </style>\n\n\n    <style name=\"AppTheme.Tab\" parent=\"AppTheme\">\n        <item name=\"android:colorPrimary\">@color/material_purple_500</item>\n        <item name=\"android:colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"android:colorAccent\">@color/material_red_500</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n        <item name=\"android:statusBarColor\">@color/material_purple_600</item>\n    </style>\n\n    <style name=\"AppTheme.TabDark\" parent=\"AppThemeDark\">\n        <item name=\"android:colorPrimary\">@color/material_purple_500</item>\n        <item name=\"android:colorPrimaryDark\">@color/material_purple_600</item>\n        <item name=\"android:colorAccent\">@color/material_red_500</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n        <item name=\"android:statusBarColor\">@color/material_purple_600</item>\n    </style>\n\n    <style name=\"AppTheme.Card.Light\" parent=\"CardView.Light\">\n\n    </style>\n</resources>"
  },
  {
    "path": "app/src/main/res/xml/setting.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<PreferenceScreen xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <PreferenceCategory android:title=\"@string/title_base\">\n\n        <ListPreference\n            android:defaultValue=\"light\"\n            android:entries=\"@array/pref_theme_list_entries\"\n            android:entryValues=\"@array/pref_theme_list_values\"\n            android:key=\"@string/key_theme\"\n            android:summary=\"%s\"\n            android:title=\"@string/setting_theme\" />\n\n        <SwitchPreference\n            android:defaultValue=\"true\"\n            android:key=\"@string/key_open\"\n            android:summaryOff=\"@string/summary_off_open\"\n            android:summaryOn=\"@string/summary_on_open\"\n            android:title=\"@string/title_open\" />\n\n        <ListPreference\n            android:defaultValue=\"10\"\n            android:entries=\"@array/entries_num\"\n            android:entryValues=\"@array/values_num\"\n            android:key=\"@string/key_num\"\n            android:summary=\"@string/summary_num\"\n            android:title=\"@string/title_num\" />\n\n    </PreferenceCategory>\n\n    <PreferenceCategory android:title=\"@string/title_option\">\n        <!--<SwitchPreference-->\n        <!--android:summary=\"just some summary text\"-->\n        <!--android:title=\"switch\"/>-->\n        <Preference\n            android:key=\"@string/key_clear\"\n            android:title=\"@string/summary_clear\" />\n\n    </PreferenceCategory>\n</PreferenceScreen>"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\n\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:1.3.0'\n\n        // NOTE: Do not place your application dependencies here; they belong\n        // in the individual module build.gradle files\n    }\n}\n\nallprojects {\n    repositories {\n        jcenter()\n    }\n}\n"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Tue Sep 22 23:09:57 GMT+08:00 2015\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.4-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "# Project-wide Gradle settings.\n\n# IDE (e.g. Android Studio) users:\n# Gradle settings configured through the IDE *will override*\n# any settings specified in this file.\n\n# For more details on how to configure your build environment visit\n# http://www.gradle.org/docs/current/userguide/build_environment.html\n\n# Specifies the JVM arguments used for the daemon process.\n# The setting is particularly useful for tweaking memory settings.\n# Default value: -Xmx10248m -XX:MaxPermSize=256m\n# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8\n\n# When configured, Gradle will run in incubating parallel mode.\n# This option should only be used with decoupled projects. More details, visit\n# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects\n# org.gradle.parallel=true"
  },
  {
    "path": "gradlew",
    "content": "#!/usr/bin/env bash\n\n##############################################################################\n##\n##  Gradle start up script for UN*X\n##\n##############################################################################\n\n# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nDEFAULT_JVM_OPTS=\"\"\n\nAPP_NAME=\"Gradle\"\nAPP_BASE_NAME=`basename \"$0\"`\n\n# Use the maximum available, or set MAX_FD != -1 to use that value.\nMAX_FD=\"maximum\"\n\nwarn ( ) {\n    echo \"$*\"\n}\n\ndie ( ) {\n    echo\n    echo \"$*\"\n    echo\n    exit 1\n}\n\n# OS specific support (must be 'true' or 'false').\ncygwin=false\nmsys=false\ndarwin=false\ncase \"`uname`\" in\n  CYGWIN* )\n    cygwin=true\n    ;;\n  Darwin* )\n    darwin=true\n    ;;\n  MINGW* )\n    msys=true\n    ;;\nesac\n\n# For Cygwin, ensure paths are in UNIX format before anything is touched.\nif $cygwin ; then\n    [ -n \"$JAVA_HOME\" ] && JAVA_HOME=`cygpath --unix \"$JAVA_HOME\"`\nfi\n\n# Attempt to set APP_HOME\n# Resolve links: $0 may be a link\nPRG=\"$0\"\n# Need this for relative symlinks.\nwhile [ -h \"$PRG\" ] ; do\n    ls=`ls -ld \"$PRG\"`\n    link=`expr \"$ls\" : '.*-> \\(.*\\)$'`\n    if expr \"$link\" : '/.*' > /dev/null; then\n        PRG=\"$link\"\n    else\n        PRG=`dirname \"$PRG\"`\"/$link\"\n    fi\ndone\nSAVED=\"`pwd`\"\ncd \"`dirname \\\"$PRG\\\"`/\" >&-\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >&-\n\nCLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar\n\n# Determine the Java command to use to start the JVM.\nif [ -n \"$JAVA_HOME\" ] ; then\n    if [ -x \"$JAVA_HOME/jre/sh/java\" ] ; then\n        # IBM's JDK on AIX uses strange locations for the executables\n        JAVACMD=\"$JAVA_HOME/jre/sh/java\"\n    else\n        JAVACMD=\"$JAVA_HOME/bin/java\"\n    fi\n    if [ ! -x \"$JAVACMD\" ] ; then\n        die \"ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\n    fi\nelse\n    JAVACMD=\"java\"\n    which java >/dev/null 2>&1 || die \"ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\n\nPlease set the JAVA_HOME variable in your environment to match the\nlocation of your Java installation.\"\nfi\n\n# Increase the maximum file descriptors if we can.\nif [ \"$cygwin\" = \"false\" -a \"$darwin\" = \"false\" ] ; then\n    MAX_FD_LIMIT=`ulimit -H -n`\n    if [ $? -eq 0 ] ; then\n        if [ \"$MAX_FD\" = \"maximum\" -o \"$MAX_FD\" = \"max\" ] ; then\n            MAX_FD=\"$MAX_FD_LIMIT\"\n        fi\n        ulimit -n $MAX_FD\n        if [ $? -ne 0 ] ; then\n            warn \"Could not set maximum file descriptor limit: $MAX_FD\"\n        fi\n    else\n        warn \"Could not query maximum file descriptor limit: $MAX_FD_LIMIT\"\n    fi\nfi\n\n# For Darwin, add options to specify how the application appears in the dock\nif $darwin; then\n    GRADLE_OPTS=\"$GRADLE_OPTS \\\"-Xdock:name=$APP_NAME\\\" \\\"-Xdock:icon=$APP_HOME/media/gradle.icns\\\"\"\nfi\n\n# For Cygwin, switch paths to Windows format before running java\nif $cygwin ; then\n    APP_HOME=`cygpath --path --mixed \"$APP_HOME\"`\n    CLASSPATH=`cygpath --path --mixed \"$CLASSPATH\"`\n\n    # We build the pattern for arguments to be converted via cygpath\n    ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`\n    SEP=\"\"\n    for dir in $ROOTDIRSRAW ; do\n        ROOTDIRS=\"$ROOTDIRS$SEP$dir\"\n        SEP=\"|\"\n    done\n    OURCYGPATTERN=\"(^($ROOTDIRS))\"\n    # Add a user-defined pattern to the cygpath arguments\n    if [ \"$GRADLE_CYGPATTERN\" != \"\" ] ; then\n        OURCYGPATTERN=\"$OURCYGPATTERN|($GRADLE_CYGPATTERN)\"\n    fi\n    # Now convert the arguments - kludge to limit ourselves to /bin/sh\n    i=0\n    for arg in \"$@\" ; do\n        CHECK=`echo \"$arg\"|egrep -c \"$OURCYGPATTERN\" -`\n        CHECK2=`echo \"$arg\"|egrep -c \"^-\"`                                 ### Determine if an option\n\n        if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then                    ### Added a condition\n            eval `echo args$i`=`cygpath --path --ignore --mixed \"$arg\"`\n        else\n            eval `echo args$i`=\"\\\"$arg\\\"\"\n        fi\n        i=$((i+1))\n    done\n    case $i in\n        (0) set -- ;;\n        (1) set -- \"$args0\" ;;\n        (2) set -- \"$args0\" \"$args1\" ;;\n        (3) set -- \"$args0\" \"$args1\" \"$args2\" ;;\n        (4) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" ;;\n        (5) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" ;;\n        (6) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" ;;\n        (7) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" ;;\n        (8) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" ;;\n        (9) set -- \"$args0\" \"$args1\" \"$args2\" \"$args3\" \"$args4\" \"$args5\" \"$args6\" \"$args7\" \"$args8\" ;;\n    esac\nfi\n\n# Split up the JVM_OPTS And GRADLE_OPTS values into an array, following the shell quoting and substitution rules\nfunction splitJvmOpts() {\n    JVM_OPTS=(\"$@\")\n}\neval splitJvmOpts $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS\nJVM_OPTS[${#JVM_OPTS[*]}]=\"-Dorg.gradle.appname=$APP_BASE_NAME\"\n\nexec \"$JAVACMD\" \"${JVM_OPTS[@]}\" -classpath \"$CLASSPATH\" org.gradle.wrapper.GradleWrapperMain \"$@\"\n"
  },
  {
    "path": "gradlew.bat",
    "content": "@if \"%DEBUG%\" == \"\" @echo off\n@rem ##########################################################################\n@rem\n@rem  Gradle startup script for Windows\n@rem\n@rem ##########################################################################\n\n@rem Set local scope for the variables with windows NT shell\nif \"%OS%\"==\"Windows_NT\" setlocal\n\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\nset DEFAULT_JVM_OPTS=\n\nset DIRNAME=%~dp0\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\nset APP_BASE_NAME=%~n0\nset APP_HOME=%DIRNAME%\n\n@rem Find java.exe\nif defined JAVA_HOME goto findJavaFromJavaHome\n\nset JAVA_EXE=java.exe\n%JAVA_EXE% -version >NUL 2>&1\nif \"%ERRORLEVEL%\" == \"0\" goto init\n\necho.\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:findJavaFromJavaHome\nset JAVA_HOME=%JAVA_HOME:\"=%\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\n\nif exist \"%JAVA_EXE%\" goto init\n\necho.\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\necho.\necho Please set the JAVA_HOME variable in your environment to match the\necho location of your Java installation.\n\ngoto fail\n\n:init\n@rem Get command-line arguments, handling Windowz variants\n\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\n\n:win9xME_args\n@rem Slurp the command line arguments.\nset CMD_LINE_ARGS=\nset _SKIP=2\n\n:win9xME_args_slurp\nif \"x%~1\" == \"x\" goto execute\n\nset CMD_LINE_ARGS=%*\ngoto execute\n\n:4NT_args\n@rem Get arguments from the 4NT Shell from JP Software\nset CMD_LINE_ARGS=%$\n\n:execute\n@rem Setup the command line\n\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\n\n@rem Execute Gradle\n\"%JAVA_EXE%\" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% \"-Dorg.gradle.appname=%APP_BASE_NAME%\" -classpath \"%CLASSPATH%\" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%\n\n:end\n@rem End local scope for the variables with windows NT shell\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\n\n:fail\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\nrem the _cmd.exe /c_ return code!\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\nexit /b 1\n\n:mainEnd\nif \"%OS%\"==\"Windows_NT\" endlocal\n\n:omega\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app'\n"
  }
]