[
  {
    "path": ".flowconfig",
    "content": "[ignore]\n\n# We fork some components by platform.\n.*/*.android.js\n\n# Ignore templates with `@flow` in header\n.*/local-cli/generator.*\n\n# Ignore malformed json\n.*/node_modules/y18n/test/.*\\.json\n\n# Ignore the website subdir\n<PROJECT_ROOT>/website/.*\n\n# Ignore BUCK generated dirs\n<PROJECT_ROOT>/\\.buckd/\n\n# Ignore unexpected extra @providesModule\n.*/node_modules/commoner/test/source/widget/share.js\n\n# Ignore duplicate module providers\n# For RN Apps installed via npm, \"Libraries\" folder is inside node_modules/react-native but in the source repo it is in the root\n.*/Libraries/react-native/React.js\n.*/Libraries/react-native/ReactNative.js\n.*/node_modules/jest-runtime/build/__tests__/.*\n\n[include]\n\n[libs]\nLibraries/react-native/react-native-interface.js\nflow/\n\n[options]\nmodule.system=haste\n\nesproposal.class_static_fields=enable\nesproposal.class_instance_fields=enable\n\nexperimental.strict_type_args=true\n\nmunge_underscores=true\n\nmodule.name_mapper='^image![a-zA-Z0-9$_-]+$' -> 'GlobalImageStub'\nmodule.name_mapper='^[./a-zA-Z0-9$_-]+\\.\\(bmp\\|gif\\|jpg\\|jpeg\\|png\\|psd\\|svg\\|webp\\|m4v\\|mov\\|mp4\\|mpeg\\|mpg\\|webm\\|aac\\|aiff\\|caf\\|m4a\\|mp3\\|wav\\|html\\|pdf\\)$' -> 'RelativeImageStub'\n\nsuppress_type=$FlowIssue\nsuppress_type=$FlowFixMe\nsuppress_type=$FixMe\n\nsuppress_comment=\\\\(.\\\\|\\n\\\\)*\\\\$FlowFixMe\\\\($\\\\|[^(]\\\\|(\\\\(>=0\\\\.\\\\(30\\\\|[1-2][0-9]\\\\|[0-9]\\\\).[0-9]\\\\)? *\\\\(site=[a-z,_]*react_native[a-z,_]*\\\\)?)\\\\)\nsuppress_comment=\\\\(.\\\\|\\n\\\\)*\\\\$FlowIssue\\\\((\\\\(>=0\\\\.\\\\(30\\\\|1[0-9]\\\\|[1-2][0-9]\\\\).[0-9]\\\\)? *\\\\(site=[a-z,_]*react_native[a-z,_]*\\\\)?)\\\\)?:? #[0-9]+\nsuppress_comment=\\\\(.\\\\|\\n\\\\)*\\\\$FlowFixedInNextDeploy\n\nunsafe.enable_getters_and_setters=true\n\n[version]\n^0.30.0\n"
  },
  {
    "path": ".gitignore",
    "content": "*.iml\n.gradle\n/local.properties\n/.idea/workspace.xml\n/.idea/libraries\n.DS_Store\n/build\n/captures\n/node_modules\n/projectFilesBackup1\n.idea\n/projectFilesBackup"
  },
  {
    "path": ".vscode/launchReactNative.js",
    "content": "// This file is automatically generated by vscode-react-native@0.1.6\n// Please do not modify it manually. All changes will be lost.\ntry {\n    var path = require(\"path\");\n    var Launcher = require(\"/Users/wukewei/.vscode/extensions/vsmobile.vscode-react-native-0.1.6/out/debugger/launcher.js\").Launcher;\n    new Launcher(path.resolve(__dirname, \"..\")).launch();\n} catch (e) {\n    throw new Error(\"Unable to launch application. Try deleting .vscode/launchReactNative.js and restarting vscode.\");\n}"
  },
  {
    "path": ".vscode/settings.json",
    "content": "// 将设置放入此文件中以覆盖默认值和用户设置。\n{\n}"
  },
  {
    "path": ".vscode/typings/react/react-addons-create-fragment.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-create-fragment)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    namespace __Addons {\n        export function createFragment(object: { [key: string]: ReactNode }): ReactFragment;\n    }\n}\n\ndeclare module \"react-addons-create-fragment\" {\n    export = __React.__Addons.createFragment;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-addons-css-transition-group.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-css-transition-group)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n/// <reference path=\"react-addons-transition-group.d.ts\" />\n\ndeclare namespace __React {\n    interface CSSTransitionGroupTransitionName {\n        enter: string;\n        enterActive?: string;\n        leave: string;\n        leaveActive?: string;\n        appear?: string;\n        appearActive?: string;\n    }\n\n    interface CSSTransitionGroupProps extends TransitionGroupProps {\n        transitionName: string | CSSTransitionGroupTransitionName;\n        transitionAppear?: boolean;\n        transitionAppearTimeout?: number;\n        transitionEnter?: boolean;\n        transitionEnterTimeout?: number;\n        transitionLeave?: boolean;\n        transitionLeaveTimeout?: number;\n    }\n\n    type CSSTransitionGroup = ComponentClass<CSSTransitionGroupProps>;\n\n    namespace __Addons {\n        export var CSSTransitionGroup: __React.CSSTransitionGroup;\n    }\n}\n\ndeclare module \"react-addons-css-transition-group\" {\n    var CSSTransitionGroup: __React.CSSTransitionGroup;\n    type CSSTransitionGroup = __React.CSSTransitionGroup;\n    export = CSSTransitionGroup;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-addons-linked-state-mixin.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-linked-state-mixin)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface ReactLink<T> {\n        value: T;\n        requestChange(newValue: T): void;\n    }\n\n    interface LinkedStateMixin extends Mixin<any, any> {\n        linkState<T>(key: string): ReactLink<T>;\n    }\n\n    interface HTMLAttributes {\n        checkedLink?: ReactLink<boolean>;\n        valueLink?: ReactLink<boolean | string | number>;\n    }\n\n    namespace __Addons {\n        export var LinkedStateMixin: LinkedStateMixin;\n    }\n}\n\ndeclare module \"react-addons-linked-state-mixin\" {\n    var LinkedStateMixin: __React.LinkedStateMixin;\n    type LinkedStateMixin = __React.LinkedStateMixin;\n    export = LinkedStateMixin;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-addons-perf.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-perf)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface ComponentPerfContext {\n        current: string;\n        owner: string;\n    }\n\n    interface NumericPerfContext {\n        [key: string]: number;\n    }\n\n    interface Measurements {\n        exclusive: NumericPerfContext;\n        inclusive: NumericPerfContext;\n        render: NumericPerfContext;\n        counts: NumericPerfContext;\n        writes: NumericPerfContext;\n        displayNames: {\n            [key: string]: ComponentPerfContext;\n        };\n        totalTime: number;\n    }\n\n    namespace __Addons {\n        namespace Perf {\n            export function start(): void;\n            export function stop(): void;\n            export function printInclusive(measurements: Measurements[]): void;\n            export function printExclusive(measurements: Measurements[]): void;\n            export function printWasted(measurements: Measurements[]): void;\n            export function printDOM(measurements: Measurements[]): void;\n            export function getLastMeasurements(): Measurements[];\n        }\n    }\n}\n\ndeclare module \"react-addons-perf\" {\n    import Perf = __React.__Addons.Perf;\n    export = Perf;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-addons-pure-render-mixin.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-pure-render-mixin)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface PureRenderMixin extends Mixin<any, any> {}\n\n    namespace __Addons {\n        export var PureRenderMixin: PureRenderMixin;\n    }\n}\n\ndeclare module \"react-addons-pure-render-mixin\" {\n    var PureRenderMixin: __React.PureRenderMixin;\n    type PureRenderMixin = __React.PureRenderMixin;\n    export = PureRenderMixin;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-addons-test-utils.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-test-utils)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface SyntheticEventData {\n        altKey?: boolean;\n        button?: number;\n        buttons?: number;\n        clientX?: number;\n        clientY?: number;\n        changedTouches?: TouchList;\n        charCode?: boolean;\n        clipboardData?: DataTransfer;\n        ctrlKey?: boolean;\n        deltaMode?: number;\n        deltaX?: number;\n        deltaY?: number;\n        deltaZ?: number;\n        detail?: number;\n        getModifierState?(key: string): boolean;\n        key?: string;\n        keyCode?: number;\n        locale?: string;\n        location?: number;\n        metaKey?: boolean;\n        pageX?: number;\n        pageY?: number;\n        relatedTarget?: EventTarget;\n        repeat?: boolean;\n        screenX?: number;\n        screenY?: number;\n        shiftKey?: boolean;\n        targetTouches?: TouchList;\n        touches?: TouchList;\n        view?: AbstractView;\n        which?: number;\n    }\n\n    interface EventSimulator {\n        (element: Element, eventData?: SyntheticEventData): void;\n        (component: Component<any, any>, eventData?: SyntheticEventData): void;\n    }\n\n    interface MockedComponentClass {\n        new(): any;\n    }\n\n    class ShallowRenderer {\n        getRenderOutput<E extends ReactElement<any>>(): E;\n        getRenderOutput(): ReactElement<any>;\n        render(element: ReactElement<any>, context?: any): void;\n        unmount(): void;\n    }\n\n    namespace __Addons {\n        namespace TestUtils {\n            namespace Simulate {\n                export var blur: EventSimulator;\n                export var change: EventSimulator;\n                export var click: EventSimulator;\n                export var cut: EventSimulator;\n                export var doubleClick: EventSimulator;\n                export var drag: EventSimulator;\n                export var dragEnd: EventSimulator;\n                export var dragEnter: EventSimulator;\n                export var dragExit: EventSimulator;\n                export var dragLeave: EventSimulator;\n                export var dragOver: EventSimulator;\n                export var dragStart: EventSimulator;\n                export var drop: EventSimulator;\n                export var focus: EventSimulator;\n                export var input: EventSimulator;\n                export var keyDown: EventSimulator;\n                export var keyPress: EventSimulator;\n                export var keyUp: EventSimulator;\n                export var mouseDown: EventSimulator;\n                export var mouseEnter: EventSimulator;\n                export var mouseLeave: EventSimulator;\n                export var mouseMove: EventSimulator;\n                export var mouseOut: EventSimulator;\n                export var mouseOver: EventSimulator;\n                export var mouseUp: EventSimulator;\n                export var paste: EventSimulator;\n                export var scroll: EventSimulator;\n                export var submit: EventSimulator;\n                export var touchCancel: EventSimulator;\n                export var touchEnd: EventSimulator;\n                export var touchMove: EventSimulator;\n                export var touchStart: EventSimulator;\n                export var wheel: EventSimulator;\n            }\n\n            export function renderIntoDocument(\n                element: DOMElement<any>): Element;\n            export function renderIntoDocument<P>(\n                element: ReactElement<P>): Component<P, any>;\n            export function renderIntoDocument<C extends Component<any, any>>(\n                element: ReactElement<any>): C;\n\n            export function mockComponent(\n                mocked: MockedComponentClass, mockTagName?: string): typeof TestUtils;\n\n            export function isElementOfType(\n                element: ReactElement<any>, type: ReactType): boolean;\n            export function isDOMComponent(instance: ReactInstance): boolean;\n            export function isCompositeComponent(instance: ReactInstance): boolean;\n            export function isCompositeComponentWithType(\n                instance: ReactInstance,\n                type: ComponentClass<any>): boolean;\n\n            export function findAllInRenderedTree(\n                root: Component<any, any>,\n                fn: (i: ReactInstance) => boolean): ReactInstance[];\n\n            export function scryRenderedDOMComponentsWithClass(\n                root: Component<any, any>,\n                className: string): Element[];\n            export function findRenderedDOMComponentWithClass(\n                root: Component<any, any>,\n                className: string): Element;\n\n            export function scryRenderedDOMComponentsWithTag(\n                root: Component<any, any>,\n                tagName: string): Element[];\n            export function findRenderedDOMComponentWithTag(\n                root: Component<any, any>,\n                tagName: string): Element;\n\n            export function scryRenderedComponentsWithType<P>(\n                root: Component<any, any>,\n                type: ComponentClass<P>): Component<P, {}>[];\n            export function scryRenderedComponentsWithType<C extends Component<any, any>>(\n                root: Component<any, any>,\n                type: ComponentClass<any>): C[];\n\n            export function findRenderedComponentWithType<P>(\n                root: Component<any, any>,\n                type: ComponentClass<P>): Component<P, {}>;\n            export function findRenderedComponentWithType<C extends Component<any, any>>(\n                root: Component<any, any>,\n                type: ComponentClass<any>): C;\n\n            export function createRenderer(): ShallowRenderer;\n        }\n    }\n}\n\ndeclare module \"react-addons-test-utils\" {\n    import TestUtils = __React.__Addons.TestUtils;\n    export = TestUtils;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-addons-transition-group.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-transition-group)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n\n    interface TransitionGroupProps {\n        component?: ReactType;\n        childFactory?: (child: ReactElement<any>) => ReactElement<any>;\n    }\n\n    type TransitionGroup = ComponentClass<TransitionGroupProps>;\n\n    namespace __Addons {\n        export var TransitionGroup: __React.TransitionGroup;\n    }\n}\n\ndeclare module \"react-addons-transition-group\" {\n    var TransitionGroup: __React.TransitionGroup;\n    type TransitionGroup = __React.TransitionGroup;\n    export = TransitionGroup;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-addons-update.d.ts",
    "content": "// Type definitions for React v0.14 (react-addons-update)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    interface UpdateSpecCommand {\n        $set?: any;\n        $merge?: {};\n        $apply?(value: any): any;\n    }\n\n    interface UpdateSpecPath {\n        [key: string]: UpdateSpec;\n    }\n\n    type UpdateSpec = UpdateSpecCommand | UpdateSpecPath;\n\n    interface UpdateArraySpec extends UpdateSpecCommand {\n        $push?: any[];\n        $unshift?: any[];\n        $splice?: any[][];\n    }\n\n    namespace __Addons {\n        export function update(value: any[], spec: UpdateArraySpec): any[];\n        export function update(value: {}, spec: UpdateSpec): any;\n    }\n}\n\ndeclare module \"react-addons-update\" {\n    export = __React.__Addons.update;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-dom.d.ts",
    "content": "// Type definitions for React v0.14 (react-dom)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n\ndeclare namespace __React {\n    namespace __DOM {\n        function findDOMNode<E extends Element>(instance: ReactInstance): E;\n        function findDOMNode(instance: ReactInstance): Element;\n\n        function render<P>(\n            element: DOMElement<P>,\n            container: Element,\n            callback?: (element: Element) => any): Element;\n        function render<P, S>(\n            element: ClassicElement<P>,\n            container: Element,\n            callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;\n        function render<P, S>(\n            element: ReactElement<P>,\n            container: Element,\n            callback?: (component: Component<P, S>) => any): Component<P, S>;\n\n        function unmountComponentAtNode(container: Element): boolean;\n\n        var version: string;\n\n        function unstable_batchedUpdates<A, B>(callback: (a: A, b: B) => any, a: A, b: B): void;\n        function unstable_batchedUpdates<A>(callback: (a: A) => any, a: A): void;\n        function unstable_batchedUpdates(callback: () => any): void;\n\n        function unstable_renderSubtreeIntoContainer<P>(\n            parentComponent: Component<any, any>,\n            nextElement: DOMElement<P>,\n            container: Element,\n            callback?: (element: Element) => any): Element;\n        function unstable_renderSubtreeIntoContainer<P, S>(\n            parentComponent: Component<any, any>,\n            nextElement: ClassicElement<P>,\n            container: Element,\n            callback?: (component: ClassicComponent<P, S>) => any): ClassicComponent<P, S>;\n        function unstable_renderSubtreeIntoContainer<P, S>(\n            parentComponent: Component<any, any>,\n            nextElement: ReactElement<P>,\n            container: Element,\n            callback?: (component: Component<P, S>) => any): Component<P, S>;\n    }\n\n    namespace __DOMServer {\n        function renderToString(element: ReactElement<any>): string;\n        function renderToStaticMarkup(element: ReactElement<any>): string;\n        var version: string;\n    }\n}\n\ndeclare module \"react-dom\" {\n    import DOM = __React.__DOM;\n    export = DOM;\n}\n\ndeclare module \"react-dom/server\" {\n    import DOMServer = __React.__DOMServer;\n    export = DOMServer;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react-global.d.ts",
    "content": "// Type definitions for React v0.14 (namespace)\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n/// <reference path=\"react.d.ts\" />\n/// <reference path=\"react-dom.d.ts\" />\n/// <reference path=\"react-addons-create-fragment.d.ts\" />\n/// <reference path=\"react-addons-css-transition-group.d.ts\" />\n/// <reference path=\"react-addons-linked-state-mixin.d.ts\" />\n/// <reference path=\"react-addons-perf.d.ts\" />\n/// <reference path=\"react-addons-pure-render-mixin.d.ts\" />\n/// <reference path=\"react-addons-test-utils.d.ts\" />\n/// <reference path=\"react-addons-transition-group.d.ts\" />\n/// <reference path=\"react-addons-update.d.ts\" />\n\nimport React = __React;\nimport ReactDOM = __React.__DOM;\n\ndeclare namespace __React {\n    export import addons = __React.__Addons;\n}\n"
  },
  {
    "path": ".vscode/typings/react/react.d.ts",
    "content": "// Type definitions for React v0.14\n// Project: http://facebook.github.io/react/\n// Definitions by: Asana <https://asana.com>, AssureSign <http://www.assuresign.com>, Microsoft <https://microsoft.com>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\ndeclare namespace __React {\n\n    //\n    // React Elements\n    // ----------------------------------------------------------------------\n\n    type ReactType = string | ComponentClass<any> | StatelessComponent<any>;\n\n    interface ReactElement<P extends Props<any>> {\n        type: string | ComponentClass<P> | StatelessComponent<P>;\n        props: P;\n        key: string | number;\n        ref: string | ((component: Component<P, any> | Element) => any);\n    }\n\n    interface ClassicElement<P> extends ReactElement<P> {\n        type: ClassicComponentClass<P>;\n        ref: string | ((component: ClassicComponent<P, any>) => any);\n    }\n\n    interface DOMElement<P extends Props<Element>> extends ReactElement<P> {\n        type: string;\n        ref: string | ((element: Element) => any);\n    }\n\n    interface ReactHTMLElement extends DOMElement<HTMLProps<HTMLElement>> {\n        ref: string | ((element: HTMLElement) => any);\n    }\n\n    interface ReactSVGElement extends DOMElement<SVGProps> {\n        ref: string | ((element: SVGElement) => any);\n    }\n\n    //\n    // Factories\n    // ----------------------------------------------------------------------\n\n    interface Factory<P> {\n        (props?: P, ...children: ReactNode[]): ReactElement<P>;\n    }\n\n    interface ClassicFactory<P> extends Factory<P> {\n        (props?: P, ...children: ReactNode[]): ClassicElement<P>;\n    }\n\n    interface DOMFactory<P extends Props<Element>> extends Factory<P> {\n        (props?: P, ...children: ReactNode[]): DOMElement<P>;\n    }\n\n    type HTMLFactory = DOMFactory<HTMLProps<HTMLElement>>;\n    type SVGFactory = DOMFactory<SVGProps>;\n\n    //\n    // React Nodes\n    // http://facebook.github.io/react/docs/glossary.html\n    // ----------------------------------------------------------------------\n\n    type ReactText = string | number;\n    type ReactChild = ReactElement<any> | ReactText;\n\n    // Should be Array<ReactNode> but type aliases cannot be recursive\n    type ReactFragment = {} | Array<ReactChild | any[] | boolean>;\n    type ReactNode = ReactChild | ReactFragment | boolean;\n\n    //\n    // Top Level API\n    // ----------------------------------------------------------------------\n\n    function createClass<P, S>(spec: ComponentSpec<P, S>): ClassicComponentClass<P>;\n\n    function createFactory<P>(type: string): DOMFactory<P>;\n    function createFactory<P>(type: ClassicComponentClass<P>): ClassicFactory<P>;\n    function createFactory<P>(type: ComponentClass<P> | StatelessComponent<P>): Factory<P>;\n\n    function createElement<P>(\n        type: string,\n        props?: P,\n        ...children: ReactNode[]): DOMElement<P>;\n    function createElement<P>(\n        type: ClassicComponentClass<P>,\n        props?: P,\n        ...children: ReactNode[]): ClassicElement<P>;\n    function createElement<P>(\n        type: ComponentClass<P> | StatelessComponent<P>,\n        props?: P,\n        ...children: ReactNode[]): ReactElement<P>;\n\n    function cloneElement<P>(\n        element: DOMElement<P>,\n        props?: P,\n        ...children: ReactNode[]): DOMElement<P>;\n    function cloneElement<P>(\n        element: ClassicElement<P>,\n        props?: P,\n        ...children: ReactNode[]): ClassicElement<P>;\n    function cloneElement<P>(\n        element: ReactElement<P>,\n        props?: P,\n        ...children: ReactNode[]): ReactElement<P>;\n\n    function isValidElement(object: {}): boolean;\n\n    var DOM: ReactDOM;\n    var PropTypes: ReactPropTypes;\n    var Children: ReactChildren;\n\n    //\n    // Component API\n    // ----------------------------------------------------------------------\n\n    type ReactInstance = Component<any, any> | Element;\n\n    // Base component for plain JS classes\n    class Component<P, S> implements ComponentLifecycle<P, S> {\n        constructor(props?: P, context?: any);\n        setState(f: (prevState: S, props: P) => S, callback?: () => any): void;\n        setState(state: S, callback?: () => any): void;\n        forceUpdate(callBack?: () => any): void;\n        render(): JSX.Element;\n        props: P;\n        state: S;\n        context: {};\n        refs: {\n            [key: string]: ReactInstance\n        };\n    }\n\n    interface ClassicComponent<P, S> extends Component<P, S> {\n        replaceState(nextState: S, callback?: () => any): void;\n        isMounted(): boolean;\n        getInitialState?(): S;\n    }\n\n    interface ChildContextProvider<CC> {\n        getChildContext(): CC;\n    }\n\n    //\n    // Class Interfaces\n    // ----------------------------------------------------------------------\n\n    interface StatelessComponent<P> {\n        (props?: P, context?: any): ReactElement<any>;\n        propTypes?: ValidationMap<P>;\n        contextTypes?: ValidationMap<any>;\n        defaultProps?: P;\n        displayName?: string;\n    }\n\n    interface ComponentClass<P> {\n        new(props?: P, context?: any): Component<P, any>;\n        propTypes?: ValidationMap<P>;\n        contextTypes?: ValidationMap<any>;\n        childContextTypes?: ValidationMap<any>;\n        defaultProps?: P;\n    }\n\n    interface ClassicComponentClass<P> extends ComponentClass<P> {\n        new(props?: P, context?: any): ClassicComponent<P, any>;\n        getDefaultProps?(): P;\n        displayName?: string;\n    }\n\n    //\n    // Component Specs and Lifecycle\n    // ----------------------------------------------------------------------\n\n    interface ComponentLifecycle<P, S> {\n        componentWillMount?(): void;\n        componentDidMount?(): void;\n        componentWillReceiveProps?(nextProps: P, nextContext: any): void;\n        shouldComponentUpdate?(nextProps: P, nextState: S, nextContext: any): boolean;\n        componentWillUpdate?(nextProps: P, nextState: S, nextContext: any): void;\n        componentDidUpdate?(prevProps: P, prevState: S, prevContext: any): void;\n        componentWillUnmount?(): void;\n    }\n\n    interface Mixin<P, S> extends ComponentLifecycle<P, S> {\n        mixins?: Mixin<P, S>;\n        statics?: {\n            [key: string]: any;\n        };\n\n        displayName?: string;\n        propTypes?: ValidationMap<any>;\n        contextTypes?: ValidationMap<any>;\n        childContextTypes?: ValidationMap<any>;\n\n        getDefaultProps?(): P;\n        getInitialState?(): S;\n    }\n\n    interface ComponentSpec<P, S> extends Mixin<P, S> {\n        render(): ReactElement<any>;\n\n        [propertyName: string]: any;\n    }\n\n    //\n    // Event System\n    // ----------------------------------------------------------------------\n\n    interface SyntheticEvent {\n        bubbles: boolean;\n        cancelable: boolean;\n        currentTarget: EventTarget;\n        defaultPrevented: boolean;\n        eventPhase: number;\n        isTrusted: boolean;\n        nativeEvent: Event;\n        preventDefault(): void;\n        stopPropagation(): void;\n        target: EventTarget;\n        timeStamp: Date;\n        type: string;\n    }\n\n    interface ClipboardEvent extends SyntheticEvent {\n        clipboardData: DataTransfer;\n    }\n\n    interface CompositionEvent extends SyntheticEvent {\n        data: string;\n    }\n\n    interface DragEvent extends SyntheticEvent {\n        dataTransfer: DataTransfer;\n    }\n\n    interface FocusEvent extends SyntheticEvent {\n        relatedTarget: EventTarget;\n    }\n\n    interface FormEvent extends SyntheticEvent {\n    }\n\n    interface KeyboardEvent extends SyntheticEvent {\n        altKey: boolean;\n        charCode: number;\n        ctrlKey: boolean;\n        getModifierState(key: string): boolean;\n        key: string;\n        keyCode: number;\n        locale: string;\n        location: number;\n        metaKey: boolean;\n        repeat: boolean;\n        shiftKey: boolean;\n        which: number;\n    }\n\n    interface MouseEvent extends SyntheticEvent {\n        altKey: boolean;\n        button: number;\n        buttons: number;\n        clientX: number;\n        clientY: number;\n        ctrlKey: boolean;\n        getModifierState(key: string): boolean;\n        metaKey: boolean;\n        pageX: number;\n        pageY: number;\n        relatedTarget: EventTarget;\n        screenX: number;\n        screenY: number;\n        shiftKey: boolean;\n    }\n\n    interface TouchEvent extends SyntheticEvent {\n        altKey: boolean;\n        changedTouches: TouchList;\n        ctrlKey: boolean;\n        getModifierState(key: string): boolean;\n        metaKey: boolean;\n        shiftKey: boolean;\n        targetTouches: TouchList;\n        touches: TouchList;\n    }\n\n    interface UIEvent extends SyntheticEvent {\n        detail: number;\n        view: AbstractView;\n    }\n\n    interface WheelEvent extends SyntheticEvent {\n        deltaMode: number;\n        deltaX: number;\n        deltaY: number;\n        deltaZ: number;\n    }\n\n    //\n    // Event Handler Types\n    // ----------------------------------------------------------------------\n\n    interface EventHandler<E extends SyntheticEvent> {\n        (event: E): void;\n    }\n\n    type ReactEventHandler = EventHandler<SyntheticEvent>;\n\n    type ClipboardEventHandler = EventHandler<ClipboardEvent>;\n    type CompositionEventHandler = EventHandler<CompositionEvent>;\n    type DragEventHandler = EventHandler<DragEvent>;\n    type FocusEventHandler = EventHandler<FocusEvent>;\n    type FormEventHandler = EventHandler<FormEvent>;\n    type KeyboardEventHandler = EventHandler<KeyboardEvent>;\n    type MouseEventHandler = EventHandler<MouseEvent>;\n    type TouchEventHandler = EventHandler<TouchEvent>;\n    type UIEventHandler = EventHandler<UIEvent>;\n    type WheelEventHandler = EventHandler<WheelEvent>;\n\n    //\n    // Props / DOM Attributes\n    // ----------------------------------------------------------------------\n\n    interface Props<T> {\n        children?: ReactNode;\n        key?: string | number;\n        ref?: string | ((component: T) => any);\n    }\n\n    interface HTMLProps<T> extends HTMLAttributes, Props<T> {\n    }\n\n    interface SVGProps extends SVGAttributes, Props<SVGElement> {\n    }\n\n    interface DOMAttributes {\n        dangerouslySetInnerHTML?: {\n            __html: string;\n        };\n\n        // Clipboard Events\n        onCopy?: ClipboardEventHandler;\n        onCut?: ClipboardEventHandler;\n        onPaste?: ClipboardEventHandler;\n\n        // Composition Events\n        onCompositionEnd?: CompositionEventHandler;\n        onCompositionStart?: CompositionEventHandler;\n        onCompositionUpdate?: CompositionEventHandler;\n\n        // Focus Events\n        onFocus?: FocusEventHandler;\n        onBlur?: FocusEventHandler;\n\n        // Form Events\n        onChange?: FormEventHandler;\n        onInput?: FormEventHandler;\n        onSubmit?: FormEventHandler;\n\n        // Image Events\n        onLoad?: ReactEventHandler;\n        onError?: ReactEventHandler; // also a Media Event\n\n        // Keyboard Events\n        onKeyDown?: KeyboardEventHandler;\n        onKeyPress?: KeyboardEventHandler;\n        onKeyUp?: KeyboardEventHandler;\n\n        // Media Events\n        onAbort?: ReactEventHandler;\n        onCanPlay?: ReactEventHandler;\n        onCanPlayThrough?: ReactEventHandler;\n        onDurationChange?: ReactEventHandler;\n        onEmptied?: ReactEventHandler;\n        onEncrypted?: ReactEventHandler;\n        onEnded?: ReactEventHandler;\n        onLoadedData?: ReactEventHandler;\n        onLoadedMetadata?: ReactEventHandler;\n        onLoadStart?: ReactEventHandler;\n        onPause?: ReactEventHandler;\n        onPlay?: ReactEventHandler;\n        onPlaying?: ReactEventHandler;\n        onProgress?: ReactEventHandler;\n        onRateChange?: ReactEventHandler;\n        onSeeked?: ReactEventHandler;\n        onSeeking?: ReactEventHandler;\n        onStalled?: ReactEventHandler;\n        onSuspend?: ReactEventHandler;\n        onTimeUpdate?: ReactEventHandler;\n        onVolumeChange?: ReactEventHandler;\n        onWaiting?: ReactEventHandler;\n\n        // MouseEvents\n        onClick?: MouseEventHandler;\n        onContextMenu?: MouseEventHandler;\n        onDoubleClick?: MouseEventHandler;\n        onDrag?: DragEventHandler;\n        onDragEnd?: DragEventHandler;\n        onDragEnter?: DragEventHandler;\n        onDragExit?: DragEventHandler;\n        onDragLeave?: DragEventHandler;\n        onDragOver?: DragEventHandler;\n        onDragStart?: DragEventHandler;\n        onDrop?: DragEventHandler;\n        onMouseDown?: MouseEventHandler;\n        onMouseEnter?: MouseEventHandler;\n        onMouseLeave?: MouseEventHandler;\n        onMouseMove?: MouseEventHandler;\n        onMouseOut?: MouseEventHandler;\n        onMouseOver?: MouseEventHandler;\n        onMouseUp?: MouseEventHandler;\n\n        // Selection Events\n        onSelect?: ReactEventHandler;\n\n        // Touch Events\n        onTouchCancel?: TouchEventHandler;\n        onTouchEnd?: TouchEventHandler;\n        onTouchMove?: TouchEventHandler;\n        onTouchStart?: TouchEventHandler;\n\n        // UI Events\n        onScroll?: UIEventHandler;\n\n        // Wheel Events\n        onWheel?: WheelEventHandler;\n    }\n\n    // This interface is not complete. Only properties accepting\n    // unitless numbers are listed here (see CSSProperty.js in React)\n    interface CSSProperties {\n        boxFlex?: number;\n        boxFlexGroup?: number;\n        columnCount?: number;\n        flex?: number | string;\n        flexGrow?: number;\n        flexShrink?: number;\n        fontWeight?: number | string;\n        lineClamp?: number;\n        lineHeight?: number | string;\n        opacity?: number;\n        order?: number;\n        orphans?: number;\n        widows?: number;\n        zIndex?: number;\n        zoom?: number;\n\n        fontSize?: number | string;\n\n        // SVG-related properties\n        fillOpacity?: number;\n        strokeOpacity?: number;\n        strokeWidth?: number;\n\n        // Remaining properties auto-extracted from http://docs.webplatform.org.\n        // License: http://docs.webplatform.org/wiki/Template:CC-by-3.0\n        /**\n         * Aligns a flex container's lines within the flex container when there is extra space in the cross-axis, similar to how justify-content aligns individual items within the main-axis.\n         */\n        alignContent?: any;\n\n        /**\n         * Sets the default alignment in the cross axis for all of the flex container's items, including anonymous flex items, similarly to how justify-content aligns items along the main axis.\n         */\n        alignItems?: any;\n\n        /**\n         * Allows the default alignment to be overridden for individual flex items.\n         */\n        alignSelf?: any;\n\n        /**\n         * This property allows precise alignment of elements, such as graphics, that do not have a baseline-table or lack the desired baseline in their baseline-table. With the alignment-adjust property, the position of the baseline identified by the alignment-baseline can be explicitly determined. It also determines precisely the alignment point for each glyph within a textual element.\n         */\n        alignmentAdjust?: any;\n\n        alignmentBaseline?: any;\n\n        /**\n         * Defines a length of time to elapse before an animation starts, allowing an animation to begin execution some time after it is applied.\n         */\n        animationDelay?: any;\n\n        /**\n         * Defines whether an animation should run in reverse on some or all cycles.\n         */\n        animationDirection?: any;\n\n        /**\n         * Specifies how many times an animation cycle should play.\n         */\n        animationIterationCount?: any;\n\n        /**\n         * Defines the list of animations that apply to the element.\n         */\n        animationName?: any;\n\n        /**\n         * Defines whether an animation is running or paused.\n         */\n        animationPlayState?: any;\n\n        /**\n         * Allows changing the style of any element to platform-based interface elements or vice versa.\n         */\n        appearance?: any;\n\n        /**\n         * Determines whether or not the “back” side of a transformed element is visible when facing the viewer.\n         */\n        backfaceVisibility?: any;\n\n        /**\n         * This property describes how the element's background images should blend with each other and the element's background color.\n         * The value is a list of blend modes that corresponds to each background image. Each element in the list will apply to the corresponding element of background-image. If a property doesn’t have enough comma-separated values to match the number of layers, the UA must calculate its used value by repeating the list of values until there are enough.\n         */\n        backgroundBlendMode?: any;\n\n        backgroundColor?: any;\n        \n        backgroundComposite?: any;\n\n        /**\n         * Applies one or more background images to an element. These can be any valid CSS image, including url() paths to image files or CSS gradients.\n         */\n        backgroundImage?: any;\n\n        /**\n         * Specifies what the background-position property is relative to.\n         */\n        backgroundOrigin?: any;\n\n        /**\n         * Sets the horizontal position of a background image.\n         */\n        backgroundPositionX?: any;\n\n        /**\n         * Background-repeat defines if and how background images will be repeated after they have been sized and positioned\n         */\n        backgroundRepeat?: any;\n\n        /**\n         * Obsolete - spec retired, not implemented.\n         */\n        baselineShift?: any;\n\n        /**\n         * Non standard. Sets or retrieves the location of the Dynamic HTML (DHTML) behavior.\n         */\n        behavior?: any;\n\n        /**\n         * Shorthand property that defines the different properties of all four sides of an element's border in a single declaration. It can be used to set border-width, border-style and border-color, or a subset of these.\n         */\n        border?: any;\n\n        /**\n         * Defines the shape of the border of the bottom-left corner.\n         */\n        borderBottomLeftRadius?: any;\n\n        /**\n         * Defines the shape of the border of the bottom-right corner.\n         */\n        borderBottomRightRadius?: any;\n\n        /**\n         * Sets the width of an element's bottom border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderBottomWidth?: any;\n\n        /**\n         * Border-collapse can be used for collapsing the borders between table cells\n         */\n        borderCollapse?: any;\n\n        /**\n         * The CSS border-color property sets the color of an element's four borders. This property can have from one to four values, made up of the elementary properties:     •       border-top-color\n         *      •       border-right-color\n         *      •       border-bottom-color\n         *      •       border-left-color The default color is the currentColor of each of these values.\n         * If you provide one value, it sets the color for the element. Two values set the horizontal and vertical values, respectively. Providing three values sets the top, vertical, and bottom values, in that order. Four values set all for sides: top, right, bottom, and left, in that order.\n         */\n        borderColor?: any;\n\n        /**\n         * Specifies different corner clipping effects, such as scoop (inner curves), bevel (straight cuts) or notch (cut-off rectangles). Works along with border-radius to specify the size of each corner effect.\n         */\n        borderCornerShape?: any;\n\n        /**\n         * The property border-image-source is used to set the image to be used instead of the border style. If this is set to none the border-style is used instead.\n         */\n        borderImageSource?: any;\n\n        /**\n         * The border-image-width CSS property defines the offset to use for dividing the border image in nine parts, the top-left corner, central top edge, top-right-corner, central right edge, bottom-right corner, central bottom edge, bottom-left corner, and central right edge. They represent inward distance from the top, right, bottom, and left edges.\n         */\n        borderImageWidth?: any;\n\n        /**\n         * Shorthand property that defines the border-width, border-style and border-color of an element's left border in a single declaration. Note that you can use the corresponding longhand properties to set specific individual properties of the left border — border-left-width, border-left-style and border-left-color.\n         */\n        borderLeft?: any;\n\n        /**\n         * The CSS border-left-color property sets the color of an element's left border. This page explains the border-left-color value, but often you will find it more convenient to fix the border's left color as part of a shorthand set, either border-left or border-color.\n         * Colors can be defined several ways. For more information, see Usage.\n         */\n        borderLeftColor?: any;\n\n        /**\n         * Sets the style of an element's left border. To set all four borders, use the shorthand property, border-style. Otherwise, you can set the borders individually with border-top-style, border-right-style, border-bottom-style, border-left-style.\n         */\n        borderLeftStyle?: any;\n\n        /**\n         * Sets the width of an element's left border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderLeftWidth?: any;\n\n        /**\n         * Shorthand property that defines the border-width, border-style and border-color of an element's right border in a single declaration. Note that you can use the corresponding longhand properties to set specific individual properties of the right border — border-right-width, border-right-style and border-right-color.\n         */\n        borderRight?: any;\n\n        /**\n         * Sets the color of an element's right border. This page explains the border-right-color value, but often you will find it more convenient to fix the border's right color as part of a shorthand set, either border-right or border-color.\n         * Colors can be defined several ways. For more information, see Usage.\n         */\n        borderRightColor?: any;\n\n        /**\n         * Sets the style of an element's right border. To set all four borders, use the shorthand property, border-style. Otherwise, you can set the borders individually with border-top-style, border-right-style, border-bottom-style, border-left-style.\n         */\n        borderRightStyle?: any;\n\n        /**\n         * Sets the width of an element's right border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderRightWidth?: any;\n\n        /**\n         * Specifies the distance between the borders of adjacent cells.\n         */\n        borderSpacing?: any;\n\n        /**\n         * Sets the style of an element's four borders. This property can have from one to four values. With only one value, the value will be applied to all four borders; otherwise, this works as a shorthand property for each of border-top-style, border-right-style, border-bottom-style, border-left-style, where each border style may be assigned a separate value.\n         */\n        borderStyle?: any;\n\n        /**\n         * Shorthand property that defines the border-width, border-style and border-color of an element's top border in a single declaration. Note that you can use the corresponding longhand properties to set specific individual properties of the top border — border-top-width, border-top-style and border-top-color.\n         */\n        borderTop?: any;\n\n        /**\n         * Sets the color of an element's top border. This page explains the border-top-color value, but often you will find it more convenient to fix the border's top color as part of a shorthand set, either border-top or border-color.\n         * Colors can be defined several ways. For more information, see Usage.\n         */\n        borderTopColor?: any;\n\n        /**\n         * Sets the rounding of the top-left corner of the element.\n         */\n        borderTopLeftRadius?: any;\n\n        /**\n         * Sets the rounding of the top-right corner of the element.\n         */\n        borderTopRightRadius?: any;\n\n        /**\n         * Sets the style of an element's top border. To set all four borders, use the shorthand property, border-style. Otherwise, you can set the borders individually with border-top-style, border-right-style, border-bottom-style, border-left-style.\n         */\n        borderTopStyle?: any;\n\n        /**\n         * Sets the width of an element's top border. To set all four borders, use the border-width shorthand property which sets the values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderTopWidth?: any;\n\n        /**\n         * Sets the width of an element's four borders. This property can have from one to four values. This is a shorthand property for setting values simultaneously for border-top-width, border-right-width, border-bottom-width, and border-left-width.\n         */\n        borderWidth?: any;\n\n        /**\n         * Obsolete.\n         */\n        boxAlign?: any;\n\n        /**\n         * Breaks a box into fragments creating new borders, padding and repeating backgrounds or lets it stay as a continuous box on a page break, column break, or, for inline elements, at a line break.\n         */\n        boxDecorationBreak?: any;\n\n        /**\n         * Deprecated\n         */\n        boxDirection?: any;\n\n        /**\n         * Do not use. This property has been replaced by the flex-wrap property.\n         * Gets or sets a value that specifies the direction to add successive rows or columns when the value of box-lines is set to multiple.\n         */\n        boxLineProgression?: any;\n\n        /**\n         * Do not use. This property has been replaced by the flex-wrap property.\n         * Gets or sets a value that specifies whether child elements wrap onto multiple lines or columns based on the space available in the object.\n         */\n        boxLines?: any;\n\n        /**\n         * Do not use. This property has been replaced by flex-order.\n         * Specifies the ordinal group that a child element of the object belongs to. This ordinal value identifies the display order (along the axis defined by the box-orient property) for the group.\n         */\n        boxOrdinalGroup?: any;\n\n        /**\n         * The CSS break-after property allows you to force a break on multi-column layouts. More specifically, it allows you to force a break after an element. It allows you to determine if a break should occur, and what type of break it should be. The break-after CSS property describes how the page, column or region break behaves after the generated box. If there is no generated box, the property is ignored.\n         */\n        breakAfter?: any;\n\n        /**\n         * Control page/column/region breaks that fall above a block of content\n         */\n        breakBefore?: any;\n\n        /**\n         * Control page/column/region breaks that fall within a block of content\n         */\n        breakInside?: any;\n\n        /**\n         * The clear CSS property specifies if an element can be positioned next to or must be positioned below the floating elements that precede it in the markup.\n         */\n        clear?: any;\n\n        /**\n         * Deprecated; see clip-path.\n         * Lets you specify the dimensions of an absolutely positioned element that should be visible, and the element is clipped into this shape, and displayed.\n         */\n        clip?: any;\n\n        /**\n         * Clipping crops an graphic, so that only a portion of the graphic is rendered, or filled. This clip-rule property, when used with the clip-path property, defines which clip rule, or algorithm, to use when filling the different parts of a graphics.\n         */\n        clipRule?: any;\n\n        /**\n         * The color property sets the color of an element's foreground content (usually text), accepting any standard CSS color from keywords and hex values to RGB(a) and HSL(a).\n         */\n        color?: any;\n\n        /**\n         * Specifies how to fill columns (balanced or sequential).\n         */\n        columnFill?: any;\n\n        /**\n         * The column-gap property controls the width of the gap between columns in multi-column elements.\n         */\n        columnGap?: any;\n\n        /**\n         * Sets the width, style, and color of the rule between columns.\n         */\n        columnRule?: any;\n\n        /**\n         * Specifies the color of the rule between columns.\n         */\n        columnRuleColor?: any;\n\n        /**\n         * Specifies the width of the rule between columns.\n         */\n        columnRuleWidth?: any;\n\n        /**\n         * The column-span CSS property makes it possible for an element to span across all columns when its value is set to all. An element that spans more than one column is called a spanning element.\n         */\n        columnSpan?: any;\n\n        /**\n         * Specifies the width of columns in multi-column elements.\n         */\n        columnWidth?: any;\n\n        /**\n         * This property is a shorthand property for setting column-width and/or column-count.\n         */\n        columns?: any;\n\n        /**\n         * The counter-increment property accepts one or more names of counters (identifiers), each one optionally followed by an integer which specifies the value by which the counter should be incremented (e.g. if the value is 2, the counter increases by 2 each time it is invoked).\n         */\n        counterIncrement?: any;\n\n        /**\n         * The counter-reset property contains a list of one or more names of counters, each one optionally followed by an integer (otherwise, the integer defaults to 0.) Each time the given element is invoked, the counters specified by the property are set to the given integer.\n         */\n        counterReset?: any;\n\n        /**\n         * The cue property specifies sound files (known as an \"auditory icon\") to be played by speech media agents before and after presenting an element's content; if only one file is specified, it is played both before and after. The volume at which the file(s) should be played, relative to the volume of the main element, may also be specified. The icon files may also be set separately with the cue-before and cue-after properties.\n         */\n        cue?: any;\n\n        /**\n         * The cue-after property specifies a sound file (known as an \"auditory icon\") to be played by speech media agents after presenting an element's content; the volume at which the file should be played may also be specified. The shorthand property cue sets cue sounds for both before and after the element is presented.\n         */\n        cueAfter?: any;\n\n        /**\n         * The direction CSS property specifies the text direction/writing direction. The rtl is used for Hebrew or Arabic text, the ltr is for other languages.\n         */\n        direction?: any;\n\n        /**\n         * This property specifies the type of rendering box used for an element. It is a shorthand property for many other display properties.\n         */\n        display?: any;\n\n        /**\n         * The ‘fill’ property paints the interior of the given graphical element. The area to be painted consists of any areas inside the outline of the shape. To determine the inside of the shape, all subpaths are considered, and the interior is determined according to the rules associated with the current value of the ‘fill-rule’ property. The zero-width geometric outline of a shape is included in the area to be painted.\n         */\n        fill?: any;\n\n        /**\n         * The ‘fill-rule’ property indicates the algorithm which is to be used to determine what parts of the canvas are included inside the shape. For a simple, non-intersecting path, it is intuitively clear what region lies \"inside\"; however, for a more complex path, such as a path that intersects itself or where one subpath encloses another, the interpretation of \"inside\" is not so obvious.\n         * The ‘fill-rule’ property provides two options for how the inside of a shape is determined:\n         */\n        fillRule?: any;\n\n        /**\n         * Applies various image processing effects. This property is largely unsupported. See Compatibility section for more information.\n         */\n        filter?: any;\n\n        /**\n         * Obsolete, do not use. This property has been renamed to align-items.\n         * Specifies the alignment (perpendicular to the layout axis defined by the flex-direction property) of child elements of the object.\n         */\n        flexAlign?: any;\n\n        /**\n         * The flex-basis CSS property describes the initial main size of the flex item before any free space is distributed according to the flex factors described in the flex property (flex-grow and flex-shrink).\n         */\n        flexBasis?: any;\n\n        /**\n         * The flex-direction CSS property describes how flex items are placed in the flex container, by setting the direction of the flex container's main axis.\n         */\n        flexDirection?: any;\n\n        /**\n         * The flex-flow CSS property defines the flex container's main and cross axis. It is a shorthand property for the flex-direction and flex-wrap properties.\n         */\n        flexFlow?: any;\n\n        /**\n         * Do not use. This property has been renamed to align-self\n         * Specifies the alignment (perpendicular to the layout axis defined by flex-direction) of child elements of the object.\n         */\n        flexItemAlign?: any;\n\n        /**\n         * Do not use. This property has been renamed to align-content.\n         * Specifies how a flexbox's lines align within the flexbox when there is extra space along the axis that is perpendicular to the axis defined by the flex-direction property.\n         */\n        flexLinePack?: any;\n\n        /**\n         * Gets or sets a value that specifies the ordinal group that a flexbox element belongs to. This ordinal value identifies the display order for the group.\n         */\n        flexOrder?: any;\n\n        /**\n         * Elements which have the style float are floated horizontally. These elements can move as far to the left or right of the containing element. All elements after the floating element will flow around it, but elements before the floating element are not impacted. If several floating elements are placed after each other, they will float next to each other as long as there is room.\n         */\n        float?: any;\n\n        /**\n         * Flows content from a named flow (specified by a corresponding flow-into) through selected elements to form a dynamic chain of layout regions.\n         */\n        flowFrom?: any;\n\n        /**\n         * The font property is shorthand that allows you to do one of two things: you can either set up six of the most mature font properties in one line, or you can set one of a choice of keywords to adopt a system font setting.\n         */\n        font?: any;\n\n        /**\n         * The font-family property allows one or more font family names and/or generic family names to be specified for usage on the selected element(s)' text. The browser then goes through the list; for each character in the selection it applies the first font family that has an available glyph for that character.\n         */\n        fontFamily?: any;\n\n        /**\n         * The font-kerning property allows contextual adjustment of inter-glyph spacing, i.e. the spaces between the characters in text. This property controls <bold>metric kerning</bold> - that utilizes adjustment data contained in the font. Optical Kerning is not supported as yet.\n         */\n        fontKerning?: any;\n\n        /**\n         * The font-size-adjust property adjusts the font-size of the fallback fonts defined with font-family, so that the x-height is the same no matter what font is used. This preserves the readability of the text when fallback happens.\n         */\n        fontSizeAdjust?: any;\n\n        /**\n         * Allows you to expand or condense the widths for a normal, condensed, or expanded font face.\n         */\n        fontStretch?: any;\n\n        /**\n         * The font-style property allows normal, italic, or oblique faces to be selected. Italic forms are generally cursive in nature while oblique faces are typically sloped versions of the regular face. Oblique faces can be simulated by artificially sloping the glyphs of the regular face.\n         */\n        fontStyle?: any;\n\n        /**\n         * This value specifies whether the user agent is allowed to synthesize bold or oblique font faces when a font family lacks bold or italic faces.\n         */\n        fontSynthesis?: any;\n\n        /**\n         * The font-variant property enables you to select the small-caps font within a font family.\n         */\n        fontVariant?: any;\n\n        /**\n         * Fonts can provide alternate glyphs in addition to default glyph for a character. This property provides control over the selection of these alternate glyphs.\n         */\n        fontVariantAlternates?: any;\n\n        /**\n         * Lays out one or more grid items bound by 4 grid lines. Shorthand for setting grid-column-start, grid-column-end, grid-row-start, and grid-row-end in a single declaration.\n         */\n        gridArea?: any;\n\n        /**\n         * Controls a grid item's placement in a grid area, particularly grid position and a grid span. Shorthand for setting grid-column-start and grid-column-end in a single declaration.\n         */\n        gridColumn?: any;\n\n        /**\n         * Controls a grid item's placement in a grid area as well as grid position and a grid span. The grid-column-end property (with grid-row-start, grid-row-end, and grid-column-start) determines a grid item's placement by specifying the grid lines of a grid item's grid area.\n         */\n        gridColumnEnd?: any;\n\n        /**\n         * Determines a grid item's placement by specifying the starting grid lines of a grid item's grid area . A grid item's placement in a grid area consists of a grid position and a grid span. See also ( grid-row-start, grid-row-end, and grid-column-end)\n         */\n        gridColumnStart?: any;\n\n        /**\n         * Gets or sets a value that indicates which row an element within a Grid should appear in. Shorthand for setting grid-row-start and grid-row-end in a single declaration.\n         */\n        gridRow?: any;\n\n        /**\n         * Determines a grid item’s placement by specifying the block-end. A grid item's placement in a grid area consists of a grid position and a grid span. The grid-row-end property (with grid-row-start, grid-column-start, and grid-column-end) determines a grid item's placement by specifying the grid lines of a grid item's grid area.\n         */\n        gridRowEnd?: any;\n\n        /**\n         * Specifies a row position based upon an integer location, string value, or desired row size.\n         * css/properties/grid-row is used as short-hand for grid-row-position and grid-row-position\n         */\n        gridRowPosition?: any;\n\n        gridRowSpan?: any;\n\n        /**\n         * Specifies named grid areas which are not associated with any particular grid item, but can be referenced from the grid-placement properties. The syntax of the grid-template-areas property also provides a visualization of the structure of the grid, making the overall layout of the grid container easier to understand.\n         */\n        gridTemplateAreas?: any;\n\n        /**\n         * Specifies (with grid-template-rows) the line names and track sizing functions of the grid. Each sizing function can be specified as a length, a percentage of the grid container’s size, a measurement of the contents occupying the column or row, or a fraction of the free space in the grid.\n         */\n        gridTemplateColumns?: any;\n\n        /**\n         * Specifies (with grid-template-columns) the line names and track sizing functions of the grid. Each sizing function can be specified as a length, a percentage of the grid container’s size, a measurement of the contents occupying the column or row, or a fraction of the free space in the grid.\n         */\n        gridTemplateRows?: any;\n\n        /**\n         * Sets the height of an element. The content area of the element height does not include the padding, border, and margin of the element.\n         */\n        height?: any;\n\n        /**\n         * Specifies the minimum number of characters in a hyphenated word\n         */\n        hyphenateLimitChars?: any;\n\n        /**\n         * Indicates the maximum number of successive hyphenated lines in an element. The ‘no-limit’ value means that there is no limit.\n         */\n        hyphenateLimitLines?: any;\n\n        /**\n         * Specifies the maximum amount of trailing whitespace (before justification) that may be left in a line before hyphenation is triggered to pull part of a word from the next line back up into the current one.\n         */\n        hyphenateLimitZone?: any;\n\n        /**\n         * Specifies whether or not words in a sentence can be split by the use of a manual or automatic hyphenation mechanism.\n         */\n        hyphens?: any;\n\n        imeMode?: any;\n\n        layoutGrid?: any;\n\n        layoutGridChar?: any;\n\n        layoutGridLine?: any;\n\n        layoutGridMode?: any;\n\n        layoutGridType?: any;\n\n        /**\n         * Sets the left edge of an element\n         */\n        left?: any;\n\n        /**\n         * The letter-spacing CSS property specifies the spacing behavior between text characters.\n         */\n        letterSpacing?: any;\n\n        /**\n         * Deprecated. Gets or sets line-breaking rules for text in selected languages such as Japanese, Chinese, and Korean.\n         */\n        lineBreak?: any;\n\n        /**\n         * Shorthand property that sets the list-style-type, list-style-position and list-style-image properties in one declaration.\n         */\n        listStyle?: any;\n\n        /**\n         * This property sets the image that will be used as the list item marker. When the image is available, it will replace the marker set with the 'list-style-type' marker. That also means that if the image is not available, it will show the style specified by list-style-property\n         */\n        listStyleImage?: any;\n\n        /**\n         * Specifies if the list-item markers should appear inside or outside the content flow.\n         */\n        listStylePosition?: any;\n\n        /**\n         * Specifies the type of list-item marker in a list.\n         */\n        listStyleType?: any;\n\n        /**\n         * The margin property is shorthand to allow you to set all four margins of an element at once. Its equivalent longhand properties are margin-top, margin-right, margin-bottom and margin-left. Negative values are also allowed.\n         */\n        margin?: any;\n\n        /**\n         * margin-bottom sets the bottom margin of an element.\n         */\n        marginBottom?: any;\n\n        /**\n         * margin-left sets the left margin of an element.\n         */\n        marginLeft?: any;\n\n        /**\n         * margin-right sets the right margin of an element.\n         */\n        marginRight?: any;\n\n        /**\n         * margin-top sets the top margin of an element.\n         */\n        marginTop?: any;\n\n        /**\n         * The marquee-direction determines the initial direction in which the marquee content moves.\n         */\n        marqueeDirection?: any;\n\n        /**\n         * The 'marquee-style' property determines a marquee's scrolling behavior.\n         */\n        marqueeStyle?: any;\n\n        /**\n         * This property is shorthand for setting mask-image, mask-mode, mask-repeat, mask-position, mask-clip, mask-origin, mask-composite and mask-size. Omitted values are set to their original properties' initial values.\n         */\n        mask?: any;\n\n        /**\n         * This property is shorthand for setting mask-border-source, mask-border-slice, mask-border-width, mask-border-outset, and mask-border-repeat. Omitted values are set to their original properties' initial values.\n         */\n        maskBorder?: any;\n\n        /**\n         * This property specifies how the images for the sides and the middle part of the mask image are scaled and tiled. The first keyword applies to the horizontal sides, the second one applies to the vertical ones. If the second keyword is absent, it is assumed to be the same as the first, similar to the CSS border-image-repeat property.\n         */\n        maskBorderRepeat?: any;\n\n        /**\n         * This property specifies inward offsets from the top, right, bottom, and left edges of the mask image, dividing it into nine regions: four corners, four edges, and a middle. The middle image part is discarded and treated as fully transparent black unless the fill keyword is present. The four values set the top, right, bottom and left offsets in that order, similar to the CSS border-image-slice property.\n         */\n        maskBorderSlice?: any;\n\n        /**\n         * Specifies an image to be used as a mask. An image that is empty, fails to download, is non-existent, or cannot be displayed is ignored and does not mask the element.\n         */\n        maskBorderSource?: any;\n\n        /**\n         * This property sets the width of the mask box image, similar to the CSS border-image-width property.\n         */\n        maskBorderWidth?: any;\n\n        /**\n         * Determines the mask painting area, which defines the area that is affected by the mask. The painted content of an element may be restricted to this area.\n         */\n        maskClip?: any;\n\n        /**\n         * For elements rendered as a single box, specifies the mask positioning area. For elements rendered as multiple boxes (e.g., inline boxes on several lines, boxes on several pages) specifies which boxes box-decoration-break operates on to determine the mask positioning area(s).\n         */\n        maskOrigin?: any;\n\n        /**\n         * This property must not be used. It is no longer included in any standard or standard track specification, nor is it implemented in any browser. It is only used when the text-align-last property is set to size. It controls allowed adjustments of font-size to fit line content.\n         */\n        maxFontSize?: any;\n\n        /**\n         * Sets the maximum height for an element. It prevents the height of the element to exceed the specified value. If min-height is specified and is greater than max-height, max-height is overridden.\n         */\n        maxHeight?: any;\n\n        /**\n         * Sets the maximum width for an element. It limits the width property to be larger than the value specified in max-width.\n         */\n        maxWidth?: any;\n\n        /**\n         * Sets the minimum height for an element. It prevents the height of the element to be smaller than the specified value. The value of min-height overrides both max-height and height.\n         */\n        minHeight?: any;\n\n        /**\n         * Sets the minimum width of an element. It limits the width property to be not smaller than the value specified in min-width.\n         */\n        minWidth?: any;\n\n        /**\n         * The CSS outline property is a shorthand property for setting one or more of the individual outline properties outline-style, outline-width and outline-color in a single rule. In most cases the use of this shortcut is preferable and more convenient.\n         * Outlines differ from borders in the following ways:  •       Outlines do not take up space, they are drawn above the content.\n         *      •       Outlines may be non-rectangular. They are rectangular in Gecko/Firefox. Internet Explorer attempts to place the smallest contiguous outline around all elements or shapes that are indicated to have an outline. Opera draws a non-rectangular shape around a construct.\n         */\n        outline?: any;\n\n        /**\n         * The outline-color property sets the color of the outline of an element. An outline is a line that is drawn around elements, outside the border edge, to make the element stand out.\n         */\n        outlineColor?: any;\n\n        /**\n         * The outline-offset property offsets the outline and draw it beyond the border edge.\n         */\n        outlineOffset?: any;\n\n        /**\n         * The overflow property controls how extra content exceeding the bounding box of an element is rendered. It can be used in conjunction with an element that has a fixed width and height, to eliminate text-induced page distortion.\n         */\n        overflow?: any;\n\n        /**\n         * Specifies the preferred scrolling methods for elements that overflow.\n         */\n        overflowStyle?: any;\n\n        /**\n         * The overflow-x property is a specific case of the generic overflow property. It controls how extra content exceeding the x-axis of the bounding box of an element is rendered.\n         */\n        overflowX?: any;\n\n        /**\n         * The padding optional CSS property sets the required padding space on one to four sides of an element. The padding area is the space between an element and its border. Negative values are not allowed but decimal values are permitted. The element size is treated as fixed, and the content of the element shifts toward the center as padding is increased.\n         * The padding property is a shorthand to avoid setting each side separately (padding-top, padding-right, padding-bottom, padding-left).\n         */\n        padding?: any;\n\n        /**\n         * The padding-bottom CSS property of an element sets the padding space required on the bottom of an element. The padding area is the space between the content of the element and its border. Contrary to margin-bottom values, negative values of padding-bottom are invalid.\n         */\n        paddingBottom?: any;\n\n        /**\n         * The padding-left CSS property of an element sets the padding space required on the left side of an element. The padding area is the space between the content of the element and its border. Contrary to margin-left values, negative values of padding-left are invalid.\n         */\n        paddingLeft?: any;\n\n        /**\n         * The padding-right CSS property of an element sets the padding space required on the right side of an element. The padding area is the space between the content of the element and its border. Contrary to margin-right values, negative values of padding-right are invalid.\n         */\n        paddingRight?: any;\n\n        /**\n         * The padding-top CSS property of an element sets the padding space required on the top of an element. The padding area is the space between the content of the element and its border. Contrary to margin-top values, negative values of padding-top are invalid.\n         */\n        paddingTop?: any;\n\n        /**\n         * The page-break-after property is supported in all major browsers. With CSS3, page-break-* properties are only aliases of the break-* properties. The CSS3 Fragmentation spec defines breaks for all CSS box fragmentation.\n         */\n        pageBreakAfter?: any;\n\n        /**\n         * The page-break-before property sets the page-breaking behavior before an element. With CSS3, page-break-* properties are only aliases of the break-* properties. The CSS3 Fragmentation spec defines breaks for all CSS box fragmentation.\n         */\n        pageBreakBefore?: any;\n\n        /**\n         * Sets the page-breaking behavior inside an element. With CSS3, page-break-* properties are only aliases of the break-* properties. The CSS3 Fragmentation spec defines breaks for all CSS box fragmentation.\n         */\n        pageBreakInside?: any;\n\n        /**\n         * The pause property determines how long a speech media agent should pause before and after presenting an element. It is a shorthand for the pause-before and pause-after properties.\n         */\n        pause?: any;\n\n        /**\n         * The pause-after property determines how long a speech media agent should pause after presenting an element. It may be replaced by the shorthand property pause, which sets pause time before and after.\n         */\n        pauseAfter?: any;\n\n        /**\n         * The pause-before property determines how long a speech media agent should pause before presenting an element. It may be replaced by the shorthand property pause, which sets pause time before and after.\n         */\n        pauseBefore?: any;\n\n        /**\n         * The perspective property defines how far an element is placed from the view on the z-axis, from the screen to the viewer.\n         * Perspective defines how an object is viewed. In graphic arts, perspective is the representation on a flat surface of what the viewer's eye would see in a 3D space. (See Wikipedia for more information about graphical perspective and for related illustrations.)\n         * The illusion of perspective on a flat surface, such as a computer screen, is created by projecting points on the flat surface as they would appear if the flat surface were a window through which the viewer was looking at the object. In discussion of virtual environments, this flat surface is called a projection plane.\n         */\n        perspective?: any;\n\n        /**\n         * The perspective-origin property establishes the origin for the perspective property. It effectively sets the X and Y position at which the viewer appears to be looking at the children of the element.\n         * When used with perspective, perspective-origin changes the appearance of an object, as if a viewer were looking at it from a different origin. An object appears differently if a viewer is looking directly at it versus looking at it from below, above, or from the side. Thus, the perspective-origin is like a vanishing point.\n         * The default value of perspective-origin is 50% 50%. This displays an object as if the viewer's eye were positioned directly at the center of the screen, both top-to-bottom and left-to-right. A value of 0% 0% changes the object as if the viewer was looking toward the top left angle. A value of 100% 100% changes the appearance as if viewed toward the bottom right angle.\n         */\n        perspectiveOrigin?: any;\n\n        /**\n         * The pointer-events property allows you to control whether an element can be the target for the pointing device (e.g, mouse, pen) events.\n         */\n        pointerEvents?: any;\n\n        /**\n         * The position property controls the type of positioning used by an element within its parent elements. The effect of the position property depends on a lot of factors, for example the position property of parent elements.\n         */\n        position?: any;\n\n        /**\n         * Obsolete: unsupported.\n         * This property determines whether or not a full-width punctuation mark character should be trimmed if it appears at the beginning of a line, so that its \"ink\" lines up with the first glyph in the line above and below.\n         */\n        punctuationTrim?: any;\n\n        /**\n         * Sets the type of quotation marks for embedded quotations.\n         */\n        quotes?: any;\n\n        /**\n         * Controls whether the last region in a chain displays additional 'overset' content according its default overflow property, or if it displays a fragment of content as if it were flowing into a subsequent region.\n         */\n        regionFragment?: any;\n\n        /**\n         * The rest-after property determines how long a speech media agent should pause after presenting an element's main content, before presenting that element's exit cue sound. It may be replaced by the shorthand property rest, which sets rest time before and after.\n         */\n        restAfter?: any;\n\n        /**\n         * The rest-before property determines how long a speech media agent should pause after presenting an intro cue sound for an element, before presenting that element's main content. It may be replaced by the shorthand property rest, which sets rest time before and after.\n         */\n        restBefore?: any;\n\n        /**\n         * Specifies the position an element in relation to the right side of the containing element.\n         */\n        right?: any;\n\n        rubyAlign?: any;\n\n        rubyPosition?: any;\n\n        /**\n         * Defines the alpha channel threshold used to extract a shape from an image. Can be thought of as a \"minimum opacity\" threshold; that is, a value of 0.5 means that the shape will enclose all the pixels that are more than 50% opaque.\n         */\n        shapeImageThreshold?: any;\n\n        /**\n         * A future level of CSS Shapes will define a shape-inside property, which will define a shape to wrap content within the element. See Editor's Draft <http://dev.w3.org/csswg/css-shapes/> and CSSWG wiki page on next-level plans <http://wiki.csswg.org/spec/css-shapes>\n         */\n        shapeInside?: any;\n\n        /**\n         * Adds a margin to a shape-outside. In effect, defines a new shape that is the smallest contour around all the points that are the shape-margin distance outward perpendicular to each point on the underlying shape. For points where a perpendicular direction is not defined (e.g., a triangle corner), takes all points on a circle centered at the point and with a radius of the shape-margin distance. This property accepts only non-negative values.\n         */\n        shapeMargin?: any;\n\n        /**\n         * Declares a shape around which text should be wrapped, with possible modifications from the shape-margin property. The shape defined by shape-outside and shape-margin changes the geometry of a float element's float area.\n         */\n        shapeOutside?: any;\n\n        /**\n         * The speak property determines whether or not a speech synthesizer will read aloud the contents of an element.\n         */\n        speak?: any;\n\n        /**\n         * The speak-as property determines how the speech synthesizer interprets the content: words as whole words or as a sequence of letters, numbers as a numerical value or a sequence of digits, punctuation as pauses in speech or named punctuation characters.\n         */\n        speakAs?: any;\n\n        /**\n         * The tab-size CSS property is used to customise the width of a tab (U+0009) character.\n         */\n        tabSize?: any;\n\n        /**\n         * The 'table-layout' property controls the algorithm used to lay out the table cells, rows, and columns.\n         */\n        tableLayout?: any;\n\n        /**\n         * The text-align CSS property describes how inline content like text is aligned in its parent block element. text-align does not control the alignment of block elements itself, only their inline content.\n         */\n        textAlign?: any;\n\n        /**\n         * The text-align-last CSS property describes how the last line of a block element or a line before line break is aligned in its parent block element.\n         */\n        textAlignLast?: any;\n\n        /**\n         * The text-decoration CSS property is used to set the text formatting to underline, overline, line-through or blink. \n         * underline and overline decorations are positioned under the text, line-through over it.\n         */\n        textDecoration?: any;\n\n        /**\n         * Sets the color of any text decoration, such as underlines, overlines, and strike throughs.\n         */\n        textDecorationColor?: any;\n\n        /**\n         * Sets what kind of line decorations are added to an element, such as underlines, overlines, etc.\n         */\n        textDecorationLine?: any;\n\n        textDecorationLineThrough?: any;\n\n        textDecorationNone?: any;\n\n        textDecorationOverline?: any;\n\n        /**\n         * Specifies what parts of an element’s content are skipped over when applying any text decoration.\n         */\n        textDecorationSkip?: any;\n\n        /**\n         * This property specifies the style of the text decoration line drawn on the specified element. The intended meaning for the values are the same as those of the border-style-properties.\n         */\n        textDecorationStyle?: any;\n\n        textDecorationUnderline?: any;\n\n        /**\n         * The text-emphasis property will apply special emphasis marks to the elements text. Slightly similar to the text-decoration property only that this property can have affect on the line-height. It also is noted that this is shorthand for text-emphasis-style and for text-emphasis-color.\n         */\n        textEmphasis?: any;\n\n        /**\n         * The text-emphasis-color property specifies the foreground color of the emphasis marks.\n         */\n        textEmphasisColor?: any;\n\n        /**\n         * The text-emphasis-style property applies special emphasis marks to an element's text.\n         */\n        textEmphasisStyle?: any;\n\n        /**\n         * This property helps determine an inline box's block-progression dimension, derived from the text-height and font-size properties for non-replaced elements, the height or the width for replaced elements, and the stacked block-progression dimension for inline-block elements. The block-progression dimension determines the position of the padding, border and margin for the element.\n         */\n        textHeight?: any;\n\n        /**\n         * Specifies the amount of space horizontally that should be left on the first line of the text of an element. This horizontal spacing is at the beginning of the first line and is in respect to the left edge of the containing block box.\n         */\n        textIndent?: any;\n\n        textJustifyTrim?: any;\n\n        textKashidaSpace?: any;\n\n        /**\n         * The text-line-through property is a shorthand property for text-line-through-style, text-line-through-color and text-line-through-mode. (Considered obsolete; use text-decoration instead.)\n         */\n        textLineThrough?: any;\n\n        /**\n         * Specifies the line colors for the line-through text decoration.\n         * (Considered obsolete; use text-decoration-color instead.)\n         */\n        textLineThroughColor?: any;\n\n        /**\n         * Sets the mode for the line-through text decoration, determining whether the text decoration affects the space characters or not.\n         * (Considered obsolete; use text-decoration-skip instead.)\n         */\n        textLineThroughMode?: any;\n\n        /**\n         * Specifies the line style for line-through text decoration.\n         * (Considered obsolete; use text-decoration-style instead.)\n         */\n        textLineThroughStyle?: any;\n\n        /**\n         * Specifies the line width for the line-through text decoration.\n         */\n        textLineThroughWidth?: any;\n\n        /**\n         * The text-overflow shorthand CSS property determines how overflowed content that is not displayed is signaled to the users. It can be clipped, display an ellipsis ('…', U+2026 HORIZONTAL ELLIPSIS) or a Web author-defined string. It covers the two long-hand properties text-overflow-mode and text-overflow-ellipsis\n         */\n        textOverflow?: any;\n\n        /**\n         * The text-overline property is the shorthand for the text-overline-style, text-overline-width, text-overline-color, and text-overline-mode properties.\n         */\n        textOverline?: any;\n\n        /**\n         * Specifies the line color for the overline text decoration.\n         */\n        textOverlineColor?: any;\n\n        /**\n         * Sets the mode for the overline text decoration, determining whether the text decoration affects the space characters or not.\n         */\n        textOverlineMode?: any;\n\n        /**\n         * Specifies the line style for overline text decoration.\n         */\n        textOverlineStyle?: any;\n\n        /**\n         * Specifies the line width for the overline text decoration.\n         */\n        textOverlineWidth?: any;\n\n        /**\n         * The text-rendering CSS property provides information to the browser about how to optimize when rendering text. Options are: legibility, speed or geometric precision.\n         */\n        textRendering?: any;\n\n        /**\n         * Obsolete: unsupported.\n         */\n        textScript?: any;\n\n        /**\n         * The CSS text-shadow property applies one or more drop shadows to the text and <text-decorations> of an element. Each shadow is specified as an offset from the text, along with optional color and blur radius values.\n         */\n        textShadow?: any;\n\n        /**\n         * This property transforms text for styling purposes. (It has no effect on the underlying content.)\n         */\n        textTransform?: any;\n\n        /**\n         * Unsupported.\n         * This property will add a underline position value to the element that has an underline defined.\n         */\n        textUnderlinePosition?: any;\n\n        /**\n         * After review this should be replaced by text-decoration should it not?\n         * This property will set the underline style for text with a line value for underline, overline, and line-through.\n         */\n        textUnderlineStyle?: any;\n\n        /**\n         * This property specifies how far an absolutely positioned box's top margin edge is offset below the top edge of the box's containing block. For relatively positioned boxes, the offset is with respect to the top edges of the box itself (i.e., the box is given a position in the normal flow, then offset from that position according to these properties).\n         */\n        top?: any;\n\n        /**\n         * Determines whether touch input may trigger default behavior supplied by the user agent, such as panning or zooming.\n         */\n        touchAction?: any;\n\n        /**\n         * CSS transforms allow elements styled with CSS to be transformed in two-dimensional or three-dimensional space. Using this property, elements can be translated, rotated, scaled, and skewed. The value list may consist of 2D and/or 3D transform values.\n         */\n        transform?: any;\n\n        /**\n         * This property defines the origin of the transformation axes relative to the element to which the transformation is applied.\n         */\n        transformOrigin?: any;\n\n        /**\n         * This property allows you to define the relative position of the origin of the transformation grid along the z-axis.\n         */\n        transformOriginZ?: any;\n\n        /**\n         * This property specifies how nested elements are rendered in 3D space relative to their parent.\n         */\n        transformStyle?: any;\n\n        /**\n         * The transition CSS property is a shorthand property for transition-property, transition-duration, transition-timing-function, and transition-delay. It allows to define the transition between two states of an element.\n         */\n        transition?: any;\n\n        /**\n         * Defines when the transition will start. A value of ‘0s’ means the transition will execute as soon as the property is changed. Otherwise, the value specifies an offset from the moment the property is changed, and the transition will delay execution by that offset.\n         */\n        transitionDelay?: any;\n\n        /**\n         * The 'transition-duration' property specifies the length of time a transition animation takes to complete.\n         */\n        transitionDuration?: any;\n\n        /**\n         * The 'transition-property' property specifies the name of the CSS property to which the transition is applied.\n         */\n        transitionProperty?: any;\n\n        /**\n         * Sets the pace of action within a transition\n         */\n        transitionTimingFunction?: any;\n\n        /**\n         * The unicode-bidi CSS property specifies the level of embedding with respect to the bidirectional algorithm.\n         */\n        unicodeBidi?: any;\n\n        /**\n         * unicode-range allows you to set a specific range of characters to be downloaded from a font (embedded using @font-face) and made available for use on the current page.\n         */\n        unicodeRange?: any;\n\n        /**\n         * This is for all the high level UX stuff.\n         */\n        userFocus?: any;\n\n        /**\n         * For inputing user content\n         */\n        userInput?: any;\n\n        /**\n         * The vertical-align property controls how inline elements or text are vertically aligned compared to the baseline. If this property is used on table-cells it controls the vertical alignment of content of the table cell.\n         */\n        verticalAlign?: any;\n\n        /**\n         * The visibility property specifies whether the boxes generated by an element are rendered.\n         */\n        visibility?: any;\n\n        /**\n         * The voice-balance property sets the apparent position (in stereo sound) of the synthesized voice for spoken media.\n         */\n        voiceBalance?: any;\n\n        /**\n         * The voice-duration property allows the author to explicitly set the amount of time it should take a speech synthesizer to read an element's content, for example to allow the speech to be synchronized with other media. With a value of auto (the default) the length of time it takes to read the content is determined by the content itself and the voice-rate property.\n         */\n        voiceDuration?: any;\n\n        /**\n         * The voice-family property sets the speaker's voice used by a speech media agent to read an element. The speaker may be specified as a named character (to match a voice option in the speech reading software) or as a generic description of the age and gender of the voice. Similar to the font-family property for visual media, a comma-separated list of fallback options may be given in case the speech reader does not recognize the character name or cannot synthesize the requested combination of generic properties.\n         */\n        voiceFamily?: any;\n\n        /**\n         * The voice-pitch property sets pitch or tone (high or low) for the synthesized speech when reading an element; the pitch may be specified absolutely or relative to the normal pitch for the voice-family used to read the text.\n         */\n        voicePitch?: any;\n\n        /**\n         * The voice-range property determines how much variation in pitch or tone will be created by the speech synthesize when reading an element. Emphasized text, grammatical structures and punctuation may all be rendered as changes in pitch, this property determines how strong or obvious those changes are; large ranges are associated with enthusiastic or emotional speech, while small ranges are associated with flat or mechanical speech.\n         */\n        voiceRange?: any;\n\n        /**\n         * The voice-rate property sets the speed at which the voice synthesized by a speech media agent will read content.\n         */\n        voiceRate?: any;\n\n        /**\n         * The voice-stress property sets the level of vocal emphasis to be used for synthesized speech reading the element.\n         */\n        voiceStress?: any;\n\n        /**\n         * The voice-volume property sets the volume for spoken content in speech media. It replaces the deprecated volume property.\n         */\n        voiceVolume?: any;\n\n        /**\n         * The white-space property controls whether and how white space inside the element is collapsed, and whether lines may wrap at unforced \"soft wrap\" opportunities.\n         */\n        whiteSpace?: any;\n\n        /**\n         * Obsolete: unsupported.\n         */\n        whiteSpaceTreatment?: any;\n\n        /**\n         * Specifies the width of the content area of an element. The content area of the element width does not include the padding, border, and margin of the element.\n         */\n        width?: any;\n\n        /**\n         * The word-break property is often used when there is long generated content that is strung together without and spaces or hyphens to beak apart. A common case of this is when there is a long URL that does not have any hyphens. This case could potentially cause the breaking of the layout as it could extend past the parent element.\n         */\n        wordBreak?: any;\n\n        /**\n         * The word-spacing CSS property specifies the spacing behavior between \"words\".\n         */\n        wordSpacing?: any;\n\n        /**\n         * An alias of css/properties/overflow-wrap, word-wrap defines whether to break words when the content exceeds the boundaries of its container.\n         */\n        wordWrap?: any;\n\n        /**\n         * Specifies how exclusions affect inline content within block-level elements. Elements lay out their inline content in their content area but wrap around exclusion areas.\n         */\n        wrapFlow?: any;\n\n        /**\n         * Set the value that is used to offset the inner wrap shape from other shapes. Inline content that intersects a shape with this property will be pushed by this shape's margin.\n         */\n        wrapMargin?: any;\n\n        /**\n         * Obsolete and unsupported. Do not use.\n         * This CSS property controls the text when it reaches the end of the block in which it is enclosed.\n         */\n        wrapOption?: any;\n\n        /**\n         * writing-mode specifies if lines of text are laid out horizontally or vertically, and the direction which lines of text and blocks progress.\n         */\n        writingMode?: any;\n\n\n        [propertyName: string]: any;\n    }\n\n    interface HTMLAttributes extends DOMAttributes {\n        // React-specific Attributes\n        defaultChecked?: boolean;\n        defaultValue?: string | string[];\n\n        // Standard HTML Attributes\n        accept?: string;\n        acceptCharset?: string;\n        accessKey?: string;\n        action?: string;\n        allowFullScreen?: boolean;\n        allowTransparency?: boolean;\n        alt?: string;\n        async?: boolean;\n        autoComplete?: string;\n        autoFocus?: boolean;\n        autoPlay?: boolean;\n        capture?: boolean;\n        cellPadding?: number | string;\n        cellSpacing?: number | string;\n        charSet?: string;\n        challenge?: string;\n        checked?: boolean;\n        classID?: string;\n        className?: string;\n        cols?: number;\n        colSpan?: number;\n        content?: string;\n        contentEditable?: boolean;\n        contextMenu?: string;\n        controls?: boolean;\n        coords?: string;\n        crossOrigin?: string;\n        data?: string;\n        dateTime?: string;\n        default?: boolean;\n        defer?: boolean;\n        dir?: string;\n        disabled?: boolean;\n        download?: any;\n        draggable?: boolean;\n        encType?: string;\n        form?: string;\n        formAction?: string;\n        formEncType?: string;\n        formMethod?: string;\n        formNoValidate?: boolean;\n        formTarget?: string;\n        frameBorder?: number | string;\n        headers?: string;\n        height?: number | string;\n        hidden?: boolean;\n        high?: number;\n        href?: string;\n        hrefLang?: string;\n        htmlFor?: string;\n        httpEquiv?: string;\n        icon?: string;\n        id?: string;\n        inputMode?: string;\n        integrity?: string;\n        is?: string;\n        keyParams?: string;\n        keyType?: string;\n        kind?: string;\n        label?: string;\n        lang?: string;\n        list?: string;\n        loop?: boolean;\n        low?: number;\n        manifest?: string;\n        marginHeight?: number;\n        marginWidth?: number;\n        max?: number | string;\n        maxLength?: number;\n        media?: string;\n        mediaGroup?: string;\n        method?: string;\n        min?: number | string;\n        minLength?: number;\n        multiple?: boolean;\n        muted?: boolean;\n        name?: string;\n        noValidate?: boolean;\n        open?: boolean;\n        optimum?: number;\n        pattern?: string;\n        placeholder?: string;\n        poster?: string;\n        preload?: string;\n        radioGroup?: string;\n        readOnly?: boolean;\n        rel?: string;\n        required?: boolean;\n        role?: string;\n        rows?: number;\n        rowSpan?: number;\n        sandbox?: string;\n        scope?: string;\n        scoped?: boolean;\n        scrolling?: string;\n        seamless?: boolean;\n        selected?: boolean;\n        shape?: string;\n        size?: number;\n        sizes?: string;\n        span?: number;\n        spellCheck?: boolean;\n        src?: string;\n        srcDoc?: string;\n        srcLang?: string;\n        srcSet?: string;\n        start?: number;\n        step?: number | string;\n        style?: CSSProperties;\n        summary?: string;\n        tabIndex?: number;\n        target?: string;\n        title?: string;\n        type?: string;\n        useMap?: string;\n        value?: string | string[];\n        width?: number | string;\n        wmode?: string;\n        wrap?: string;\n\n        // RDFa Attributes\n        about?: string;\n        datatype?: string;\n        inlist?: any;\n        prefix?: string;\n        property?: string;\n        resource?: string;\n        typeof?: string;\n        vocab?: string;\n\n        // Non-standard Attributes\n        autoCapitalize?: string;\n        autoCorrect?: string;\n        autoSave?: string;\n        color?: string;\n        itemProp?: string;\n        itemScope?: boolean;\n        itemType?: string;\n        itemID?: string;\n        itemRef?: string;\n        results?: number;\n        security?: string;\n        unselectable?: boolean;\n    }\n\n    interface SVGAttributes extends HTMLAttributes {\n        clipPath?: string;\n        cx?: number | string;\n        cy?: number | string;\n        d?: string;\n        dx?: number | string;\n        dy?: number | string;\n        fill?: string;\n        fillOpacity?: number | string;\n        fontFamily?: string;\n        fontSize?: number | string;\n        fx?: number | string;\n        fy?: number | string;\n        gradientTransform?: string;\n        gradientUnits?: string;\n        markerEnd?: string;\n        markerMid?: string;\n        markerStart?: string;\n        offset?: number | string;\n        opacity?: number | string;\n        patternContentUnits?: string;\n        patternUnits?: string;\n        points?: string;\n        preserveAspectRatio?: string;\n        r?: number | string;\n        rx?: number | string;\n        ry?: number | string;\n        spreadMethod?: string;\n        stopColor?: string;\n        stopOpacity?: number | string;\n        stroke?: string;\n        strokeDasharray?: string;\n        strokeLinecap?: string;\n        strokeMiterlimit?: string;\n        strokeOpacity?: number | string;\n        strokeWidth?: number | string;\n        textAnchor?: string;\n        transform?: string;\n        version?: string;\n        viewBox?: string;\n        x1?: number | string;\n        x2?: number | string;\n        x?: number | string;\n        xlinkActuate?: string;\n        xlinkArcrole?: string;\n        xlinkHref?: string;\n        xlinkRole?: string;\n        xlinkShow?: string;\n        xlinkTitle?: string;\n        xlinkType?: string;\n        xmlBase?: string;\n        xmlLang?: string;\n        xmlSpace?: string;\n        y1?: number | string;\n        y2?: number | string;\n        y?: number | string;\n    }\n\n    //\n    // React.DOM\n    // ----------------------------------------------------------------------\n\n    interface ReactDOM {\n        // HTML\n        a: HTMLFactory;\n        abbr: HTMLFactory;\n        address: HTMLFactory;\n        area: HTMLFactory;\n        article: HTMLFactory;\n        aside: HTMLFactory;\n        audio: HTMLFactory;\n        b: HTMLFactory;\n        base: HTMLFactory;\n        bdi: HTMLFactory;\n        bdo: HTMLFactory;\n        big: HTMLFactory;\n        blockquote: HTMLFactory;\n        body: HTMLFactory;\n        br: HTMLFactory;\n        button: HTMLFactory;\n        canvas: HTMLFactory;\n        caption: HTMLFactory;\n        cite: HTMLFactory;\n        showapi_res_code: HTMLFactory;\n        col: HTMLFactory;\n        colgroup: HTMLFactory;\n        data: HTMLFactory;\n        datalist: HTMLFactory;\n        dd: HTMLFactory;\n        del: HTMLFactory;\n        details: HTMLFactory;\n        dfn: HTMLFactory;\n        dialog: HTMLFactory;\n        div: HTMLFactory;\n        dl: HTMLFactory;\n        dt: HTMLFactory;\n        em: HTMLFactory;\n        embed: HTMLFactory;\n        fieldset: HTMLFactory;\n        figcaption: HTMLFactory;\n        figure: HTMLFactory;\n        footer: HTMLFactory;\n        form: HTMLFactory;\n        h1: HTMLFactory;\n        h2: HTMLFactory;\n        h3: HTMLFactory;\n        h4: HTMLFactory;\n        h5: HTMLFactory;\n        h6: HTMLFactory;\n        head: HTMLFactory;\n        header: HTMLFactory;\n        hr: HTMLFactory;\n        html: HTMLFactory;\n        i: HTMLFactory;\n        iframe: HTMLFactory;\n        img: HTMLFactory;\n        input: HTMLFactory;\n        ins: HTMLFactory;\n        kbd: HTMLFactory;\n        keygen: HTMLFactory;\n        label: HTMLFactory;\n        legend: HTMLFactory;\n        li: HTMLFactory;\n        link: HTMLFactory;\n        main: HTMLFactory;\n        map: HTMLFactory;\n        mark: HTMLFactory;\n        menu: HTMLFactory;\n        menuitem: HTMLFactory;\n        meta: HTMLFactory;\n        meter: HTMLFactory;\n        nav: HTMLFactory;\n        noscript: HTMLFactory;\n        object: HTMLFactory;\n        ol: HTMLFactory;\n        optgroup: HTMLFactory;\n        option: HTMLFactory;\n        output: HTMLFactory;\n        p: HTMLFactory;\n        param: HTMLFactory;\n        picture: HTMLFactory;\n        pre: HTMLFactory;\n        progress: HTMLFactory;\n        q: HTMLFactory;\n        rp: HTMLFactory;\n        rt: HTMLFactory;\n        ruby: HTMLFactory;\n        s: HTMLFactory;\n        samp: HTMLFactory;\n        script: HTMLFactory;\n        section: HTMLFactory;\n        select: HTMLFactory;\n        small: HTMLFactory;\n        source: HTMLFactory;\n        span: HTMLFactory;\n        strong: HTMLFactory;\n        style: HTMLFactory;\n        sub: HTMLFactory;\n        summary: HTMLFactory;\n        sup: HTMLFactory;\n        table: HTMLFactory;\n        tbody: HTMLFactory;\n        td: HTMLFactory;\n        textarea: HTMLFactory;\n        tfoot: HTMLFactory;\n        th: HTMLFactory;\n        thead: HTMLFactory;\n        time: HTMLFactory;\n        title: HTMLFactory;\n        tr: HTMLFactory;\n        track: HTMLFactory;\n        u: HTMLFactory;\n        ul: HTMLFactory;\n        \"var\": HTMLFactory;\n        video: HTMLFactory;\n        wbr: HTMLFactory;\n\n        // SVG\n        svg: SVGFactory;\n        circle: SVGFactory;\n        defs: SVGFactory;\n        ellipse: SVGFactory;\n        g: SVGFactory;\n        image: SVGFactory;\n        line: SVGFactory;\n        linearGradient: SVGFactory;\n        mask: SVGFactory;\n        path: SVGFactory;\n        pattern: SVGFactory;\n        polygon: SVGFactory;\n        polyline: SVGFactory;\n        radialGradient: SVGFactory;\n        rect: SVGFactory;\n        stop: SVGFactory;\n        text: SVGFactory;\n        tspan: SVGFactory;\n    }\n\n    //\n    // React.PropTypes\n    // ----------------------------------------------------------------------\n\n    interface Validator<T> {\n        (object: T, key: string, componentName: string): Error;\n    }\n\n    interface Requireable<T> extends Validator<T> {\n        isRequired: Validator<T>;\n    }\n\n    interface ValidationMap<T> {\n        [key: string]: Validator<T>;\n    }\n\n    interface ReactPropTypes {\n        any: Requireable<any>;\n        array: Requireable<any>;\n        bool: Requireable<any>;\n        func: Requireable<any>;\n        number: Requireable<any>;\n        object: Requireable<any>;\n        string: Requireable<any>;\n        node: Requireable<any>;\n        element: Requireable<any>;\n        instanceOf(expectedClass: {}): Requireable<any>;\n        oneOf(types: any[]): Requireable<any>;\n        oneOfType(types: Validator<any>[]): Requireable<any>;\n        arrayOf(type: Validator<any>): Requireable<any>;\n        objectOf(type: Validator<any>): Requireable<any>;\n        shape(type: ValidationMap<any>): Requireable<any>;\n    }\n\n    //\n    // React.Children\n    // ----------------------------------------------------------------------\n\n    interface ReactChildren {\n        map<T>(children: ReactNode, fn: (child: ReactChild, index: number) => T): T[];\n        forEach(children: ReactNode, fn: (child: ReactChild, index: number) => any): void;\n        count(children: ReactNode): number;\n        only(children: ReactNode): ReactElement<any>;\n        toArray(children: ReactNode): ReactChild[];\n    }\n\n    //\n    // Browser Interfaces\n    // https://github.com/nikeee/2048-typescript/blob/master/2048/js/touch.d.ts\n    // ----------------------------------------------------------------------\n\n    interface AbstractView {\n        styleMedia: StyleMedia;\n        document: Document;\n    }\n\n    interface Touch {\n        identifier: number;\n        target: EventTarget;\n        screenX: number;\n        screenY: number;\n        clientX: number;\n        clientY: number;\n        pageX: number;\n        pageY: number;\n    }\n\n    interface TouchList {\n        [index: number]: Touch;\n        length: number;\n        item(index: number): Touch;\n        identifiedTouch(identifier: number): Touch;\n    }\n}\n\ndeclare module \"react\" {\n    export = __React;\n}\n\ndeclare namespace JSX {\n    import React = __React;\n\n    interface Element extends React.ReactElement<any> { }\n    interface ElementClass extends React.Component<any, any> {\n        render(): JSX.Element;\n    }\n    interface ElementAttributesProperty { props: {}; }\n\n    interface IntrinsicAttributes {\n        key?: string | number;\n    }\n\n    interface IntrinsicClassAttributes<T> {\n        ref?: string | ((classInstance: T) => void);\n    }\n\n    interface IntrinsicElements {\n        // HTML\n        a: React.HTMLProps<HTMLAnchorElement>;\n        abbr: React.HTMLProps<HTMLElement>;\n        address: React.HTMLProps<HTMLElement>;\n        area: React.HTMLProps<HTMLAreaElement>;\n        article: React.HTMLProps<HTMLElement>;\n        aside: React.HTMLProps<HTMLElement>;\n        audio: React.HTMLProps<HTMLAudioElement>;\n        b: React.HTMLProps<HTMLElement>;\n        base: React.HTMLProps<HTMLBaseElement>;\n        bdi: React.HTMLProps<HTMLElement>;\n        bdo: React.HTMLProps<HTMLElement>;\n        big: React.HTMLProps<HTMLElement>;\n        blockquote: React.HTMLProps<HTMLElement>;\n        body: React.HTMLProps<HTMLBodyElement>;\n        br: React.HTMLProps<HTMLBRElement>;\n        button: React.HTMLProps<HTMLButtonElement>;\n        canvas: React.HTMLProps<HTMLCanvasElement>;\n        caption: React.HTMLProps<HTMLElement>;\n        cite: React.HTMLProps<HTMLElement>;\n        showapi_res_code: React.HTMLProps<HTMLElement>;\n        col: React.HTMLProps<HTMLTableColElement>;\n        colgroup: React.HTMLProps<HTMLTableColElement>;\n        data: React.HTMLProps<HTMLElement>;\n        datalist: React.HTMLProps<HTMLDataListElement>;\n        dd: React.HTMLProps<HTMLElement>;\n        del: React.HTMLProps<HTMLElement>;\n        details: React.HTMLProps<HTMLElement>;\n        dfn: React.HTMLProps<HTMLElement>;\n        dialog: React.HTMLProps<HTMLElement>;\n        div: React.HTMLProps<HTMLDivElement>;\n        dl: React.HTMLProps<HTMLDListElement>;\n        dt: React.HTMLProps<HTMLElement>;\n        em: React.HTMLProps<HTMLElement>;\n        embed: React.HTMLProps<HTMLEmbedElement>;\n        fieldset: React.HTMLProps<HTMLFieldSetElement>;\n        figcaption: React.HTMLProps<HTMLElement>;\n        figure: React.HTMLProps<HTMLElement>;\n        footer: React.HTMLProps<HTMLElement>;\n        form: React.HTMLProps<HTMLFormElement>;\n        h1: React.HTMLProps<HTMLHeadingElement>;\n        h2: React.HTMLProps<HTMLHeadingElement>;\n        h3: React.HTMLProps<HTMLHeadingElement>;\n        h4: React.HTMLProps<HTMLHeadingElement>;\n        h5: React.HTMLProps<HTMLHeadingElement>;\n        h6: React.HTMLProps<HTMLHeadingElement>;\n        head: React.HTMLProps<HTMLHeadElement>;\n        header: React.HTMLProps<HTMLElement>;\n        hr: React.HTMLProps<HTMLHRElement>;\n        html: React.HTMLProps<HTMLHtmlElement>;\n        i: React.HTMLProps<HTMLElement>;\n        iframe: React.HTMLProps<HTMLIFrameElement>;\n        img: React.HTMLProps<HTMLImageElement>;\n        input: React.HTMLProps<HTMLInputElement>;\n        ins: React.HTMLProps<HTMLModElement>;\n        kbd: React.HTMLProps<HTMLElement>;\n        keygen: React.HTMLProps<HTMLElement>;\n        label: React.HTMLProps<HTMLLabelElement>;\n        legend: React.HTMLProps<HTMLLegendElement>;\n        li: React.HTMLProps<HTMLLIElement>;\n        link: React.HTMLProps<HTMLLinkElement>;\n        main: React.HTMLProps<HTMLElement>;\n        map: React.HTMLProps<HTMLMapElement>;\n        mark: React.HTMLProps<HTMLElement>;\n        menu: React.HTMLProps<HTMLElement>;\n        menuitem: React.HTMLProps<HTMLElement>;\n        meta: React.HTMLProps<HTMLMetaElement>;\n        meter: React.HTMLProps<HTMLElement>;\n        nav: React.HTMLProps<HTMLElement>;\n        noscript: React.HTMLProps<HTMLElement>;\n        object: React.HTMLProps<HTMLObjectElement>;\n        ol: React.HTMLProps<HTMLOListElement>;\n        optgroup: React.HTMLProps<HTMLOptGroupElement>;\n        option: React.HTMLProps<HTMLOptionElement>;\n        output: React.HTMLProps<HTMLElement>;\n        p: React.HTMLProps<HTMLParagraphElement>;\n        param: React.HTMLProps<HTMLParamElement>;\n        picture: React.HTMLProps<HTMLElement>;\n        pre: React.HTMLProps<HTMLPreElement>;\n        progress: React.HTMLProps<HTMLProgressElement>;\n        q: React.HTMLProps<HTMLQuoteElement>;\n        rp: React.HTMLProps<HTMLElement>;\n        rt: React.HTMLProps<HTMLElement>;\n        ruby: React.HTMLProps<HTMLElement>;\n        s: React.HTMLProps<HTMLElement>;\n        samp: React.HTMLProps<HTMLElement>;\n        script: React.HTMLProps<HTMLElement>;\n        section: React.HTMLProps<HTMLElement>;\n        select: React.HTMLProps<HTMLSelectElement>;\n        small: React.HTMLProps<HTMLElement>;\n        source: React.HTMLProps<HTMLSourceElement>;\n        span: React.HTMLProps<HTMLSpanElement>;\n        strong: React.HTMLProps<HTMLElement>;\n        style: React.HTMLProps<HTMLStyleElement>;\n        sub: React.HTMLProps<HTMLElement>;\n        summary: React.HTMLProps<HTMLElement>;\n        sup: React.HTMLProps<HTMLElement>;\n        table: React.HTMLProps<HTMLTableElement>;\n        tbody: React.HTMLProps<HTMLTableSectionElement>;\n        td: React.HTMLProps<HTMLTableDataCellElement>;\n        textarea: React.HTMLProps<HTMLTextAreaElement>;\n        tfoot: React.HTMLProps<HTMLTableSectionElement>;\n        th: React.HTMLProps<HTMLTableHeaderCellElement>;\n        thead: React.HTMLProps<HTMLTableSectionElement>;\n        time: React.HTMLProps<HTMLElement>;\n        title: React.HTMLProps<HTMLTitleElement>;\n        tr: React.HTMLProps<HTMLTableRowElement>;\n        track: React.HTMLProps<HTMLTrackElement>;\n        u: React.HTMLProps<HTMLElement>;\n        ul: React.HTMLProps<HTMLUListElement>;\n        \"var\": React.HTMLProps<HTMLElement>;\n        video: React.HTMLProps<HTMLVideoElement>;\n        wbr: React.HTMLProps<HTMLElement>;\n\n        // SVG\n        svg: React.SVGProps;\n\n        circle: React.SVGProps;\n        clipPath: React.SVGProps;\n        defs: React.SVGProps;\n        ellipse: React.SVGProps;\n        g: React.SVGProps;\n        image: React.SVGProps;\n        line: React.SVGProps;\n        linearGradient: React.SVGProps;\n        mask: React.SVGProps;\n        path: React.SVGProps;\n        pattern: React.SVGProps;\n        polygon: React.SVGProps;\n        polyline: React.SVGProps;\n        radialGradient: React.SVGProps;\n        rect: React.SVGProps;\n        stop: React.SVGProps;\n        text: React.SVGProps;\n        tspan: React.SVGProps;\n    }\n}\n"
  },
  {
    "path": ".vscode/typings/react-native/react-native.d.ts",
    "content": "// Type definitions for react-native 0.14\n// Project: https://github.com/facebook/react-native\n// Definitions by: Bruno Grieder <https://github.com/bgrieder>\n// Definitions: https://github.com/borisyankov/DefinitelyTyped\n\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n//\n// USING: these definitions are meant to be used with the TSC compiler target set to ES6\n//\n// USAGE EXAMPLES: check the RNTSExplorer project at https://github.com/bgrieder/RNTSExplorer\n//\n// CONTRIBUTING: please open pull requests and make sure that the changes do not break RNTSExplorer (they should not)\n// Do not hesitate to open a pull request against RNTSExplorer to provide an example for a case not covered by the current App\n//\n// CREDITS: This work is based on an original work made by Bernd Paradies: https://github.com/bparadie\n//\n///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////\n\n/// <reference path=\"../react/react.d.ts\" />\n\n//so we know what is \"original\" React\nimport React = __React;\n\n//react-native \"extends\" react\ndeclare namespace  __React {\n\n\n    /**\n     * Represents the completion of an asynchronous operation\n     * @see lib.es6.d.ts\n     */\n    export interface Promise<T> {\n        /**\n         * Attaches callbacks for the resolution and/or rejection of the Promise.\n         * @param onfulfilled The callback to execute when the Promise is resolved.\n         * @param onrejected The callback to execute when the Promise is rejected.\n         * @returns A Promise for the completion of which ever callback is executed.\n         */\n        then<TResult>( onfulfilled?: ( value: T ) => TResult | Promise<TResult>, onrejected?: ( reason: any ) => TResult | Promise<TResult> ): Promise<TResult>;\n\n        /**\n         * Attaches a callback for only the rejection of the Promise.\n         * @param onrejected The callback to execute when the Promise is rejected.\n         * @returns A Promise for the completion of the callback.\n         */\n        catch( onrejected?: ( reason: any ) => T | Promise<T> ): Promise<T>;\n\n\n        // not in lib.es6.d.ts but called by react-native\n        done( callback?: ( value: T ) => void ): void;\n    }\n\n    export interface PromiseConstructor {\n        /**\n         * A reference to the prototype.\n         */\n        prototype: Promise<any>;\n\n        /**\n         * Creates a new Promise.\n         * @param init A callback used to initialize the promise. This callback is passed two arguments:\n         * a resolve callback used resolve the promise with a value or the result of another promise,\n         * and a reject callback used to reject the promise with a provided reason or error.\n         */\n        new <T>( init: ( resolve: ( value?: T | Promise<T> ) => void, reject: ( reason?: any ) => void ) => void ): Promise<T>;\n\n        <T>( init: ( resolve: ( value?: T | Promise<T> ) => void, reject: ( reason?: any ) => void ) => void ): Promise<T>;\n\n        /**\n         * Creates a Promise that is resolved with an array of results when all of the provided Promises\n         * resolve, or rejected when any Promise is rejected.\n         * @param values An array of Promises.\n         * @returns A new Promise.\n         */\n        all<T>( values: (T | Promise<T>)[] ): Promise<T[]>;\n\n        /**\n         * Creates a Promise that is resolved with an array of results when all of the provided Promises\n         * resolve, or rejected when any Promise is rejected.\n         * @param values An array of values.\n         * @returns A new Promise.\n         */\n        all( values: Promise<void>[] ): Promise<void>;\n\n        /**\n         * Creates a Promise that is resolved or rejected when any of the provided Promises are resolved\n         * or rejected.\n         * @param values An array of Promises.\n         * @returns A new Promise.\n         */\n        race<T>( values: (T | Promise<T>)[] ): Promise<T>;\n\n        /**\n         * Creates a new rejected promise for the provided reason.\n         * @param reason The reason the promise was rejected.\n         * @returns A new rejected Promise.\n         */\n        reject( reason: any ): Promise<void>;\n\n        /**\n         * Creates a new rejected promise for the provided reason.\n         * @param reason The reason the promise was rejected.\n         * @returns A new rejected Promise.\n         */\n        reject<T>( reason: any ): Promise<T>;\n\n        /**\n         * Creates a new resolved promise for the provided value.\n         * @param value A promise.\n         * @returns A promise whose internal state matches the provided promise.\n         */\n        resolve<T>( value: T | Promise<T> ): Promise<T>;\n\n        /**\n         * Creates a new resolved promise .\n         * @returns A resolved promise.\n         */\n        resolve(): Promise<void>;\n    }\n\n    // @see lib.es6.d.ts\n    export var Promise: PromiseConstructor;\n\n    //TODO: BGR: Replace with ComponentClass ?\n    // node_modules/react-tools/src/classic/class/ReactClass.js\n    export interface ReactClass<D, P, S> {\n        // TODO:\n    }\n\n    // see react-jsx.d.ts\n    export function createElement<P>( type: React.ReactType,\n                                      props?: P,\n                                      ...children: React.ReactNode[] ): React.ReactElement<P>;\n\n\n    export type Runnable = ( appParameters: any ) => void;\n\n\n    // Similar to React.SyntheticEvent except for nativeEvent\n    interface NativeSyntheticEvent<T> {\n        bubbles: boolean\n        cancelable: boolean\n        currentTarget: EventTarget\n        defaultPrevented: boolean\n        eventPhase: number\n        isTrusted: boolean\n        nativeEvent: T\n        preventDefault(): void\n        stopPropagation(): void\n        target: EventTarget\n        timeStamp: Date\n        type: string\n    }\n\n    export interface NativeTouchEvent {\n        /**\n         * Array of all touch events that have changed since the last event\n         */\n        changedTouches: NativeTouchEvent[]\n\n        /**\n         * The ID of the touch\n         */\n        identifier: string\n\n        /**\n         * The X position of the touch, relative to the element\n         */\n        locationX: number\n\n        /**\n         * The Y position of the touch, relative to the element\n         */\n        locationY: number\n\n        /**\n         * The X position of the touch, relative to the screen\n         */\n        pageX: number\n\n        /**\n         * The Y position of the touch, relative to the screen\n         */\n        pageY: number\n\n        /**\n         * The node id of the element receiving the touch event\n         */\n        target: string\n\n        /**\n         * A time identifier for the touch, useful for velocity calculation\n         */\n        timestamp: number\n\n        /**\n         * Array of all current touches on the screen\n         */\n        touches : NativeTouchEvent[]\n    }\n\n    export interface GestureResponderEvent extends NativeSyntheticEvent<NativeTouchEvent> {\n    }\n\n\n    export interface  PointProperties {\n        x: number\n        y: number\n    }\n\n    export interface Insets {\n        top?: number\n        left?: number\n        bottom?: number\n        right?: number\n    }\n\n    /**\n     * //FIXME: need to find documentation on which compoenent is a native (i.e. non composite component)\n     */\n    export interface NativeComponent {\n        setNativeProps: ( props: Object ) => void\n    }\n\n    /**\n     * //FIXME: need to find documentation on which component is a TTouchable and can implement that interface\n     * @see React.DOMAtributes\n     */\n    export interface Touchable {\n        onTouchStart?: ( event: GestureResponderEvent ) => void\n        onTouchMove?: ( event: GestureResponderEvent ) => void\n        onTouchEnd?: ( event: GestureResponderEvent ) => void\n        onTouchCancel?: ( event: GestureResponderEvent ) => void\n        onTouchEndCapture?: ( event: GestureResponderEvent ) => void\n    }\n\n    export type AppConfig = {\n        appKey: string;\n        component: ReactClass<any, any, any>;\n        run?: Runnable;\n    }\n\n    // https://github.com/facebook/react-native/blob/master/Libraries/AppRegistry/AppRegistry.js\n    export class AppRegistry {\n        static registerConfig( config: AppConfig[] ): void;\n\n        static registerComponent( appKey: string, getComponentFunc: () => React.ComponentClass<any> ): string;\n\n        static registerRunnable( appKey: string, func: Runnable ): string;\n\n        static runApplication( appKey: string, appParameters: any ): void;\n    }\n\n    export interface LayoutAnimationTypes {\n        spring: string\n        linear: string\n        easeInEaseOut: string\n        easeIn: string\n        easeOut: string\n    }\n\n    export interface LayoutAnimationProperties {\n        opacity: string\n        scaleXY: string\n    }\n\n    export interface LayoutAnimationAnim {\n        duration?: number\n        delay?: number\n        springDamping?: number\n        initialVelocity?: number\n        type?: string //LayoutAnimationTypes\n        property?: string //LayoutAnimationProperties\n    }\n\n    export interface LayoutAnimationConfig {\n        duration: number\n        create?: LayoutAnimationAnim\n        update?: LayoutAnimationAnim\n        delete?: LayoutAnimationAnim\n    }\n\n    export interface LayoutAnimationStatic {\n\n        configureNext: ( config: LayoutAnimationConfig, onAnimationDidEnd?: () => void, onError?: ( error?: any ) => void ) => void\n        create: ( duration: number, type?: string, creationProp?: string ) => LayoutAnimationConfig\n        Types: LayoutAnimationTypes\n        Properties: LayoutAnimationProperties\n        configChecker: ( conf: {config: LayoutAnimationConfig}, name: string, next: string ) => void\n        Presets : {\n            easeInEaseOut: LayoutAnimationConfig\n            linear:LayoutAnimationConfig\n            spring: LayoutAnimationConfig\n        }\n    }\n\n\n    /**\n     * Flex Prop Types\n     * @see https://facebook.github.io/react-native/docs/flexbox.html#proptypes\n     * @see LayoutPropTypes.js\n     */\n    export interface FlexStyle {\n\n        alignItems?: string;  //enum('flex-start', 'flex-end', 'center', 'stretch')\n        alignSelf?: string// enum('auto', 'flex-start', 'flex-end', 'center', 'stretch')\n        borderBottomWidth?: number\n        borderLeftWidth?: number\n        borderRightWidth?: number\n        borderTopWidth?: number\n        borderWidth?: number\n        bottom?: number\n        flex?: number\n        flexDirection?: string // enum('row', 'column')\n        flexWrap?: string // enum('wrap', 'nowrap')\n        height?: number\n        justifyContent?: string // enum('flex-start', 'flex-end', 'center', 'space-between', 'space-around')\n        left?: number\n        margin?: number\n        marginBottom?: number\n        marginHorizontal?: number\n        marginLeft?: number\n        marginRight?: number\n        marginTop?: number\n        marginVertical?: number\n        padding?: number\n        paddingBottom?: number\n        paddingHorizontal?: number\n        paddingLeft?: number\n        paddingRight?: number\n        paddingTop?: number\n        paddingVertical?: number\n        position?: string // enum('absolute', 'relative')\n        right?: number\n        top?: number\n        width?: number\n    }\n\n\n    export interface TransformsStyle {\n\n        transform?: [{perspective: number}, {rotate: string}, {rotateX: string}, {rotateY: string}, {rotateZ: string}, {scale: number}, {scaleX: number}, {scaleY: number}, {translateX: number}, {translateY: number}, {skewX: string}, {skewY: string}]\n        transformMatrix?: Array<number>\n        rotation?: number\n        scaleX?: number\n        scaleY?: number\n        translateX?: number\n        translateY?: number\n    }\n\n\n    export interface StyleSheetProperties {\n        // TODO:\n    }\n\n    export interface LayoutRectangle {\n        x: number;\n        y: number;\n        width: number;\n        height: number;\n    }\n\n    // @see TextProperties.onLayout\n    export interface LayoutChangeEvent {\n        nativeEvent: {\n            layout: LayoutRectangle\n        }\n    }\n\n    // @see https://facebook.github.io/react-native/docs/text.html#style\n    export interface TextStyle extends ViewStyle {\n        color?: string\n        fontFamily?: string\n        fontSize?: number\n        fontStyle?: string // 'normal' | 'italic';\n        fontWeight?: string // enum(\"normal\", 'bold', '100', '200', '300', '400', '500', '600', '700', '800', '900')\n        letterSpacing?: number\n        lineHeight?: number\n        textAlign?: string // enum(\"auto\", 'left', 'right', 'center')\n        textDecorationLine?: string // enum(\"none\", 'underline', 'line-through', 'underline line-through')\n        textDecorationStyle?: string // enum(\"solid\", 'double', 'dotted', 'dashed')\n        textDecorationColor?: string\n        writingDirection?: string; //enum(\"auto\", 'ltr', 'rtl')\n        //containerBackgroundColor?: string\n    }\n\n    export interface TextPropertiesIOS {\n\n        /**\n         * When true, no visual change is made when text is pressed down.\n         * By default, a gray oval highlights the text on press down.\n         */\n        suppressHighlighting?: boolean\n    }\n\n    // https://facebook.github.io/react-native/docs/text.html#props\n    export interface TextProperties extends React.Props<TextProperties> {\n\n        /**\n         * Specifies should fonts scale to respect Text Size accessibility setting on iOS.\n         */\n        allowFontScaling?: boolean\n\n        /**\n         * Used to truncate the text with an elipsis after computing the text layout, including line wrapping, such that the total number of lines does not exceed this number.\n         */\n        numberOfLines?: number\n\n        /**\n         * Invoked on mount and layout changes with\n         *\n         * {nativeEvent: { layout: {x, y, width, height}}}.\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void\n\n        /**\n         * This function is called on press.\n         * Text intrinsically supports press handling with a default highlight state (which can be disabled with suppressHighlighting).\n         */\n        onPress?: () => void\n\n        /**\n         * @see https://facebook.github.io/react-native/docs/text.html#style\n         */\n        style?: TextStyle\n\n        /**\n         * Used to locate this view in end-to-end tests.\n         */\n        testID?: string\n    }\n\n    /**\n     * A React component for displaying text which supports nesting, styling, and touch handling.\n     */\n    export interface TextStatic extends React.ComponentClass<TextProperties> {\n\n    }\n\n\n    /**\n     * IOS Specific properties for TextInput\n     * @see https://facebook.github.io/react-native/docs/textinput.html#props\n     */\n    export interface TextInputIOSProperties {\n\n        /**\n         * If true, the text field will blur when submitted.\n         * The default value is true.\n         */\n        blurOnSubmit?: boolean\n\n        /**\n         * enum('never', 'while-editing', 'unless-editing', 'always')\n         * When the clear button should appear on the right side of the text view\n         */\n        clearButtonMode?: string\n\n        /**\n         * If true, clears the text field automatically when editing begins\n         */\n        clearTextOnFocus?: boolean\n\n        /**\n         * If true, the keyboard disables the return key when there is no text and automatically enables it when there is text.\n         * The default value is false.\n         */\n        enablesReturnKeyAutomatically?: boolean\n\n        /**\n         * Callback that is called when a key is pressed.\n         * Pressed key value is passed as an argument to the callback handler.\n         * Fires before onChange callbacks.\n         */\n        onKeyPress?: () => void\n\n        /**\n         * enum('default', 'go', 'google', 'join', 'next', 'route', 'search', 'send', 'yahoo', 'done', 'emergency-call')\n         * Determines how the return key should look.\n         */\n        returnKeyType?: string\n\n        /**\n         * If true, all text will automatically be selected on focus\n         */\n        selectTextOnFocus?: boolean\n\n        /**\n         * //FIXME: requires typing\n         * See DocumentSelectionState.js, some state that is responsible for maintaining selection information for a document\n         */\n        selectionState?: any\n\n\n    }\n\n    /**\n     * Android Specific properties for TextInput\n     * @see https://facebook.github.io/react-native/docs/textinput.html#props\n     */\n    export interface TextInputAndroidProperties {\n\n        /**\n         * Sets the number of lines for a TextInput.\n         * Use it with multiline set to true to be able to fill the lines.\n         */\n        numberOfLines?: number\n\n        /**\n         * enum('start', 'center', 'end')\n         * Set the position of the cursor from where editing will begin.\n         */\n        textAlign?: string\n\n        /**\n         * enum('top', 'center', 'bottom')\n         * Aligns text vertically within the TextInput.\n         */\n        textAlignVertical?: string\n\n        /**\n         * The color of the textInput underline.\n         */\n        underlineColorAndroid?: string\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/textinput.html#props\n     */\n    export interface TextInputProperties extends TextInputIOSProperties, TextInputAndroidProperties, React.Props<TextInputStatic> {\n\n        /**\n         * Can tell TextInput to automatically capitalize certain characters.\n         *      characters: all characters,\n         *      words: first letter of each word\n         *      sentences: first letter of each sentence (default)\n         *      none: don't auto capitalize anything\n         *\n         * https://facebook.github.io/react-native/docs/textinput.html#autocapitalize\n         */\n        autoCapitalize?: string\n\n        /**\n         * If false, disables auto-correct.\n         * The default value is true.\n         */\n        autoCorrect?: boolean\n\n        /**\n         * If true, focuses the input on componentDidMount.\n         * The default value is false.\n         */\n        autoFocus?: boolean\n\n        /**\n         * Provides an initial value that will change when the user starts typing.\n         * Useful for simple use-cases where you don't want to deal with listening to events\n         * and updating the value prop to keep the controlled state in sync.\n         */\n        defaultValue?: string\n\n        /**\n         * If false, text is not editable. The default value is true.\n         */\n        editable?: boolean\n\n        /**\n         * enum(\"default\", 'numeric', 'email-address', \"ascii-capable\", 'numbers-and-punctuation', 'url', 'number-pad', 'phone-pad', 'name-phone-pad', 'decimal-pad', 'twitter', 'web-search')\n         * Determines which keyboard to open, e.g.numeric.\n         * The following values work across platforms: - default - numeric - email-address\n         */\n        keyboardType?: string\n\n        /**\n         * Limits the maximum number of characters that can be entered.\n         * Use this instead of implementing the logic in JS to avoid flicker.\n         */\n        maxLength?: number\n\n        /**\n         * If true, the text input can be multiple lines. The default value is false.\n         */\n        multiline?: boolean\n\n        /**\n         * Callback that is called when the text input is blurred\n         */\n        onBlur?: () => void\n\n        /**\n         * Callback that is called when the text input's text changes.\n         */\n        onChange?: ( event: {nativeEvent: {text: string}} ) => void\n\n        /**\n         * Callback that is called when the text input's text changes.\n         * Changed text is passed as an argument to the callback handler.\n         */\n        onChangeText?: ( text: string ) => void\n\n        /**\n         * Callback that is called when text input ends.\n         */\n        onEndEditing?: ( event: {nativeEvent: {text: string}} ) => void\n\n        /**\n         * Callback that is called when the text input is focused\n         */\n        onFocus?: () => void\n\n        /**\n         * Invoked on mount and layout changes with {x, y, width, height}.\n         */\n        onLayout?: ( event: {nativeEvent: {x: number, y: number, width: number, height: number}} ) => void\n\n        /**\n         * Callback that is called when the text input's submit button is pressed.\n         */\n        onSubmitEditing?: ( event: {nativeEvent: {text: string}} ) => void\n\n        /**\n         * //FIXME: Not part of the doc but found in examples\n         */\n        password?: boolean\n\n        /**\n         * The string that will be rendered before text input has been entered\n         */\n        placeholder?: string\n\n        /**\n         * The text color of the placeholder string\n         */\n        placeholderTextColor?: string\n\n        /**\n         * If true, the text input obscures the text entered so that sensitive text like passwords stay secure.\n         * The default value is false.\n         */\n        secureTextEntry?: boolean\n\n        /**\n         * Styles\n         */\n        style?: TextStyle\n\n        /**\n         * Used to locate this view in end-to-end tests\n         */\n        testID?: string\n\n        /**\n         * The value to show for the text input. TextInput is a controlled component,\n         * which means the native value will be forced to match this value prop if provided.\n         * For most uses this works great, but in some cases this may cause flickering - one common cause is preventing edits by keeping value the same.\n         * In addition to simply setting the same value, either set editable={false},\n         * or set/update maxLength to prevent unwanted edits without flicker.\n         */\n        value?: string\n    }\n\n    export interface TextInputStatic extends NativeComponent, React.ComponentClass<TextInputProperties> {\n        blur: () => void\n        focus: () => void\n    }\n\n\n    /**\n     * Gesture recognition on mobile devices is much more complicated than web.\n     * A touch can go through several phases as the app determines what the user's intention is.\n     * For example, the app needs to determine if the touch is scrolling, sliding on a widget, or tapping.\n     * This can even change during the duration of a touch. There can also be multiple simultaneous touches.\n     *\n     * The touch responder system is needed to allow components to negotiate these touch interactions\n     * without any additional knowledge about their parent or child components.\n     * This system is implemented in ResponderEventPlugin.js, which contains further details and documentation.\n     *\n     * Best Practices\n     * Users can feel huge differences in the usability of web apps vs. native, and this is one of the big causes.\n     * Every action should have the following attributes:\n     *      Feedback/highlighting- show the user what is handling their touch, and what will happen when they release the gesture\n     *      Cancel-ability- when making an action, the user should be able to abort it mid-touch by dragging their finger away\n     *\n     * These features make users more comfortable while using an app,\n     * because it allows people to experiment and interact without fear of making mistakes.\n     *\n     * TouchableHighlight and Touchable*\n     * The responder system can be complicated to use.\n     * So we have provided an abstract Touchable implementation for things that should be \"tappable\".\n     * This uses the responder system and allows you to easily configure tap interactions declaratively.\n     * Use TouchableHighlight anywhere where you would use a button or link on web.\n     */\n    export interface GestureResponderHandlers {\n\n        /**\n         * A view can become the touch responder by implementing the correct negotiation methods.\n         * There are two methods to ask the view if it wants to become responder:\n         */\n\n        /**\n         * Does this view want to become responder on the start of a touch?\n         */\n        onStartShouldSetResponder?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * Called for every touch move on the View when it is not the responder: does this view want to \"claim\" touch responsiveness?\n         */\n        onMoveShouldSetResponder?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * If the View returns true and attempts to become the responder, one of the following will happen:\n         */\n\n        /**\n         * The View is now responding for touch events.\n         * This is the time to highlight and show the user what is happening\n         */\n        onResponderGrant?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * Something else is the responder right now and will not release it\n         */\n        onResponderReject?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * If the view is responding, the following handlers can be called:\n         */\n\n        /**\n         * The user is moving their finger\n         */\n        onResponderMove?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * Fired at the end of the touch, ie \"touchUp\"\n         */\n        onResponderRelease?: ( event: GestureResponderEvent ) => void\n\n        /**\n         *  Something else wants to become responder.\n         *  Should this view release the responder? Returning true allows release\n         */\n        onResponderTerminationRequest?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * The responder has been taken from the View.\n         * Might be taken by other views after a call to onResponderTerminationRequest,\n         * or might be taken by the OS without asking (happens with control center/ notification center on iOS)\n         */\n        onResponderTerminate?: ( event: GestureResponderEvent ) => void\n\n        /**\n         * onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern,\n         * where the deepest node is called first.\n         * That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers.\n         * This is desirable in most cases, because it makes sure all controls and buttons are usable.\n         *\n         * However, sometimes a parent will want to make sure that it becomes responder.\n         * This can be handled by using the capture phase.\n         * Before the responder system bubbles up from the deepest component,\n         * it will do a capture phase, firing on*ShouldSetResponderCapture.\n         * So if a parent View wants to prevent the child from becoming responder on a touch start,\n         * it should have a onStartShouldSetResponderCapture handler which returns true.\n         */\n        onStartShouldSetResponderCapture?: ( event: GestureResponderEvent ) => boolean\n\n        /**\n         * onStartShouldSetResponder and onMoveShouldSetResponder are called with a bubbling pattern,\n         * where the deepest node is called first.\n         * That means that the deepest component will become responder when multiple Views return true for *ShouldSetResponder handlers.\n         * This is desirable in most cases, because it makes sure all controls and buttons are usable.\n         *\n         * However, sometimes a parent will want to make sure that it becomes responder.\n         * This can be handled by using the capture phase.\n         * Before the responder system bubbles up from the deepest component,\n         * it will do a capture phase, firing on*ShouldSetResponderCapture.\n         * So if a parent View wants to prevent the child from becoming responder on a touch start,\n         * it should have a onStartShouldSetResponderCapture handler which returns true.\n         */\n        onMoveShouldSetResponderCapture?: () => void;\n\n    }\n\n    // @see https://facebook.github.io/react-native/docs/view.html#style\n    export interface ViewStyle extends FlexStyle, TransformsStyle {\n        backgroundColor?: string;\n        borderBottomColor?: string;\n        borderBottomLeftRadius?: number;\n        borderBottomRightRadius?: number;\n        borderColor?: string;\n        borderLeftColor?: string;\n        borderRadius?: number;\n        borderRightColor?: string;\n        borderTopColor?: string;\n        borderTopLeftRadius?: number;\n        borderTopRightRadius?: number;\n        opacity?: number;\n        overflow?: string; // enum('visible', 'hidden')\n        shadowColor?: string;\n        shadowOffset?: {width: number, height: number};\n        shadowOpacity?: number;\n        shadowRadius?: number;\n    }\n\n\n    export interface ViewPropertiesIOS {\n\n        /**\n         * Provides additional traits to screen reader.\n         * By default no traits are provided unless specified otherwise in element\n         *\n         * @enum('none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text','summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn')\n         */\n        accessibilityTraits?: string | string[];\n\n        /**\n         * Whether this view should be rendered as a bitmap before compositing.\n         *\n         * On iOS, this is useful for animations and interactions that do not modify this component's dimensions nor its children;\n         * for example, when translating the position of a static view, rasterization allows the renderer to reuse a cached bitmap of a static view\n         * and quickly composite it during each frame.\n         *\n         * Rasterization incurs an off-screen drawing pass and the bitmap consumes memory.\n         * Test and measure when using this property.\n         */\n        shouldRasterizeIOS?: boolean\n    }\n\n    export interface ViewPropertiesAndroid {\n\n        /**\n         * Indicates to accessibility services to treat UI component like a native one.\n         * Works for Android only.\n         *\n         * @enum('none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' )\n         */\n        accessibilityComponentType?: string\n\n\n        /**\n         * Indicates to accessibility services whether the user should be notified when this view changes.\n         * Works for Android API >= 19 only.\n         * See http://developer.android.com/reference/android/view/View.html#attr_android:accessibilityLiveRegion for references.\n         */\n        accessibilityLiveRegion?: string\n\n        /**\n         * Views that are only used to layout their children or otherwise don't draw anything\n         * may be automatically removed from the native hierarchy as an optimization.\n         * Set this property to false to disable this optimization and ensure that this View exists in the native view hierarchy.\n         */\n        collapsable?: boolean\n\n\n        /**\n         * Controls how view is important for accessibility which is if it fires accessibility events\n         * and if it is reported to accessibility services that query the screen.\n         * Works for Android only. See http://developer.android.com/reference/android/R.attr.html#importantForAccessibility for references.\n         *\n         * Possible values:\n         *      'auto' - The system determines whether the view is important for accessibility - default (recommended).\n         *      'yes' - The view is important for accessibility.\n         *      'no' - The view is not important for accessibility.\n         *      'no-hide-descendants' - The view is not important for accessibility, nor are any of its descendant views.\n         */\n        importantForAccessibility?: string\n\n\n        /**\n         * Whether this view needs to rendered offscreen and composited with an alpha in order to preserve 100% correct colors and blending behavior.\n         * The default (false) falls back to drawing the component and its children\n         * with an alpha applied to the paint used to draw each element instead of rendering the full component offscreen and compositing it back with an alpha value.\n         * This default may be noticeable and undesired in the case where the View you are setting an opacity on\n         * has multiple overlapping elements (e.g. multiple overlapping Views, or text and a background).\n         *\n         * Rendering offscreen to preserve correct alpha behavior is extremely expensive\n         * and hard to debug for non-native developers, which is why it is not turned on by default.\n         * If you do need to enable this property for an animation,\n         * consider combining it with renderToHardwareTextureAndroid if the view contents are static (i.e. it doesn't need to be redrawn each frame).\n         * If that property is enabled, this View will be rendered off-screen once,\n         * saved in a hardware texture, and then composited onto the screen with an alpha each frame without having to switch rendering targets on the GPU.\n         */\n        needsOffscreenAlphaCompositing?: boolean\n\n\n        /**\n         * Whether this view should render itself (and all of its children) into a single hardware texture on the GPU.\n         *\n         * On Android, this is useful for animations and interactions that only modify opacity, rotation, translation, and/or scale:\n         * in those cases, the view doesn't have to be redrawn and display lists don't need to be re-executed. The texture can just be\n         * re-used and re-composited with different parameters. The downside is that this can use up limited video memory, so this prop should be set back to false at the end of the interaction/animation.\n         */\n        renderToHardwareTextureAndroid?: boolean;\n\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/view.html#props\n     */\n    export interface ViewProperties extends ViewPropertiesAndroid, ViewPropertiesIOS, GestureResponderHandlers, Touchable, React.Props<ViewStatic> {\n\n        /**\n         * Overrides the text that's read by the screen reader when the user interacts with the element. By default, the label is constructed by traversing all the children and accumulating all the Text nodes separated by space.\n         */\n        accessibilityLabel?: string;\n\n        /**\n         * When true, indicates that the view is an accessibility element.\n         * By default, all the touchable elements are accessible.\n         */\n        accessible?: boolean;\n\n        /**\n         * When `accessible` is true, the system will try to invoke this function when the user performs accessibility tap gesture.\n         */\n        onAcccessibilityTap?: () => void;\n\n        /**\n         * Invoked on mount and layout changes with\n         *\n         * {nativeEvent: { layout: {x, y, width, height}}}.\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void;\n\n        /**\n         * When accessible is true, the system will invoke this function when the user performs the magic tap gesture.\n         */\n        onMagicTap?: () => void;\n\n        /**\n         *\n         * In the absence of auto property, none is much like CSS's none value. box-none is as if you had applied the CSS class:\n         *\n         * .box-none {\n         *   pointer-events: none;\n         * }\n         * .box-none * {\n         *   pointer-events: all;\n         * }\n         *\n         * box-only is the equivalent of\n         *\n         * .box-only {\n         *   pointer-events: all;\n         * }\n         * .box-only * {\n         *   pointer-events: none;\n         * }\n         *\n         * But since pointerEvents does not affect layout/appearance, and we are already deviating from the spec by adding additional modes,\n         * we opt to not include pointerEvents on style. On some platforms, we would need to implement it as a className anyways. Using style or not is an implementation detail of the platform.\n         */\n        pointerEvents?: string;\n\n        /**\n         *\n         * This is a special performance property exposed by RCTView and is useful for scrolling content when there are many subviews,\n         * most of which are offscreen. For this property to be effective, it must be applied to a view that contains many subviews that extend outside its bound.\n         * The subviews must also have overflow: hidden, as should the containing view (or one of its superviews).\n         */\n        removeClippedSubviews?: boolean\n\n        style?: ViewStyle;\n\n        /**\n         * Used to locate this view in end-to-end tests.\n         */\n        testID?: string;\n    }\n\n    /**\n     * The most fundamental component for building UI, View is a container that supports layout with flexbox, style, some touch handling,\n     * and accessibility controls, and is designed to be nested inside other views and to have 0 to many children of any type.\n     * View maps directly to the native view equivalent on whatever platform React is running on,\n     * whether that is a UIView, <div>, android.view, etc.\n     */\n    export interface ViewStatic extends NativeComponent, React.ComponentClass<ViewProperties> {\n\n    }\n\n    /**\n     * //FIXME: No documentation extracted from showapi_res_code comment on WebView.ios.js\n     */\n    export interface NavState {\n\n        url?: string\n        title?: string\n        loading?: boolean\n        canGoBack?: boolean\n        canGoForward?: boolean;\n\n        [key: string]: any\n    }\n\n    export interface WebViewPropertiesAndroid {\n\n        /**\n         * Used for android only, JS is enabled by default for WebView on iOS\n         */\n        javaScriptEnabledAndroid?: boolean\n    }\n\n    export interface WebViewPropertiesIOS {\n\n        /**\n         * Used for iOS only, sets whether the webpage scales to fit the view and the user can change the scale\n         */\n        scalesPageToFit?: boolean\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/webview.html#props\n     */\n    export interface WebViewProperties extends WebViewPropertiesAndroid, WebViewPropertiesIOS, React.Props<WebViewStatic> {\n\n        automaticallyAdjustContentInsets?: boolean\n\n        bounces?: boolean\n\n        contentInset?: Insets\n\n        html?: string\n\n        /**\n         * Sets the JS to be injected when the webpage loads.\n         */\n        injectedJavaScript?: string\n\n        onNavigationStateChange?: ( event: NavState ) => void\n\n        /**\n         * Allows custom handling of any webview requests by a JS handler.\n         * Return true or false from this method to continue loading the request.\n         */\n        onShouldStartLoadWithRequest?: () => boolean\n\n        /**\n         * view to show if there's an error\n         */\n        renderError?: () => ViewStatic\n\n        /**\n         * loading indicator to show\n         */\n        renderLoading?: () => ViewStatic\n\n        scrollEnabled?: boolean\n\n        startInLoadingState?: boolean\n\n        style?: ViewStyle\n\n        url: string\n    }\n\n\n    export interface WebViewStatic extends React.ComponentClass<WebViewProperties> {\n\n        goBack: () => void\n        goForward: () => void\n        reload: () => void\n    }\n\n\n    /**\n     * @see\n     */\n    export interface SegmentedControlIOSProperties {\n        /// TODO\n    }\n\n\n    export interface NavigatorIOSProperties extends React.Props<NavigatorIOSStatic> {\n\n        /**\n         * NavigatorIOS uses \"route\" objects to identify child views, their props, and navigation bar configuration.\n         * \"push\" and all the other navigation operations expect routes to be like this\n         */\n        initialRoute?: Route\n\n        /**\n         * The default wrapper style for components in the navigator.\n         * A common use case is to set the backgroundColor for every page\n         */\n        itemWrapperStyle?: ViewStyle\n\n        /**\n         * A Boolean value that indicates whether the navigation bar is hidden\n         */\n        navigationBarHidden?: boolean\n\n        /**\n         * A Boolean value that indicates whether to hide the 1px hairline shadow\n         */\n        shadowHidden?: boolean\n\n        /**\n         * The color used for buttons in the navigation bar\n         */\n        tintColor?: string\n\n        /**\n         * The text color of the navigation bar title\n         */\n        titleTextColor?: string\n\n        /**\n         * A Boolean value that indicates whether the navigation bar is translucent\n         */\n        translucent?: boolean\n\n        /**\n         * NOT IN THE DOC BUT IN THE EXAMPLES\n         */\n        style?: ViewStyle\n    }\n\n    /**\n     * A navigator is an object of navigation functions that a view can call.\n     * It is passed as a prop to any component rendered by NavigatorIOS.\n     *\n     * Navigator functions are also available on the NavigatorIOS component:\n     *\n     * @see https://facebook.github.io/react-native/docs/navigatorios.html#navigator\n     */\n    export interface NavigationIOS {\n        /**\n         * Navigate forward to a new route\n         */\n        push: ( route: Route ) => void\n\n        /**\n         * Go back one page\n         */\n        pop: () => void\n\n        /**\n         * Go back N pages at once. When N=1, behavior matches pop()\n         */\n        popN: ( n: number ) => void\n\n        /**\n         * Replace the route for the current page and immediately load the view for the new route\n         */\n        replace: ( route: Route ) => void\n\n        /**\n         * Replace the route/view for the previous page\n         */\n        replacePrevious: ( route: Route ) => void\n\n        /**\n         * Replaces the previous route/view and transitions back to it\n         */\n        replacePreviousAndPop: ( route: Route ) => void\n\n        /**\n         * Replaces the top item and popToTop\n         */\n        resetTo: ( route: Route ) => void\n\n        /**\n         * Go back to the item for a particular route object\n         */\n        popToRoute( route: Route ): void\n\n        /**\n         * Go back to the top item\n         */\n        popToTop(): void\n    }\n\n    export interface NavigatorIOSStatic extends NavigationIOS, React.ComponentClass<NavigatorIOSProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/activityindicatorios.html#props\n     */\n    export interface ActivityIndicatorIOSProperties extends React.Props<ActivityIndicatorIOSStatic> {\n\n        /**\n         * Whether to show the indicator (true, the default) or hide it (false).\n         */\n        animating?: boolean\n\n        /**\n         * The foreground color of the spinner (default is gray).\n         */\n        color?: string\n\n        /**\n         * Whether the indicator should hide when not animating (true by default).\n         */\n        hidesWhenStopped?: boolean\n\n        /**\n         * Invoked on mount and layout changes with\n         */\n        onLayout?: ( event: {nativeEvent: { layout: {x: number, y: number , width: number, height: number}}} ) => void\n\n        /**\n         * Size of the indicator.\n         * Small has a height of 20, large has a height of 36.\n         *\n         * enum('small', 'large')\n         */\n        size?: string\n\n        style?: ViewStyle\n    }\n\n    export interface ActivityIndicatorIOSStatic extends React.ComponentClass<ActivityIndicatorIOSProperties> {\n    }\n\n\n    export interface DatePickerIOSProperties extends React.Props<DatePickerIOSStatic> {\n\n        /**\n         * The currently selected date.\n         */\n        date?: Date\n\n\n        /**\n         * Maximum date.\n         * Restricts the range of possible date/time values.\n         */\n        maximumDate?: Date\n\n        /**\n         * Maximum date.\n         * Restricts the range of possible date/time values.\n         */\n        minimumDate?: Date\n\n        /**\n         *  enum(1, 2, 3, 4, 5, 6, 10, 12, 15, 20, 30)\n         *  The interval at which minutes can be selected.\n         */\n        minuteInterval?: number\n\n        /**\n         *  enum('date', 'time', 'datetime')\n         *  The date picker mode.\n         */\n        mode?: string\n\n        /**\n         * Date change handler.\n         * This is called when the user changes the date or time in the UI.\n         * The first and only argument is a Date object representing the new date and time.\n         */\n        onDateChange?: ( newDate: Date ) => void\n\n        /**\n         * Timezone offset in minutes.\n         * By default, the date picker will use the device's timezone. With this parameter, it is possible to force a certain timezone offset.\n         * For instance, to show times in Pacific Standard Time, pass -7 * 60.\n         */\n        timeZoneOffsetInMinutes?: number\n\n    }\n\n    export interface DatePickerIOSStatic extends React.ComponentClass<DatePickerIOSProperties> {\n    }\n\n\n    /**\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSItemProperties extends React.Props<PickerIOSItemStatic> {\n        value?: string | number\n        label?: string\n    }\n\n    /**\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSItemStatic extends React.ComponentClass<PickerIOSItemProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/pickerios.html\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSProperties extends React.Props<PickerIOSStatic> {\n\n        onValueChange?: ( value: string | number ) => void\n\n        selectedValue?: string | number\n\n        style?: ViewStyle\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/pickerios.html\n     * @see PickerIOS.ios.js\n     */\n    export interface PickerIOSStatic extends React.ComponentClass<PickerIOSProperties> {\n\n        Item: PickerIOSItemStatic\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/sliderios.html\n     */\n    export interface SliderIOSProperties extends React.Props<SliderIOSStatic> {\n\n        /**\n         * If true the user won't be able to move the slider. Default value is false.\n         */\n        disabled?: boolean\n\n        /**\n         * Initial maximum value of the slider. Default value is 1.\n         */\n        maximumValue?: number\n\n        /**\n         * The color used for the track to the right of the button. Overrides the default blue gradient image.\n         */\n        maximumTrackTintColor?: string\n\n        /**\n         * Initial minimum value of the slider. Default value is 0.\n         */\n        minimumValue?: number\n\n        /**\n         * The color used for the track to the left of the button. Overrides the default blue gradient image.\n         */\n        minimumTrackTintColor?: string\n\n        /**\n         * Callback called when the user finishes changing the value (e.g. when the slider is released).\n         */\n        onSlidingComplete?: () => void\n\n        /**\n         * Callback continuously called while the user is dragging the slider.\n         */\n        onValueChange?: ( value: number ) => void\n\n        /**\n         * Step value of the slider.\n         * The value should be between 0 and (maximumValue - minimumValue).\n         * Default value is 0.\n         */\n        step?: number\n\n        /**\n         * Used to style and layout the Slider.\n         * @see StyleSheet.js and ViewStylePropTypes.js for more info.\n         */\n        style?: ViewStyle\n\n        /**\n         * Initial value of the slider.\n         * The value should be between minimumValue and maximumValue, which default to 0 and 1 respectively.\n         * Default value is 0.\n         *\n         * This is not a controlled component, e.g. if you don't update the value, the component won't be reset to its inital value.\n         */\n        value?: number\n    }\n\n    export interface SliderIOSStatic extends React.ComponentClass<SliderIOSProperties> {\n\n    }\n\n    /**\n     * //FIXME: no dcumentation, inferred\n     * @see SwitchIOS.ios.js\n     */\n    export interface SwitchIOSStyle extends ViewStyle {\n        height?: number\n        width?: number\n    }\n\n\n    /**\n     * https://facebook.github.io/react-native/docs/switchios.html#props\n     */\n    export interface SwitchIOSProperties extends React.Props<SwitchIOSStatic> {\n\n        /**\n         * If true the user won't be able to toggle the switch. Default value is false.\n         */\n        disabled?: boolean\n\n        /**\n         * Background color when the switch is turned on.\n         */\n        onTintColor?: string\n\n        /**\n         * Callback that is called when the user toggles the switch.\n         */\n        onValueChange?: ( value: boolean ) => void\n\n        /**\n         * Background color for the switch round button.\n         */\n        thumbTintColor?: string\n\n        /**\n         * Background color when the switch is turned off.\n         */\n        tintColor?: string\n\n        /**\n         * The value of the switch, if true the switch will be turned on. Default value is false.\n         */\n        value?: boolean\n\n        style?: SwitchIOSStyle\n    }\n\n    /**\n     *\n     * Use SwitchIOS to render a boolean input on iOS.\n     *\n     * This is a controlled component, so you must hook in to the onValueChange callback and update the value prop in order for the component to update,\n     * otherwise the user's change will be reverted immediately to reflect props.value as the source of truth.\n     *\n     * @see https://facebook.github.io/react-native/docs/switchios.html\n     */\n    export interface SwitchIOSStatic extends React.ComponentClass<SwitchIOSProperties> {\n\n    }\n\n\n    /**\n     * @see ImageResizeMode.js\n     */\n    export interface ImageResizeModeStatic {\n        /**\n         * contain - The image will be resized such that it will be completely\n         * visible, contained within the frame of the View.\n         */\n        contain: string\n        /**\n         * cover - The image will be resized such that the entire area of the view\n         * is covered by the image, potentially clipping parts of the image.\n         */\n        cover: string\n        /**\n         * stretch - The image will be stretched to fill the entire frame of the\n         * view without clipping.  This may change the aspect ratio of the image,\n         * distoring it.  Only supported on iOS.\n         */\n        stretch: string\n    }\n\n    /**\n     * Image style\n     * @see https://facebook.github.io/react-native/docs/image.html#style\n     */\n    export interface ImageStyle extends FlexStyle, TransformsStyle {\n        resizeMode?: string //Object.keys(ImageResizeMode)\n        backgroundColor?: string\n        borderColor?: string\n        borderWidth?: number\n        borderRadius?: number\n        overflow?: string // enum('visible', 'hidden')\n        tintColor?: string\n        opacity?: number\n    }\n\n    export interface ImagePropertiesIOS {\n        /**\n         * The text that's read by the screen reader when the user interacts with the image.\n         */\n        accessibilityLabel?: string;\n\n        /**\n         * When true, indicates the image is an accessibility element.\n         */\n        accessible?: boolean;\n\n        /**\n         * When the image is resized, the corners of the size specified by capInsets will stay a fixed size,\n         * but the center content and borders of the image will be stretched.\n         * This is useful for creating resizable rounded buttons, shadows, and other resizable assets.\n         * More info on Apple documentation\n         */\n        capInsets?: Insets\n\n        /**\n         * A static image to display while downloading the final image off the network.\n         */\n        defaultSource?: {uri: string}\n\n        /**\n         * Invoked on load error with {nativeEvent: {error}}\n         */\n        onError?: ( error: {nativeEvent: any} ) => void\n\n        /**\n         * Invoked when load completes successfully\n         */\n        onLoad?: () => void\n\n        /**\n         * Invoked when load either succeeds or fails\n         */\n        onLoadEnd?: () => void\n\n        /**\n         * Invoked on load start\n         */\n        onLoadStart?: () => void\n\n        /**\n         * Invoked on download progress with {nativeEvent: {loaded, total}}\n         */\n        onProgress?: ()=> void\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/image.html\n     */\n    export interface ImageProperties extends ImagePropertiesIOS, React.Props<Image> {\n        /**\n         * onLayout function\n         *\n         * Invoked on mount and layout changes with\n         *\n         * {nativeEvent: { layout: {x, y, width, height}}}.\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void;\n\n\n        /**\n         * Determines how to resize the image when the frame doesn't match the raw image dimensions.\n         *\n         * enum('cover', 'contain', 'stretch')\n         */\n        resizeMode?: string;\n\n        /**\n         * uri is a string representing the resource identifier for the image,\n         * which could be an http address, a local file path,\n         * or the name of a static image resource (which should be wrapped in the require('image!name') function).\n         */\n        source: {uri: string} | string;\n\n        /**\n         *\n         * Style\n         */\n        style?:  ImageStyle;\n\n        /**\n         * A unique identifier for this element to be used in UI Automation testing scripts.\n         */\n        testID?: string;\n\n    }\n\n    export interface ImageStatic extends React.ComponentClass<ImageProperties> {\n        uri: string;\n        resizeMode: ImageResizeModeStatic\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/listview.html#props\n     */\n    export interface ListViewProperties extends ScrollViewProperties, React.Props<ListViewStatic> {\n\n        dataSource?: ListViewDataSource\n\n        /**\n         * How many rows to render on initial component mount.  Use this to make\n         * it so that the first screen worth of data apears at one time instead of\n         * over the course of multiple frames.\n         */\n        initialListSize?: number\n\n        /**\n         * (visibleRows, changedRows) => void\n         *\n         * Called when the set of visible rows changes.  `visibleRows` maps\n         * { sectionID: { rowID: true }} for all the visible rows, and\n         * `changedRows` maps { sectionID: { rowID: true | false }} for the rows\n         * that have changed their visibility, with true indicating visible, and\n         * false indicating the view has moved out of view.\n         */\n        onChangeVisibleRows?: ( visibleRows: Array<{[sectionId: string]: {[rowID: string]: boolean}}>, changedRows: Array<{[sectionId: string]: {[rowID: string]: boolean}}> ) => void\n\n        /**\n         * Called when all rows have been rendered and the list has been scrolled\n         * to within onEndReachedThreshold of the bottom.  The native scroll\n         * event is provided.\n         */\n        onEndReached?: () => void\n\n        /**\n         * Threshold in pixels for onEndReached.\n         */\n        onEndReachedThreshold?: number\n\n        /**\n         * Number of rows to render per event loop.\n         */\n        pageSize?: number\n\n        /**\n         * An experimental performance optimization for improving scroll perf of\n         * large lists, used in conjunction with overflow: 'hidden' on the row\n         * containers.  Use at your own risk.\n         */\n        removeClippedSubviews?: boolean\n\n        /**\n         * () => renderable\n         *\n         * The header and footer are always rendered (if these props are provided)\n         * on every render pass.  If they are expensive to re-render, wrap them\n         * in StaticContainer or other mechanism as appropriate.  Footer is always\n         * at the bottom of the list, and header at the top, on every render pass.\n         */\n        renderFooter?: () => React.ReactElement<any>\n\n        /**\n         * () => renderable\n         *\n         * The header and footer are always rendered (if these props are provided)\n         * on every render pass.  If they are expensive to re-render, wrap them\n         * in StaticContainer or other mechanism as appropriate.  Footer is always\n         * at the bottom of the list, and header at the top, on every render pass.\n         */\n        renderHeader?: () => React.ReactElement<any>\n\n        /**\n         * (rowData, sectionID, rowID) => renderable\n         * Takes a data entry from the data source and its ids and should return\n         * a renderable component to be rendered as the row.  By default the data\n         * is exactly what was put into the data source, but it's also possible to\n         * provide custom extractors.\n         */\n        renderRow?: ( rowData: any, sectionID: string | number, rowID: string | number, highlightRow?: boolean ) => React.ReactElement<any>\n\n\n        /**\n         * A function that returns the scrollable component in which the list rows are rendered.\n         * Defaults to returning a ScrollView with the given props.\n         */\n        renderScrollComponent?: ( props: ScrollViewProperties ) => React.ReactElement<ScrollViewProperties>\n\n        /**\n         * (sectionData, sectionID) => renderable\n         *\n         * If provided, a sticky header is rendered for this section.  The sticky\n         * behavior means that it will scroll with the content at the top of the\n         * section until it reaches the top of the screen, at which point it will\n         * stick to the top until it is pushed off the screen by the next section\n         * header.\n         */\n        renderSectionHeader?: ( sectionData: any, sectionId: string | number ) => React.ReactElement<any>\n\n\n        /**\n         * (sectionID, rowID, adjacentRowHighlighted) => renderable\n         * If provided, a renderable component to be rendered as the separator below each row\n         * but not the last row if there is a section header below.\n         * Take a sectionID and rowID of the row above and whether its adjacent row is highlighted.\n         */\n        renderSeparator?: ( sectionID: string | number, rowID: string | number, adjacentRowHighlighted?: boolean ) => React.ReactElement<any>\n\n        /**\n         * How early to start rendering rows before they come on screen, in\n         * pixels.\n         */\n        scrollRenderAheadDistance?: number\n    }\n\n    export interface ListViewStatic extends React.ComponentClass<ListViewProperties> {\n        DataSource: ListViewDataSource;\n    }\n\n\n    export interface MapViewAnnotation {\n        latitude?: number\n        longitude?: number\n        animateDrop?: boolean\n        title?: string\n        subtitle?: string\n        hasLeftCallout?: boolean\n        hasRightCallout?: boolean\n        onLeftCalloutPress?: () => void\n        onRightCalloutPress?: () => void\n        id?: string\n    }\n\n    export interface MapViewRegion {\n        latitude: number\n        longitude: number\n        latitudeDelta: number\n        longitudeDelta: number\n    }\n\n    export interface MapViewPropertiesIOS {\n\n        /**\n         * If false points of interest won't be displayed on the map.\n         * Default value is true.\n         */\n        showsPointsOfInterest?: boolean\n    }\n\n    export interface MapViewProperties extends MapViewPropertiesIOS, Touchable, React.Props<MapViewStatic> {\n\n        /**\n         * Map annotations with title/subtitle.\n         */\n        annotations?: MapViewAnnotation[]\n\n        /**\n         * Insets for the map's legal label, originally at bottom left of the map. See EdgeInsetsPropType.js for more information.\n         */\n        legalLabelInsets?: Insets\n\n        /**\n         * The map type to be displayed.\n         *     standard: standard road map (default)\n         *     satellite: satellite view\n         *     hybrid: satellite view with roads and points of interest overlayed\n         *\n         * enum('standard', 'satellite', 'hybrid')\n         */\n        mapType?: string\n\n        /**\n         * Maximum size of area that can be displayed.\n         */\n        maxDelta?: number\n\n        /**\n         * Minimum size of area that can be displayed.\n         */\n        minDelta?: number\n\n        /**\n         * Callback that is called once, when the user taps an annotation.\n         */\n        onAnnotationPress?: () => void\n\n        /**\n         * Callback that is called continuously when the user is dragging the map.\n         */\n        onRegionChange?: ( region: MapViewRegion ) => void\n\n        /**\n         * Callback that is called once, when the user is done moving the map.\n         */\n        onRegionChangeComplete?: ( region: MapViewRegion ) => void\n\n        /**\n         * When this property is set to true and a valid camera is associated with the map,\n         * the camera’s pitch angle is used to tilt the plane of the map.\n         *\n         * When this property is set to false, the camera’s pitch angle is ignored and\n         * the map is always displayed as if the user is looking straight down onto it.\n         */\n        pitchEnabled?: boolean\n\n        /**\n         * The region to be displayed by the map.\n         * The region is defined by the center coordinates and the span of coordinates to display.\n         */\n        region?: MapViewRegion\n\n        /**\n         * When this property is set to true and a valid camera is associated with the map,\n         * the camera’s heading angle is used to rotate the plane of the map around its center point.\n         *\n         * When this property is set to false, the camera’s heading angle is ignored and the map is always oriented\n         * so that true north is situated at the top of the map view\n         */\n        rotateEnabled?: boolean\n\n        /**\n         * If false the user won't be able to change the map region being displayed.\n         * Default value is true.\n         */\n        scrollEnabled?: boolean\n\n        /**\n         * If true the app will ask for the user's location and focus on it.\n         * Default value is false.\n         *\n         * NOTE: You need to add NSLocationWhenInUseUsageDescription key in Info.plist to enable geolocation,\n         * otherwise it is going to fail silently!\n         */\n        showsUserLocation?: boolean\n\n        /**\n         * Used to style and layout the MapView.\n         * See StyleSheet.js and ViewStylePropTypes.js for more info.\n         */\n        style?: ViewStyle\n\n        /**\n         * If false the user won't be able to pinch/zoom the map.\n         * Default value is true.\n         */\n        zoomEnabled?: boolean\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/mapview.html#content\n     */\n    export interface MapViewStatic extends React.ComponentClass<MapViewProperties> {\n    }\n\n\n    export interface TouchableWithoutFeedbackAndroidProperties {\n\n        /**\n         * Indicates to accessibility services to treat UI component like a native one.\n         * Works for Android only.\n         *\n         * @enum('none', 'button', 'radiobutton_checked', 'radiobutton_unchecked' )\n         */\n        accessibilityComponentType?: string\n    }\n\n    export interface TouchableWithoutFeedbackIOSProperties {\n\n        /**\n         * Provides additional traits to screen reader.\n         * By default no traits are provided unless specified otherwise in element\n         *\n         * @enum('none', 'button', 'link', 'header', 'search', 'image', 'selected', 'plays', 'key', 'text','summary', 'disabled', 'frequentUpdates', 'startsMedia', 'adjustable', 'allowsDirectInteraction', 'pageTurn')\n         */\n        accessibilityTraits?: string | string[];\n\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html#props\n     */\n    export interface TouchableWithoutFeedbackProperties extends TouchableWithoutFeedbackAndroidProperties, TouchableWithoutFeedbackIOSProperties {\n\n\n        /**\n         * Called when the touch is released, but not if cancelled (e.g. by a scroll that steals the responder lock).\n         */\n        accessible?: boolean\n\n        /**\n         * Delay in ms, from onPressIn, before onLongPress is called.\n         */\n        delayLongPress?: number;\n\n        /**\n         * Delay in ms, from the start of the touch, before onPressIn is called.\n         */\n        delayPressIn?: number;\n\n        /**\n         * Delay in ms, from the release of the touch, before onPressOut is called.\n         */\n        delayPressOut?: number;\n\n        /**\n         * Invoked on mount and layout changes with\n         * {nativeEvent: {layout: {x, y, width, height}}}\n         */\n        onLayout?: ( event: LayoutChangeEvent ) => void\n\n        onLongPress?: () => void;\n\n        /**\n         * Called when the touch is released,\n         * but not if cancelled (e.g. by a scroll that steals the responder lock).\n         */\n        onPress?: () => void;\n\n        onPressIn?: () => void;\n\n        onPressOut?: () => void;\n\n        /**\n         * //FIXME: not in doc but available in exmaples\n         */\n        style?: ViewStyle\n    }\n\n\n    export interface TouchableWithoutFeedbackProps extends TouchableWithoutFeedbackProperties, React.Props<TouchableWithoutFeedbackStatic> {\n\n    }\n\n    /**\n     * Do not use unless you have a very good reason.\n     * All the elements that respond to press should have a visual feedback when touched.\n     * This is one of the primary reason a \"web\" app doesn't feel \"native\".\n     *\n     * @see https://facebook.github.io/react-native/docs/touchablewithoutfeedback.html\n     */\n    export interface TouchableWithoutFeedbackStatic extends React.ComponentClass<TouchableWithoutFeedbackProps> {\n\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchablehighlight.html#props\n     */\n    export interface TouchableHighlightProperties extends TouchableWithoutFeedbackProperties, React.Props<TouchableHighlightStatic> {\n\n        /**\n         * Determines what the opacity of the wrapped view should be when touch is active.\n         */\n        activeOpacity?: number\n\n        /**\n         *\n         * Called immediately after the underlay is hidden\n         */\n        onHideUnderlay?: () => void\n\n        /**\n         * Called immediately after the underlay is shown\n         */\n        onShowUnderlay?: () => void\n\n        /**\n         * @see https://facebook.github.io/react-native/docs/view.html#style\n         */\n        style?: ViewStyle\n\n\n        /**\n         * The color of the underlay that will show through when the touch is active.\n         */\n        underlayColor?: string\n    }\n\n    /**\n     * A wrapper for making views respond properly to touches.\n     * On press down, the opacity of the wrapped view is decreased,\n     * which allows the underlay color to show through, darkening or tinting the view.\n     * The underlay comes from adding a view to the view hierarchy,\n     * which can sometimes cause unwanted visual artifacts if not used correctly,\n     * for example if the backgroundColor of the wrapped view isn't explicitly set to an opaque color.\n     *\n     * NOTE: TouchableHighlight supports only one child\n     * If you wish to have several child components, wrap them in a View.\n     *\n     * @see https://facebook.github.io/react-native/docs/touchablehighlight.html\n     */\n    export interface TouchableHighlightStatic extends React.ComponentClass<TouchableHighlightProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchableopacity.html#props\n     */\n    export interface TouchableOpacityProperties extends TouchableWithoutFeedbackProperties, React.Props<TouchableOpacityStatic> {\n        /**\n         * Determines what the opacity of the wrapped view should be when touch is active.\n         * Defaults to 0.2\n         */\n        activeOpacity?: number\n    }\n\n    /**\n     * A wrapper for making views respond properly to touches.\n     * On press down, the opacity of the wrapped view is decreased, dimming it.\n     * This is done without actually changing the view hierarchy,\n     * and in general is easy to add to an app without weird side-effects.\n     *\n     * @see https://facebook.github.io/react-native/docs/touchableopacity.html\n     */\n    export interface TouchableOpacityStatic extends React.ComponentClass<TouchableOpacityProperties> {\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/touchableopacity.html#props\n     */\n    export interface TouchableNativeFeedbackProperties extends TouchableWithoutFeedbackProperties, React.Props<TouchableNativeFeedbackStatic> {\n        /**\n         * Determines the type of background drawable that's going to be used to display feedback.\n         * It takes an object with type property and extra data depending on the type.\n         * It's recommended to use one of the following static methods to generate that dictionary:\n         *      1) TouchableNativeFeedback.SelectableBackground() - will create object that represents android theme's default background for selectable elements (?android:attr/selectableItemBackground)\n         *      2) TouchableNativeFeedback.SelectableBackgroundBorderless() - will create object that represent android theme's default background for borderless selectable elements (?android:attr/selectableItemBackgroundBorderless). Available on android API level 21+\n         *      3) TouchableNativeFeedback.Ripple(color, borderless) - will create object that represents ripple drawable with specified color (as a string). If property borderless evaluates to true the ripple will render outside of the view bounds (see native actionbar buttons as an example of that behavior). This background type is available on Android API level 21+\n         */\n        background?: any\n    }\n\n    /**\n     * A wrapper for making views respond properly to touches (Android only).\n     * On Android this component uses native state drawable to display touch feedback.\n     * At the moment it only supports having a single View instance as a child node,\n     * as it's implemented by replacing that View with another instance of RCTView node with some additional properties set.\n     *\n     * Background drawable of native feedback touchable can be customized with background property.\n     *\n     * @see https://facebook.github.io/react-native/docs/touchablenativefeedback.html#content\n     */\n    export interface TouchableNativeFeedbackStatic extends React.ComponentClass<TouchableNativeFeedbackProperties> {\n        SelectableBackground: () => TouchableNativeFeedbackStatic\n        SelectableBackgroundBorderless: () => TouchableNativeFeedbackStatic\n        Ripple: ( color: string, borderless?: boolean ) => TouchableNativeFeedbackStatic\n    }\n\n\n    export interface LeftToRightGesture {\n        //TODO:\n    }\n\n    export interface AnimationInterpolator {\n        //TODO:\n    }\n\n    // see /NavigatorSceneConfigs.js\n    export interface SceneConfig {\n        // A list of all gestures that are enabled on this scene\n        gestures: {\n            pop: LeftToRightGesture,\n        },\n\n        // Rebound spring parameters when transitioning FROM this scene\n        springFriction: number;\n        springTension: number;\n\n        // Velocity to start at when transitioning without gesture\n        defaultTransitionVelocity: number;\n\n        // Animation interpolators for horizontal transitioning:\n        animationInterpolators: {\n            into: AnimationInterpolator,\n            out: AnimationInterpolator\n        };\n\n    }\n\n    // see /NavigatorSceneConfigs.js\n    export interface SceneConfigs {\n        FloatFromBottom: SceneConfig;\n        FloatFromRight: SceneConfig;\n        PushFromRight: SceneConfig;\n        FloatFromLeft: SceneConfig;\n        HorizontalSwipeJump: SceneConfig;\n    }\n\n    export interface Route {\n        component?: ComponentClass<ViewProperties>\n        id?: string\n        title?: string\n        passProps?: Object;\n\n        //anything else\n        [key: string]: any\n\n        //Commonly found properties\n        backButtonTitle?: string\n        content?: string\n        message?: string;\n        index?: number\n        onRightButtonPress?: () => void\n        rightButtonTitle?: string\n        sceneConfig?: SceneConfig\n        wrapperStyle?: any\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/navigator.html#content\n     */\n    export interface NavigatorProperties extends React.Props<Navigator> {\n        /**\n         * Optional function that allows configuration about scene animations and gestures.\n         * Will be invoked with the route and should return a scene configuration object\n         * @param route\n         */\n        configureScene?: ( route: Route ) => SceneConfig\n        /**\n         * Specify a route to start on.\n         * A route is an object that the navigator will use to identify each scene to render.\n         * initialRoute must be a route in the initialRouteStack if both props are provided.\n         * The initialRoute will default to the last item in the initialRouteStack.\n         */\n        initialRoute?: Route\n        /**\n         * Provide a set of routes to initially mount.\n         * Required if no initialRoute is provided.\n         * Otherwise, it will default to an array containing only the initialRoute\n         */\n        initialRouteStack?: Route[]\n\n        /**\n         * Optionally provide a navigation bar that persists across scene transitions\n         */\n        navigationBar?: React.ReactElement<NavigatorStatic.NavigationBarProperties>\n\n        /**\n         * Optionally provide the navigator object from a parent Navigator\n         */\n        navigator?: Navigator\n\n        /**\n         * @deprecated Use navigationContext.addListener('willfocus', callback) instead.\n         */\n        onDidFocus?: Function\n\n        /**\n         * @deprecated Use navigationContext.addListener('willfocus', callback) instead.\n         */\n        onWillFocus?: Function\n\n        /**\n         * Required function which renders the scene for a given route.\n         * Will be invoked with the route and the navigator object\n         * @param route\n         * @param navigator\n         */\n        renderScene?: ( route: Route, navigator: Navigator ) => React.ReactElement<ViewProperties>\n\n        /**\n         * Styles to apply to the container of each scene\n         */\n        sceneStyle?: ViewStyle\n\n        /**\n         * //FIXME: not found in doc but found in examples\n         */\n        debugOverlay?: boolean\n\n    }\n\n    /**\n     * Use Navigator to transition between different scenes in your app.\n     * To accomplish this, provide route objects to the navigator to identify each scene,\n     * and also a renderScene function that the navigator can use to render the scene for a given route.\n     *\n     * To change the animation or gesture properties of the scene, provide a configureScene prop to get the config object for a given route.\n     * See Navigator.SceneConfigs for default animations and more info on scene config options.\n     * @see https://facebook.github.io/react-native/docs/navigator.html\n     */\n    export interface NavigatorStatic extends React.ComponentClass<NavigatorProperties> {\n        SceneConfigs: SceneConfigs;\n        NavigationBar: NavigatorStatic.NavigationBarStatic;\n        BreadcrumbNavigationBar: NavigatorStatic.BreadcrumbNavigationBarStatic\n\n        getContext( self: any ): NavigatorStatic;\n\n        /**\n         * returns the current list of routes\n         */\n        getCurrentRoutes(): Route[];\n\n        /**\n         * Jump backward without unmounting the current scen\n         */\n        jumpBack(): void;\n\n        /**\n         * Jump forward to the next scene in the route stack\n         */\n        jumpForward(): void;\n\n        /**\n         * Transition to an existing scene without unmounting\n         */\n        jumpTo( route: Route ): void;\n\n        /**\n         * Navigate forward to a new scene, squashing any scenes that you could jumpForward to\n         */\n        push( route: Route ): void;\n\n        /**\n         * Transition back and unmount the current scene\n         */\n        pop(): void;\n\n        /**\n         * Replace the current scene with a new route\n         */\n        replace( route: Route ): void;\n\n        /**\n         * Replace a scene as specified by an index\n         */\n        replaceAtIndex( route: Route, index: number ): void;\n\n        /**\n         *  Replace the previous scene\n         */\n        replacePrevious( route: Route ): void;\n\n        /**\n         * Reset every scene with an array of routes\n         */\n        immediatelyResetRouteStack( routes: Route[] ): void;\n\n        /**\n         * Pop to a particular scene, as specified by its route. All scenes after it will be unmounted\n         */\n        popToRoute( route: Route ): void;\n\n        /**\n         * Pop to the first scene in the stack, unmounting every other scene\n         */\n        popToTop(): void;\n\n    }\n\n    namespace NavigatorStatic {\n\n\n        export interface NavState {\n            routeStack: Route[]\n            idStack: number[]\n            presentedIndex: number\n        }\n\n        export interface NavigationBarStyle {\n            //TODO @see NavigationBarStyle.ios.js\n        }\n\n\n        export interface NavigationBarRouteMapper {\n            Title: ( route: Route, nav: Navigator, index: number, navState: NavState ) => React.ReactElement<any>;\n            LeftButton: ( route: Route, nav: Navigator, index: number, navState: NavState )=> React.ReactElement<any>;\n            RightButton: ( route: Route, nav: Navigator, index: number, navState: NavState )=> React.ReactElement<any>;\n        }\n\n        /**\n         * @see NavigatorNavigationBar.js\n         */\n        export interface NavigationBarProperties extends React.Props<NavigationBarStatic> {\n            navigator?: Navigator\n            routeMapper?: NavigationBarRouteMapper\n            navState?: NavState\n            style?: ViewStyle\n        }\n\n        export interface NavigationBarStatic extends React.ComponentClass<NavigationBarProperties> {\n            Styles: NavigationBarStyle\n\n        }\n\n        export type NavigationBar = NavigationBarStatic\n        export var NavigationBar: NavigationBarStatic\n\n\n        export interface BreadcrumbNavigationBarStyle {\n            //TODO &see NavigatorBreadcrumbNavigationBar.js\n        }\n\n        export interface BreadcrumbNavigationBarRouteMapper {\n            rightContentForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n            titleContentForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n            iconForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n            //in samples...\n            separatorForRoute: ( route: Route, navigator: Navigator ) => React.ReactElement<any>\n        }\n\n        /**\n         * @see NavigatorNavigationBar.js\n         */\n        export interface BreadcrumbNavigationBarProperties extends React.Props<BreadcrumbNavigationBarStatic> {\n            navigator?: Navigator\n            routeMapper?: BreadcrumbNavigationBarRouteMapper\n            navState?: NavState\n            style?: ViewStyle\n        }\n\n        export interface BreadcrumbNavigationBarStatic extends React.ComponentClass<BreadcrumbNavigationBarProperties> {\n            Styles: BreadcrumbNavigationBarStyle\n        }\n\n        export type BreadcrumbNavigationBar = BreadcrumbNavigationBarStatic\n        var BreadcrumbNavigationBar: BreadcrumbNavigationBarStatic\n\n    }\n\n\n    export interface StyleSheetStatic extends React.ComponentClass<StyleSheetProperties> {\n        create<T>( styles: T ): T;\n    }\n\n    /**\n     * //FIXME: Could not find docs. Inferred from examples and jscode : ListViewDataSource.js\n     */\n    export interface DataSourceAssetCallback {\n        rowHasChanged?: ( r1: any, r2: any ) => boolean\n        sectionHeaderHasChanged?: ( h1: any, h2: any ) => boolean\n        getRowData?: <T>( dataBlob: any, sectionID: number | string, rowID: number | string ) => T\n        getSectionHeaderData?: <T>( dataBlob: any, sectionID: number | string ) => T\n    }\n\n    /**\n     * //FIXME: Could not find docs. Inferred from examples and js showapi_res_code: ListViewDataSource.js\n     */\n    export interface ListViewDataSource {\n        new( onAsset: DataSourceAssetCallback ): ListViewDataSource;\n        /**\n         * Clones this `ListViewDataSource` with the specified `dataBlob` and\n         * `rowIdentities`. The `dataBlob` is just an aribitrary blob of data. At\n         * construction an extractor to get the interesting informatoin was defined\n         * (or the default was used).\n         *\n         * The `rowIdentities` is is a 2D array of identifiers for rows.\n         * ie. [['a1', 'a2'], ['b1', 'b2', 'b3'], ...].  If not provided, it's\n         * assumed that the keys of the section data are the row identities.\n         *\n         * Note: This function does NOT clone the data in this data source. It simply\n         * passes the functions defined at construction to a new data source with\n         * the data specified. If you wish to maintain the existing data you must\n         * handle merging of old and new data separately and then pass that into\n         * this function as the `dataBlob`.\n         */\n        cloneWithRows<T>( dataBlob: Array<any> | {[key: string ]: any}, rowIdentities?: Array<string | number> ): ListViewDataSource\n\n        /**\n         * This performs the same function as the `cloneWithRows` function but here\n         * you also specify what your `sectionIdentities` are. If you don't care\n         * about sections you should safely be able to use `cloneWithRows`.\n         *\n         * `sectionIdentities` is an array of identifiers for  sections.\n         * ie. ['s1', 's2', ...].  If not provided, it's assumed that the\n         * keys of dataBlob are the section identities.\n         *\n         * Note: this returns a new object!\n         */\n        cloneWithRowsAndSections( dataBlob: Array<any> | {[key: string]: any}, sectionIdentities?: Array<string | number>, rowIdentities?: Array<Array<string | number>> ): ListViewDataSource\n\n        getRowCount(): number\n\n        /**\n         * Gets the data required to render the row.\n         */\n        getRowData( sectionIndex: number, rowIndex: number ): any\n\n        /**\n         * Gets the rowID at index provided if the dataSource arrays were flattened,\n         * or null of out of range indexes.\n         */\n        getRowIDForFlatIndex( index: number ): string\n\n        /**\n         * Gets the sectionID at index provided if the dataSource arrays were flattened,\n         * or null for out of range indexes.\n         */\n        getSectionIDForFlatIndex( index: number ): string\n\n        /**\n         * Returns an array containing the number of rows in each section\n         */\n        getSectionLengths(): Array<number>\n\n        /**\n         * Returns if the section header is dirtied and needs to be rerendered\n         */\n        sectionHeaderShouldUpdate( sectionIndex: number ): boolean\n\n        /**\n         * Gets the data required to render the section header\n         */\n        getSectionHeaderData( sectionIndex: number ): any\n    }\n\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/tabbarios-item.html#props\n     */\n    export interface TabBarItemProperties extends React.Props<TabBarItemStatic> {\n\n        /**\n         * Little red bubble that sits at the top right of the icon.\n         */\n        badge?:  string | number\n\n        /**\n         * A custom icon for the tab. It is ignored when a system icon is defined.\n         */\n        icon?: {uri: string} | string\n\n        /**\n         * Callback when this tab is being selected,\n         * you should change the state of your component to set selected={true}.\n         */\n        onPress?: () => void\n\n        /**\n         * It specifies whether the children are visible or not. If you see a blank content, you probably forgot to add a selected one.\n         */\n        selected?: boolean\n\n        /**\n         * A custom icon when the tab is selected.\n         * It is ignored when a system icon is defined. If left empty, the icon will be tinted in blue.\n         */\n        selectedIcon?: {uri: string} | string;\n\n        /**\n         * React style object.\n         */\n        style?: ViewStyle\n\n        /**\n         * Items comes with a few predefined system icons.\n         * Note that if you are using them, the title and selectedIcon will be overridden with the system ones.\n         *\n         *  enum('bookmarks', 'contacts', 'downloads', 'favorites', 'featured', 'history', 'more', 'most-recent', 'most-viewed', 'recents', 'search', 'top-rated')\n         */\n        systemIcon: string\n\n        /**\n         * Text that appears under the icon. It is ignored when a system icon is defined.\n         */\n        title?: string\n\n    }\n\n    export interface TabBarItemStatic extends React.ComponentClass<TabBarItemProperties> {\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/tabbarios.html#props\n     */\n    export interface TabBarIOSProperties extends React.Props<TabBarIOSStatic> {\n\n        /**\n         * Background color of the tab bar\n         */\n        barTintColor?: string\n\n        style?: ViewStyle\n\n        /**\n         * Color of the currently selected tab icon\n         */\n        tintColor?: string\n\n        /**\n         * A Boolean value that indicates whether the tab bar is translucent\n         */\n        translucent?: boolean\n    }\n\n    export interface TabBarIOSStatic extends React.ComponentClass<TabBarIOSProperties> {\n        Item: TabBarItemStatic;\n    }\n\n\n    export interface PixelRatioStatic {\n        get(): number;\n    }\n\n    export interface DeviceEventSubscriptionStatic {\n        remove(): void;\n    }\n\n    export interface DeviceEventEmitterStatic {\n        addListener<T>( type: string, onReceived: ( data: T ) => void ): DeviceEventSubscription;\n    }\n\n    // Used by Dimensions below\n    export interface ScaledSize {\n        width: number;\n        height: number;\n        scale: number;\n    }\n\n\n    export interface InteractionManagerStatic {\n        runAfterInteractions( fn: () => void ): void;\n    }\n\n\n    export interface ScrollViewStyle extends FlexStyle, TransformsStyle {\n\n        backfaceVisibility?:string //enum('visible', 'hidden')\n        backgroundColor?: string\n        borderColor?: string\n        borderTopColor?: string\n        borderRightColor?: string\n        borderBottomColor?: string\n        borderLeftColor?: string\n        borderRadius?: number\n        borderTopLeftRadius?: number\n        borderTopRightRadius?: number\n        borderBottomLeftRadius?: number\n        borderBottomRightRadius?: number\n        borderStyle?: string //enum('solid', 'dotted', 'dashed')\n        borderWidth?: number\n        borderTopWidth?: number\n        borderRightWidth?: number\n        borderBottomWidth?: number\n        borderLeftWidth?: number\n        opacity?: number\n        overflow?: string //enum('visible', 'hidden')\n        shadowColor?: string\n        shadowOffset?: {width: number; height: number}\n        shadowOpacity?: number\n        shadowRadius?: number\n    }\n\n\n    export interface ScrollViewIOSProperties {\n\n        /**\n         * When true the scroll view bounces horizontally when it reaches the end\n         * even if the content is smaller than the scroll view itself. The default\n         * value is true when `horizontal={true}` and false otherwise.\n         */\n        alwaysBounceHorizontal?: boolean\n        /**\n         * When true the scroll view bounces vertically when it reaches the end\n         * even if the content is smaller than the scroll view itself. The default\n         * value is false when `horizontal={true}` and true otherwise.\n         */\n        alwaysBounceVertical?: boolean\n\n        /**\n         * Controls whether iOS should automatically adjust the content inset for scroll views that are placed behind a navigation bar or tab bar/ toolbar.\n         * The default value is true.\n         */\n        automaticallyAdjustContentInsets?: boolean // true\n\n        /**\n         * When true the scroll view bounces when it reaches the end of the\n         * content if the content is larger then the scroll view along the axis of\n         * the scroll direction. When false it disables all bouncing even if\n         * the `alwaysBounce*` props are true. The default value is true.\n         */\n        bounces?: boolean\n        /**\n         * When true gestures can drive zoom past min/max and the zoom will animate\n         * to the min/max value at gesture end otherwise the zoom will not exceed\n         * the limits.\n         */\n        bouncesZoom?: boolean\n\n        /**\n         * When false once tracking starts won't try to drag if the touch moves.\n         * The default value is true.\n         */\n        canCancelContentTouches?: boolean\n\n        /**\n         * When true the scroll view automatically centers the content when the\n         * content is smaller than the scroll view bounds; when the content is\n         * larger than the scroll view this property has no effect. The default\n         * value is false.\n         */\n        centerContent?: boolean\n\n\n        /**\n         * The amount by which the scroll view content is inset from the edges of the scroll view.\n         * Defaults to {0, 0, 0, 0}.\n         */\n        contentInset?: Insets // zeros\n\n        /**\n         * Used to manually set the starting scroll offset.\n         * The default value is {x: 0, y: 0}\n         */\n        contentOffset?: PointProperties // zeros\n\n        /**\n         * A floating-point number that determines how quickly the scroll view\n         * decelerates after the user lifts their finger. Reasonable choices include\n         *   - Normal: 0.998 (the default)\n         *   - Fast: 0.9\n         */\n        decelerationRate?: number\n\n        /**\n         * When true the ScrollView will try to lock to only vertical or horizontal\n         * scrolling while dragging.  The default value is false.\n         */\n        directionalLockEnabled?: boolean\n\n        /**\n         * The maximum allowed zoom scale. The default value is 1.0.\n         */\n        maximumZoomScale?: number\n\n        /**\n         * The minimum allowed zoom scale. The default value is 1.0.\n         */\n        minimumZoomScale?: number\n\n        /**\n         * Called when a scrolling animation ends.\n         */\n        onScrollAnimationEnd?: () => void\n\n        /**\n         * When true the scroll view stops on multiples of the scroll view's size\n         * when scrolling. This can be used for horizontal pagination. The default\n         * value is false.\n         */\n        pagingEnabled?: boolean\n\n        /**\n         * When false, the content does not scroll. The default value is true\n         */\n        scrollEnabled?: boolean // true\n\n        /**\n         * This controls how often the scroll event will be fired while scrolling (in events per seconds).\n         * A higher number yields better accuracy for showapi_res_code that is tracking the scroll position,\n         * but can lead to scroll performance problems due to the volume of information being send over the bridge.\n         * The default value is zero, which means the scroll event will be sent only once each time the view is scrolled.\n         */\n        scrollEventThrottle?: number // null\n\n        /**\n         * The amount by which the scroll view indicators are inset from the edges of the scroll view.\n         * This should normally be set to the same value as the contentInset.\n         * Defaults to {0, 0, 0, 0}.\n         */\n        scrollIndicatorInsets?: Insets //zeroes\n\n        /**\n         * When true the scroll view scrolls to top when the status bar is tapped.\n         * The default value is true.\n         */\n        scrollsToTop?: boolean\n\n        /**\n         * When snapToInterval is set, snapToAlignment will define the relationship of the the snapping to the scroll view.\n         *      - start (the default) will align the snap at the left (horizontal) or top (vertical)\n         *      - center will align the snap in the center\n         *      - end will align the snap at the right (horizontal) or bottom (vertical)\n         */\n        snapToAlignment?: string\n\n        /**\n         * When set, causes the scroll view to stop at multiples of the value of snapToInterval.\n         * This can be used for paginating through children that have lengths smaller than the scroll view.\n         * Used in combination with snapToAlignment.\n         */\n        snapToInterval?: number\n\n        /**\n         * An array of child indices determining which children get docked to the\n         * top of the screen when scrolling. For example passing\n         * `stickyHeaderIndices={[0]}` will cause the first child to be fixed to the\n         * top of the scroll view. This property is not supported in conjunction\n         * with `horizontal={true}`.\n         */\n        stickyHeaderIndices?: number[]\n\n        /**\n         * The current scale of the scroll view content. The default value is 1.0.\n         */\n        zoomScale?: number\n    }\n\n    export interface ScrollViewProperties extends ScrollViewIOSProperties, Touchable {\n\n        /**\n         * These styles will be applied to the scroll view content container which\n         * wraps all of the child views. Example:\n         *\n         *   return (\n         *     <ScrollView contentContainerStyle={styles.contentContainer}>\n         *     </ScrollView>\n         *   );\n         *   ...\n         *   var styles = StyleSheet.create({\n         *     contentContainer: {\n         *       paddingVertical: 20\n         *     }\n         *   });\n         */\n        contentContainerStyle?: ViewStyle\n\n        /**\n         * When true the scroll view's children are arranged horizontally in a row\n         * instead of vertically in a column. The default value is false.\n         */\n        horizontal?: boolean\n\n        /**\n         * Determines whether the keyboard gets dismissed in response to a drag.\n         *   - 'none' (the default) drags do not dismiss the keyboard.\n         *   - 'onDrag' the keyboard is dismissed when a drag begins.\n         *   - 'interactive' the keyboard is dismissed interactively with the drag\n         *     and moves in synchrony with the touch; dragging upwards cancels the\n         *     dismissal.\n         */\n        keyboardDismissMode?: string\n\n        /**\n         * When false tapping outside of the focused text input when the keyboard\n         * is up dismisses the keyboard. When true the scroll view will not catch\n         * taps and the keyboard will not dismiss automatically. The default value\n         * is false.\n         */\n        keyboardShouldPersistTaps?: boolean\n\n        /**\n         * Fires at most once per frame during scrolling.\n         * The frequency of the events can be contolled using the scrollEventThrottle prop.\n         */\n        onScroll?: (event?: { nativeEvent: NativeScrollEvent }) => void\n\n        /**\n         * Experimental: When true offscreen child views (whose `overflow` value is\n         * `hidden`) are removed from their native backing superview when offscreen.\n         * This canimprove scrolling performance on long lists. The default value is\n         * false.\n         */\n        removeClippedSubviews?: boolean\n\n        /**\n         * When true, shows a horizontal scroll indicator.\n         */\n        showsHorizontalScrollIndicator?: boolean\n\n        /**\n         * When true, shows a vertical scroll indicator.\n         */\n        showsVerticalScrollIndicator?: boolean\n\n        /**\n         * Style\n         */\n        style?: ScrollViewStyle\n    }\n\n    export interface ScrollViewProps extends ScrollViewProperties, React.Props<ScrollViewStatic> {\n\n    }\n\n    interface ScrollViewStatic extends React.ComponentClass<ScrollViewProps> {\n\n    }\n\n\n    export interface NativeScrollRectangle {\n        left: number;\n        top: number;\n        bottom: number;\n        right: number;\n    }\n\n    export interface NativeScrollPoint {\n        x: number;\n        y: number;\n    }\n\n    export interface NativeScrollSize {\n        height: number;\n        width: number;\n    }\n\n    export interface NativeScrollEvent {\n        contentInset: NativeScrollRectangle;\n        contentOffset: NativeScrollPoint;\n        contentSize: NativeScrollSize;\n        layoutMeasurement: NativeScrollSize;\n        zoomScale: number;\n    }\n\n\n    //////////////////////////////////////////////////////////////////////////\n    //\n    // A P I s\n    //\n    //////////////////////////////////////////////////////////////////////////\n\n    /**\n     * //FIXME: no documentation - inferred from RCTACtionSheetManager.m\n     */\n    export interface ActionSheetIOSOptions {\n        title?: string\n        options?: string[]\n        cancelButtonIndex?: number\n        destructiveButtonIndex?: number\n    }\n\n    /**\n     * //FIXME: no documentation - inferred from RCTACtionSheetManager.m\n     */\n    export interface ShareActionSheetIOSOptions {\n        message?: string\n        url?: string\n    }\n\n    /**\n     * @see https://facebook.github.io/react-native/docs/actionsheetios.html#content\n     * //FIXME: no documentation - inferred from RCTACtionSheetManager.m\n     */\n    export interface ActionSheetIOSStatic {\n        showActionSheetWithOptions: ( options: ActionSheetIOSOptions, callback: ( buttonIndex: number ) => void ) => void\n        showShareActionSheetWithOptions: ( options: ShareActionSheetIOSOptions, failureCallback: ( error: Error ) => void, successCallback: ( success: boolean, method: string ) => void ) => void\n    }\n\n\n    /**\n     * //FIXME: No documentation - inferred from RCTAdSupport.m\n     */\n    export interface AdSupportIOSStatic {\n        getAdvertisingId: ( onSuccess: ( deviceId: string ) => void, onFailure: ( err: Error ) => void ) => void\n        getAdvertisingTrackingEnabled: ( onSuccess: ( hasTracking: boolean ) => void, onFailure: ( err: Error ) => void ) => void\n    }\n\n    interface AlertIOSButton {\n        text: string\n        onPress?: () => void\n    }\n\n    /**\n     * Launches an alert dialog with the specified title and message.\n     *\n     * Optionally provide a list of buttons.\n     * Tapping any button will fire the respective onPress callback and dismiss the alert.\n     * By default, the only button will be an 'OK' button\n     *\n     * The last button in the list will be considered the 'Primary' button and it will appear bold.\n     *\n     * @see https://facebook.github.io/react-native/docs/alertios.html#content\n     */\n    export interface AlertIOSStatic {\n        alert: ( title: string, message?: string, buttons?: Array<AlertIOSButton>, type?: string ) => void\n        prompt: ( title: string, value?: string, buttons?: Array<AlertIOSButton>, callback?: ( value?: string ) => void ) => void\n    }\n\n\n    /**\n     * AppStateIOS can tell you if the app is in the foreground or background,\n     * and notify you when the state changes.\n     *\n     * AppStateIOS is frequently used to determine the intent and proper behavior\n     * when handling push notifications.\n     *\n     * iOS App States\n     *      active - The app is running in the foreground\n     *      background - The app is running in the background. The user is either in another app or on the home screen\n     *      inactive - This is a transition state that currently never happens for typical React Native apps.\n     *\n     * For more information, see Apple's documentation: https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/TheAppLifeCycle/TheAppLifeCycle.html\n     *\n     * @see https://facebook.github.io/react-native/docs/appstateios.html#content\n     */\n    export interface AppStateIOSStatic {\n        currentState: string\n        addEventListener( type: string, listener: ( state: string ) => void ): void\n        removeEventListener( type: string, listener: ( state: string ) => void ): void\n    }\n\n    /**\n     * AsyncStorage is a simple, asynchronous, persistent, key-value storage system that is global to the app.\n     * It should be used instead of LocalStorage.\n     *\n     * It is recommended that you use an abstraction on top of AsyncStorage\n     * instead of AsyncStorage directly for anything more than light usage since it operates globally.\n     *\n     * @see https://facebook.github.io/react-native/docs/asyncstorage.html#content\n     */\n    export interface AsyncStorageStatic {\n\n        /**\n         * Fetches key and passes the result to callback, along with an Error if there is any.\n         */\n        getItem( key: string, callback?: ( error?: Error, result?: string ) => void ): Promise<string>\n\n        /**\n         * Sets value for key and calls callback on completion, along with an Error if there is any\n         */\n        setItem( key: string, value: string, callback?: ( error?: Error ) => void ): Promise<string>\n\n        removeItem( key: string, callback?: ( error?: Error ) => void ): Promise<string>\n\n        /**\n         * Merges existing value with input value, assuming they are stringified json. Returns a Promise object.\n         * Not supported by all native implementation\n         */\n        mergeItem( key: string, value: string, callback?: ( error?: Error ) => void ): Promise<string>\n\n        /**\n         * Erases all AsyncStorage for all clients, libraries, etc. You probably don't want to call this.\n         * Use removeItem or multiRemove to clear only your own keys instead.\n         */\n        clear( callback?: ( error?: Error ) => void ): Promise<string>\n\n        /**\n         * Gets all keys known to the app, for all callers, libraries, etc\n         */\n        getAllKeys( callback?: ( error?: Error, keys?: string[] ) => void ): Promise<string>\n\n        /**\n         * multiGet invokes callback with an array of key-value pair arrays that matches the input format of multiSet\n         */\n        multiGet( keys: string[], callback?: ( errors?: Error[], result?: string[][] ) => void ): Promise<string>\n\n        /**\n         * multiSet and multiMerge take arrays of key-value array pairs that match the output of multiGet,\n         *\n         * multiSet([['k1', 'val1'], ['k2', 'val2']], cb);\n         */\n        multiSet( keyValuePairs: string[][], callback?: ( errors?: Error[] ) => void ): Promise<string>\n\n        /**\n         * Delete all the keys in the keys array.\n         */\n        multiRemove( keys: string[], callback?: ( errors?: Error[] ) => void ): Promise<string>\n\n        /**\n         * Merges existing values with input values, assuming they are stringified json.\n         * Returns a Promise object.\n         *\n         * Not supported by all native implementations.\n         */\n        multiMerge( keyValuePairs: string[][], callback?: ( errors?: Error[] ) => void ): Promise<string>\n    }\n\n\n    export interface CameraRollFetchParams {\n        first: number;\n        after?: string;\n        groupTypes: string; //  'Album','All','Event','Faces','Library','PhotoStream','SavedPhotos'\n        groupName?: string\n        assetType?: string\n    }\n\n    export interface CameraRollNodeInfo {\n        image: Image;\n        group_name: string;\n        timestamp: number;\n        location: any;\n    }\n\n    export interface CameraRollEdgeInfo {\n        node: CameraRollNodeInfo;\n    }\n\n    export interface CameraRollAssetInfo {\n        edges: CameraRollEdgeInfo[];\n        page_info: {\n            has_next_page: boolean;\n            end_cursor: string;\n        };\n    }\n\n    /**\n     * CameraRoll provides access to the local camera roll / gallery.\n     */\n    export interface CameraRollStatic {\n\n        GroupTypesOptions: string[] //'Album','All','Event','Faces','Library','PhotoStream','SavedPhotos'\n\n        /**\n         * Saves the image to the camera roll / gallery.\n         *\n         * The CameraRoll API is not yet implemented for Android.\n         *\n         * @tag On Android, this is a local URI, such as \"file:///sdcard/img.png\".\n         * On iOS, the tag can be one of the following:\n         *      local URI\n         *      assets-library tag\n         *      a tag not maching any of the above, which means the image data will be stored in memory (and consume memory as long as the process is alive)\n         *\n         * @param successCallback Invoked with the value of tag on success.\n         * @param errorCallback Invoked with error message on error.\n         */\n        saveImageWithTag( tag: string, successCallback: ( tag?: string ) => void, errorCallback: ( error: Error ) => void ): void\n\n        /**\n         * Invokes callback with photo identifier objects from the local camera roll of the device matching shape defined by getPhotosReturnChecker.\n         *\n         * @param {object} params See getPhotosParamChecker.\n         * @param {function} callback Invoked with arg of shape defined by getPhotosReturnChecker on success.\n         * @param {function} errorCallback Invoked with error message on error.\n         */\n        getPhotos( fetch: CameraRollFetchParams,\n                   callback: ( assetInfo: CameraRollAssetInfo ) => void,\n                   errorCallback: ( error: Error )=> void ): void;\n    }\n\n    export interface FetchableListenable<T> {\n        fetch: () => Promise<T>\n\n        /**\n         * eventName is expected to be `change`\n         * //FIXME: No doc - inferred from NetInfo.js\n         */\n        addEventListener: ( eventName: string, listener: ( result: T ) => void ) => void\n\n        /**\n         * eventName is expected to be `change`\n         * //FIXME: No doc - inferred from NetInfo.js\n         */\n        removeEventListener: ( eventName: string, listener: ( result: T ) => void ) => void\n    }\n\n    /**\n     * NetInfo exposes info about online/offline status\n     *\n     * Asynchronously determine if the device is online and on a cellular network.\n     *\n     * - `none` - device is offline\n     * - `wifi` - device is online and connected via wifi, or is the iOS simulator\n     * - `cell` - device is connected via Edge, 3G, WiMax, or LTE\n     * - `unknown` - error case and the network status is unknown\n\n     * @see https://facebook.github.io/react-native/docs/netinfo.html#content\n     */\n    export interface NetInfoStatic extends FetchableListenable<string> {\n\n        /**\n         *\n         * Available on all platforms.\n         * Asynchronously fetch a boolean to determine internet connectivity.\n         */\n        isConnected: FetchableListenable<boolean>\n\n        //FIXME: Documentation missing\n        isConnectionMetered: any\n    }\n\n\n    export interface PanResponderGestureState {\n\n        /**\n         *  ID of the gestureState- persisted as long as there at least one touch on\n         */\n        stateID: number\n\n        /**\n         *  the latest screen coordinates of the recently-moved touch\n         */\n        moveX: number\n\n        /**\n         *  the latest screen coordinates of the recently-moved touch\n         */\n        moveY: number\n\n        /**\n         * the screen coordinates of the responder grant\n         */\n        x0: number\n\n        /**\n         * the screen coordinates of the responder grant\n         */\n        y0: number\n\n        /**\n         * accumulated distance of the gesture since the touch started\n         */\n        dx: number\n\n        /**\n         * accumulated distance of the gesture since the touch started\n         */\n        dy: number\n\n        /**\n         * current velocity of the gesture\n         */\n        vx: number\n\n        /**\n         * current velocity of the gesture\n         */\n        vy: number\n\n        /**\n         * Number of touches currently on screeen\n         */\n        numberActiveTouches: number\n\n\n        // All `gestureState` accounts for timeStamps up until:\n        _accountsForMovesUpTo: number\n    }\n\n\n    /**\n     * @see documentation of GestureResponderHandlers\n     */\n    export interface PanResponderCallbacks {\n        onMoveShouldSetPanResponder?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n        onStartShouldSetPanResponder?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderGrant?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderMove?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderRelease?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderTerminate?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n\n        onMoveShouldSetPanResponderCapture?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n        onStartShouldSetPanResponderCapture?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n        onPanResponderReject?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderStart?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderEnd?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => void\n        onPanResponderTerminationRequest?: ( e: GestureResponderEvent, gestureState: PanResponderGestureState ) => boolean\n    }\n\n    export interface PanResponderInstance {\n        panHandlers: GestureResponderHandlers\n    }\n\n    /**\n     * PanResponder reconciles several touches into a single gesture.\n     * It makes single-touch gestures resilient to extra touches,\n     * and can be used to recognize simple multi-touch gestures.\n     *\n     * It provides a predictable wrapper of the responder handlers provided by the gesture responder system.\n     * For each handler, it provides a new gestureState object alongside the normal event.\n     */\n    export interface PanResponderStatic {\n        /**\n         * @param config Enhanced versions of all of the responder callbacks\n         * that provide not only the typical `ResponderSyntheticEvent`, but also the\n         * `PanResponder` gesture state.  Simply replace the word `Responder` with\n         * `PanResponder` in each of the typical `onResponder*` callbacks. For\n         * example, the `config` object would look like:\n         *\n         *  - `onMoveShouldSetPanResponder: (e, gestureState) => {...}`\n         *  - `onMoveShouldSetPanResponderCapture: (e, gestureState) => {...}`\n         *  - `onStartShouldSetPanResponder: (e, gestureState) => {...}`\n         *  - `onStartShouldSetPanResponderCapture: (e, gestureState) => {...}`\n         *  - `onPanResponderReject: (e, gestureState) => {...}`\n         *  - `onPanResponderGrant: (e, gestureState) => {...}`\n         *  - `onPanResponderStart: (e, gestureState) => {...}`\n         *  - `onPanResponderEnd: (e, gestureState) => {...}`\n         *  - `onPanResponderRelease: (e, gestureState) => {...}`\n         *  - `onPanResponderMove: (e, gestureState) => {...}`\n         *  - `onPanResponderTerminate: (e, gestureState) => {...}`\n         *  - `onPanResponderTerminationRequest: (e, gestureState) => {...}`\n         *\n         *  In general, for events that have capture equivalents, we update the\n         *  gestureState once in the capture phase and can use it in the bubble phase\n         *  as well.\n         *\n         *  Be careful with onStartShould* callbacks. They only reflect updated\n         *  `gestureState` for start/end events that bubble/capture to the Node.\n         *  Once the node is the responder, you can rely on every start/end event\n         *  being processed by the gesture and `gestureState` being updated\n         *  accordingly. (numberActiveTouches) may not be totally accurate unless you\n         *  are the responder.\n         */\n        create( config: PanResponderCallbacks ): PanResponderInstance\n    }\n\n    export interface PushNotificationPermissions {\n        alert?: boolean\n        badge?: boolean\n        sound?: boolean\n    }\n\n    export interface PushNotification {\n\n\n        /**\n         * An alias for `getAlert` to get the notification's main message string\n         */\n        getMessage(): string | Object\n\n        /**\n         * Gets the sound string from the `aps` object\n         */\n        getSound(): string\n\n        /**\n         * Gets the notification's main message from the `aps` object\n         */\n        getAlert(): string | Object\n\n        /**\n         * Gets the badge count number from the `aps` object\n         */\n        getBadgeCount(): number\n\n        /**\n         * Gets the data object on the notif\n         */\n        getData(): Object\n\n    }\n\n\n    /**\n     * Handle push notifications for your app, including permission handling and icon badge number.\n     * @see https://facebook.github.io/react-native/docs/pushnotificationios.html#content\n     *\n     * //FIXME: BGR: The documentation seems completely off compared to the actual js implementation. I could never get the example to run\n     */\n    export interface PushNotificationIOSStatic {\n\n        /**\n         * Sets the badge number for the app icon on the home screen\n         */\n        setApplicationIconBadgeNumber( number: number ): void\n\n        /**\n         * Gets the current badge number for the app icon on the home screen\n         */\n        getApplicationIconBadgeNumber( callback: ( badge: number ) => void ): void\n\n        /**\n         * Attaches a listener to remote notifications while the app is running in the\n         * foreground or the background.\n         *\n         * The handler will get be invoked with an instance of `PushNotificationIOS`\n         *\n         * The type MUST be 'notification'\n         */\n        addEventListener( type: string, handler: ( notification: PushNotification ) => void ):void\n\n        /**\n         * Requests all notification permissions from iOS, prompting the user's\n         * dialog box.\n         */\n        requestPermissions(): void\n\n        /**\n         * See what push permissions are currently enabled. `callback` will be\n         * invoked with a `permissions` object:\n         *\n         *  - `alert` :boolean\n         *  - `badge` :boolean\n         *  - `sound` :boolean\n         */\n        checkPermissions( callback: ( permissions: PushNotificationPermissions ) => void ): void\n\n        /**\n         * Removes the event listener. Do this in `componentWillUnmount` to prevent\n         * memory leaks\n         */\n        removeEventListener( type: string, handler: ( notification: PushNotification ) => void ): void\n\n        /**\n         * An initial notification will be available if the app was cold-launched\n         * from a notification.\n         *\n         * The first caller of `popInitialNotification` will get the initial\n         * notification object, or `null`. Subsequent invocations will return null.\n         */\n        popInitialNotification(): PushNotification\n    }\n\n\n    /**\n     * @enum('default', 'light-content')\n     */\n    export type StatusBarStyle = string\n\n    /**\n     * @enum('none','fade', 'slide')\n     */\n    type StatusBarAnimation = string\n\n\n    /**\n     * //FIXME: No documentation is available (although this is self explanatory)\n     *\n     * @see https://facebook.github.io/react-native/docs/statusbarios.html#content\n     */\n    export interface StatusBarIOSStatic {\n\n        setStyle(style: StatusBarStyle, animated?: boolean): void\n\n        setHidden(hidden: boolean, animation?: StatusBarAnimation): void\n\n        setNetworkActivityIndicatorVisible(visible: boolean): void\n    }\n\n    /**\n     * The Vibration API is exposed at VibrationIOS.vibrate().\n     * On iOS, calling this function will trigger a one second vibration.\n     * The vibration is asynchronous so this method will return immediately.\n     *\n     * There will be no effect on devices that do not support Vibration, eg. the iOS simulator.\n     *\n     * Vibration patterns are currently unsupported.\n     *\n     * @see https://facebook.github.io/react-native/docs/vibrationios.html#content\n     */\n    export interface VibrationIOSStatic {\n        vibrate(): void\n    }\n\n    //////////////////////////////////////////////////////////////////////////\n    //\n    //  R E - E X P O R T S\n    //\n    //////////////////////////////////////////////////////////////////////////\n\n    // export var AppRegistry: AppRegistryStatic;\n\n\n    export var ActivityIndicatorIOS: ActivityIndicatorIOSStatic\n    export type ActivityIndicatorIOS = ActivityIndicatorIOSStatic\n\n    export var DatePickerIOS: DatePickerIOSStatic\n    export type DatePickerIOS = DatePickerIOSStatic\n\n    export var Image: ImageStatic\n    export type Image = ImageStatic\n\n    export var LayoutAnimation: LayoutAnimationStatic\n    export type LayoutAnimation = LayoutAnimationStatic\n\n    export var ListView: ListViewStatic\n    export type ListView = ListViewStatic\n\n    export var MapView: MapViewStatic\n    export type MapView = MapViewStatic\n\n    export var Navigator: NavigatorStatic\n    export type Navigator = NavigatorStatic\n\n    export var NavigatorIOS: NavigatorIOSStatic\n    export type NavigatorIOS = NavigatorIOSStatic\n\n    export var PickerIOS: PickerIOSStatic\n    export type PickerIOS = PickerIOSStatic\n\n    export var SliderIOS: SliderIOSStatic\n    export type SliderIOS = SliderIOSStatic\n\n    export var ScrollView: ScrollViewStatic\n    export type ScrollView = ScrollViewStatic\n\n    export var StyleSheet: StyleSheetStatic\n    export type StyleSheet = StyleSheetStatic\n\n    export var SwitchIOS: SwitchIOSStatic\n    export type SwitchIOS = SwitchIOSStatic\n\n    export var TabBarIOS: TabBarIOSStatic\n    export type TabBarIOS = TabBarIOSStatic\n\n    export var Text: TextStatic\n    export type Text = TextStatic\n\n    export var TextInput: TextInputStatic\n    export type TextInput = TextInputStatic\n\n    export var TouchableHighlight: TouchableHighlightStatic\n    export type TouchableHighlight = TouchableHighlightStatic\n\n    export var TouchableNativeFeedback: TouchableNativeFeedbackStatic\n    export type TouchableNativeFeedback = TouchableNativeFeedbackStatic\n\n    export var TouchableOpacity: TouchableOpacityStatic\n    export type TouchableOpacity = TouchableOpacityStatic\n\n    export var TouchableWithoutFeedback: TouchableWithoutFeedbackStatic\n    export type TouchableWithoutFeedback= TouchableWithoutFeedbackStatic\n\n    export var View: ViewStatic\n    export type View = ViewStatic\n\n    export var WebView: WebViewStatic\n    export type WebView = WebViewStatic\n\n\n    //////////// APIS //////////////\n    export var ActionSheetIOS: ActionSheetIOSStatic\n    export type ActionSheetIOS = ActionSheetIOSStatic\n\n    export var AdSupportIOS: AdSupportIOSStatic\n    export type AdSupportIOS = AdSupportIOSStatic\n\n    export var AlertIOS: AlertIOSStatic\n    export type AlertIOS = AlertIOSStatic\n\n    export var AppStateIOS: AppStateIOSStatic\n    export type AppStateIOS = AppStateIOSStatic\n\n    export var AsyncStorage: AsyncStorageStatic\n    export type AsyncStorage = AsyncStorageStatic\n\n    export var CameraRoll: CameraRollStatic\n    export type CameraRoll = CameraRollStatic\n\n    export var NetInfo: NetInfoStatic\n    export type NetInfo = NetInfoStatic\n\n    export var PanResponder: PanResponderStatic\n    export type PanResponder = PanResponderStatic\n\n    export var PushNotificationIOS: PushNotificationIOSStatic\n    export type PushNotificationIOS = PushNotificationIOSStatic\n\n    export var StatusBarIOS: StatusBarIOSStatic\n    export type StatusBarIOS = StatusBarIOSStatic\n\n    export var VibrationIOS: VibrationIOSStatic\n    export type VibrationIOS = VibrationIOSStatic\n\n\n    //\n    // /TODO: BGR: These are leftovers of the initial port that must be revisited\n    //\n\n    export var SegmentedControlIOS: React.ComponentClass<SegmentedControlIOSProperties>\n\n    export var PixelRatio: PixelRatioStatic\n    export var DeviceEventEmitter: DeviceEventEmitterStatic\n    export var DeviceEventSubscription: DeviceEventSubscriptionStatic\n    export type DeviceEventSubscription = DeviceEventSubscriptionStatic\n    export var InteractionManager: InteractionManagerStatic\n\n    //////////////////////////////////////////////////////////////////////////\n    //\n    // Additional ( and controversial)\n    //\n    //////////////////////////////////////////////////////////////////////////\n\n    export function __spread( target: any, ...sources: any[] ): any;\n\n\n    export interface GlobalStatic {\n\n        /**\n         * Accepts a function as its only argument and calls that function before the next repaint.\n         * It is an essential building block for animations that underlies all of the JavaScript-based animation APIs.\n         * In general, you shouldn't need to call this yourself - the animation API's will manage frame updates for you.\n         * @see https://facebook.github.io/react-native/docs/animations.html#requestanimationframe\n         */\n        requestAnimationFrame( fn: () => void ) : void;\n\n    }\n\n    //\n    // Add-Ons\n    //\n    namespace addons {\n\n        //FIXME: Documentation ?\n        export interface TestModuleStatic {\n\n            verifySnapshot: ( done: ( indicator?: any ) => void ) => void\n            markTestPassed: ( indicator: any ) => void\n            markTestCompleted: () => void\n        }\n\n        export var TestModule: TestModuleStatic\n        export type TestModule = TestModuleStatic\n    }\n\n\n}\n\ndeclare module \"react-native\" {\n\n    import ReactNative = __React\n    export = ReactNative\n}\n\ndeclare var global: __React.GlobalStatic\n\ndeclare function require( name: string ): any\n\n\n//TODO: BGR: this is a left-over from the initial port. Not sure it makes any sense\ndeclare module \"Dimensions\" {\n    import * as React from 'react-native';\n\n    interface Dimensions {\n        get( what: string ): React.ScaledSize;\n    }\n\n    var ExportDimensions: Dimensions;\n    export = ExportDimensions;\n}\n"
  },
  {
    "path": "README.md",
    "content": "# Hot\nthis is a hot project\n这是一个用MVP+Rxjava+Retrofit构建项目，是个微信头条的分享。\n\n##  Screenshot\n\n![image](https://github.com/zj-wukewei/Hot/blob/master/screenshot/1.png)![image](https://github.com/zj-wukewei/Hot/blob/master/screenshot/2.png)\n\n\n## Update\n>* 6月25日 加入了缓存功能。\n>* 7月11日 加入Datamanager来统一管理数据来源\n>* 7月20日 加入Dagger2\n>* 9月12日 完成了用react-native实现的体育新闻列表\n>* 9月13日 加入materialsearchview库完成搜索功能，关于界面的入口改变\n\n##  Welcome\n>* Star\n>* Fork\n>* PR\n>* Issue\n"
  },
  {
    "path": "app/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "app/build.gradle",
    "content": "apply plugin: 'com.android.application'\napply plugin: 'com.neenbedankt.android-apt'\napply plugin: 'me.tatarka.retrolambda'\nandroid {\n    compileSdkVersion rootProject.ext.android.compileSdkVersion\n    buildToolsVersion rootProject.ext.android.buildToolsVersion\n\n    defaultConfig {\n        applicationId rootProject.ext.android.applicationId\n        minSdkVersion rootProject.ext.android.minSdkVersion\n        targetSdkVersion rootProject.ext.android.targetSdkVersion\n        versionCode rootProject.ext.android.versionCode\n        versionName rootProject.ext.android.versionName\n        ndk {\n            abiFilters \"armeabi-v7a\", \"x86\"\n        }\n    }\n\n\n\n\n    compileOptions {\n        sourceCompatibility rootProject.ext.android.javaVersion\n        sourceCompatibility rootProject.ext.android.javaVersion\n    }\n\n\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(include: ['*.jar'], dir: 'libs')\n    testCompile 'junit:junit:4.12'\n    compile rootProject.ext.dependencies[\"appcompat-v7\"]\n    compile rootProject.ext.dependencies[\"cardview\"]\n    compile rootProject.ext.dependencies[\"design\"]\n    compile rootProject.ext.dependencies[\"recyclerview-v7\"]\n    compile rootProject.ext.dependencies[\"retrofit\"]\n    compile rootProject.ext.dependencies[\"logging-interceptor\"]\n    compile rootProject.ext.dependencies[\"rxandroid\"]\n    compile rootProject.ext.dependencies[\"converter-gson\"]\n    compile rootProject.ext.dependencies[\"adapter-rxjava\"]\n    compile rootProject.ext.dependencies[\"gson\"]\n    compile rootProject.ext.dependencies[\"react-native-preloader\"]\n    compile rootProject.ext.dependencies[\"butterknife\"]\n    compile rootProject.ext.dependencies[\"dagger\"]\n    compile rootProject.ext.dependencies[\"react-native\"]\n    compile rootProject.ext.dependencies[\"materialsearchview\"]\n    apt rootProject.ext.dependencies[\"dagger-compiler\"]\n    provided rootProject.ext.dependencies[\"glassfish\"]\n    compile project(':common_lib')\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/wukewei/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/com/wkw/hot/ApplicationTest.java",
    "content": "package com.wkw.hot;\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": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.wkw.hot\">\n\n    <uses-permission android:name=\"android.permission.INTERNET\"></uses-permission>\n    <uses-permission android:name=\"android.permission.WRITE_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.READ_EXTERNAL_STORAGE\" />\n    <uses-permission android:name=\"android.permission.ACCESS_NETWORK_STATE\" />\n    <uses-permission android:name=\"android.permission.READ_PHONE_STATE\" />\n    <uses-permission android:name=\"android.permission.READ_PROFILE\"/>\n    <application\n        android:allowBackup=\"true\"\n        android:icon=\"@mipmap/h\"\n        android:label=\"@string/app_name\"\n        android:name=\".ui.App\"\n        android:supportsRtl=\"true\"\n        android:theme=\"@style/AppTheme\">\n        <activity\n            android:name=\".ui.main.MainActivity\"\n            android:label=\"@string/app_name\"\n            android:theme=\"@style/AppTheme.NoActionBar\">\n            <intent-filter>\n                <action android:name=\"android.intent.action.MAIN\" />\n\n                <category android:name=\"android.intent.category.LAUNCHER\" />\n            </intent-filter>\n        </activity>\n        <activity android:name=\".ui.web.WebActivity\" android:screenOrientation=\"portrait\" ></activity>\n        <activity android:name=\".ui.AboutActivity\" android:screenOrientation=\"portrait\" ></activity>\n        <activity android:name=\".ui.search.SearchActivity\" android:screenOrientation=\"portrait\" ></activity>\n        <activity android:name=\".ui.react.MyReactActivity\" android:screenOrientation=\"portrait\" ></activity>\n        <activity android:name=\"com.facebook.react.devsupport.DevSettingsActivity\"/>\n    </application>\n\n</manifest>"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/adapter/FragmentAdapter.java",
    "content": "package com.wkw.hot.adapter;\n\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentManager;\nimport android.support.v4.app.FragmentPagerAdapter;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class FragmentAdapter extends FragmentPagerAdapter {\n\n    private List<Fragment> mFragments;\n    private List<String> mTitles;\n\n    public FragmentAdapter(FragmentManager fm) {\n        super(fm);\n        mFragments = new ArrayList<>();\n        mTitles = new ArrayList<>();\n    }\n\n    public void addFragment(Fragment fragment, String title) {\n        mFragments.add(fragment);\n        mTitles.add(title);\n    }\n\n    @Override\n    public Fragment getItem(int position) {\n        return mFragments.get(position);\n    }\n\n    @Override\n    public int getCount() {\n        return mFragments.size();\n    }\n\n    @Override\n    public CharSequence getPageTitle(int position) {\n        return mTitles.get(position);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/BaseActivity.java",
    "content": "package com.wkw.hot.base;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.Toolbar;\n\nimport com.wkw.common_lib.utils.AppManager;\nimport com.wkw.hot.navigator.Navigator;\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.module.ActivityModule;\nimport com.wkw.hot.ui.App;\n\nimport javax.inject.Inject;\n\nimport butterknife.ButterKnife;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic abstract class BaseActivity<T extends IPresenter> extends AppCompatActivity implements IView {\n\n    @Inject\n    protected T mPresenter;\n    protected Activity mContext;\n    @Inject\n    protected Navigator navigator;\n    @Override\n    protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        setContentView(getLayout());\n        ButterKnife.bind(this);\n        mContext = this;\n        setupActivityComponent(App.getAppComponent(),new ActivityModule(this));\n        if (mPresenter != null)\n        mPresenter.attachView(this);\n        initEventAndData();\n        AppManager.getAppManager().addActivity(this);\n    }\n\n    protected void setCommonBackToolBack(Toolbar toolbar, String title) {\n        toolbar.setTitle(title);\n        setSupportActionBar(toolbar);\n        getSupportActionBar().setDisplayHomeAsUpEnabled(true);\n        getSupportActionBar().setDisplayShowHomeEnabled(true);\n        toolbar.setNavigationOnClickListener(v -> onBackPressed());\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        AppManager.getAppManager().removeActivity(this);\n        ButterKnife.unbind(this);\n        if (mPresenter != null) mPresenter.detachView();\n    }\n\n    /**\n     * 依赖注入的入口\n     * @param appComponent appComponent\n     */\n    protected abstract void setupActivityComponent(AppComponent appComponent, ActivityModule activityModule);\n\n    protected abstract int getLayout();\n    protected abstract void initEventAndData();\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/BaseFragment.java",
    "content": "package com.wkw.hot.base;\n\nimport android.app.Activity;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.util.Log;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\n\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.module.ActivityModule;\nimport com.wkw.hot.reject.module.FragmentModule;\nimport com.wkw.hot.ui.App;\n\nimport javax.inject.Inject;\n\nimport butterknife.ButterKnife;\n\n/**\n * Created by wukewei on 16/5/30.\n */\npublic abstract class BaseFragment<T extends IPresenter> extends Fragment implements IView{\n    @Inject\n    protected T mPresenter;\n    protected View mView;\n    protected Activity mContext;\n\n    @Override\n    public void onAttach(Activity activity) {\n        if (activity instanceof BaseActivity) {\n            mContext = activity;\n        }\n        super.onAttach(activity);\n    }\n\n    @Nullable\n    @Override\n    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {\n        mView = inflater.inflate(getLayoutId(), null);\n        setupActivityComponent(App.getAppComponent(),new FragmentModule(this));\n        return mView;\n    }\n\n    @Override\n    public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {\n        super.onViewCreated(view, savedInstanceState);\n        mPresenter.attachView(this);\n        ButterKnife.bind(this, view);\n        initEventAndData();\n    }\n\n    @Override\n    public void onActivityCreated(@Nullable Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n\n    }\n\n    @Override\n    public void onDestroyView() {\n        super.onDestroyView();\n        ButterKnife.unbind(this);\n    }\n\n    @Override\n    public void onDestroy() {\n        super.onDestroy();\n        if (mPresenter != null) mPresenter.detachView();\n    }\n\n\n    /**\n     * 依赖注入的入口\n     * @param appComponent appComponent\n     */\n    protected abstract void setupActivityComponent(AppComponent appComponent, FragmentModule fragmentModule);\n\n    protected abstract int getLayoutId();\n    protected abstract void initEventAndData();\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/BaseLazyFragment.java",
    "content": "package com.wkw.hot.base;\n\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\n\nimport java.lang.reflect.Field;\n\n/**\n * Created by wukewei on 16/7/26.\n */\npublic abstract class BaseLazyFragment<T extends IPresenter> extends BaseFragment<T>{\n\n    private boolean isFirstResume = true;\n    private boolean isFirstVisible = true;\n    private boolean isFirstInvisible = true;\n    private boolean isPrepared;\n\n\n    @Override\n    public void onDetach() {\n        super.onDetach();\n        // for bug ---> java.lang.IllegalStateException: Activity has been destroyed\n        try {\n            Field childFragmentManager = Fragment.class.getDeclaredField(\"mChildFragmentManager\");\n            childFragmentManager.setAccessible(true);\n            childFragmentManager.set(this, null);\n\n        } catch (NoSuchFieldException e) {\n            throw new RuntimeException(e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        initPrepare();\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n        if (isFirstResume) {\n            isFirstResume = false;\n            return;\n        }\n        if (getUserVisibleHint()) {\n            onUserVisible();\n        }\n    }\n\n    @Override\n    public void onPause() {\n        super.onPause();\n        if (getUserVisibleHint()) {\n            onUserInvisible();\n        }\n    }\n\n    @Override\n    public void setUserVisibleHint(boolean isVisibleToUser) {\n        super.setUserVisibleHint(isVisibleToUser);\n        if (isVisibleToUser) {\n            if (isFirstVisible) {\n                isFirstVisible = false;\n                initPrepare();\n            } else {\n                onUserVisible();\n            }\n        } else {\n            if (isFirstInvisible) {\n                isFirstInvisible = false;\n                onFirstUserInvisible();\n            } else {\n                onUserInvisible();\n            }\n        }\n    }\n\n    private synchronized void initPrepare() {\n        if (isPrepared) {\n            onFirstUserVisible();\n        } else {\n            isPrepared = true;\n        }\n    }\n\n    /**\n     * when fragment is visible for the first time, here we can do some initialized work or refresh data only once\n     */\n    protected abstract void onFirstUserVisible();\n\n    /**\n     * this method like the fragment's lifecycle method onResume()\n     */\n    protected abstract void onUserVisible();\n\n    /**\n     * when fragment is invisible for the first time\n     */\n    private void onFirstUserInvisible() {\n        // here we do not recommend do something\n    }\n\n    /**\n     * this method like the fragment's lifecycle method onPause()\n     */\n    protected abstract void onUserInvisible();\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/BaseLoadMoreAdapter.java",
    "content": "package com.wkw.hot.base;\n\nimport android.support.v7.widget.RecyclerView;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\n\nimport com.wkw.hot.R;\nimport com.wkw.hot.common.Constants;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/6/1.\n */\npublic abstract class BaseLoadMoreAdapter<T, VH extends RecyclerView.ViewHolder> extends RecyclerView.Adapter {\n\n    public static final int TYPE_FOOTER = Integer.MAX_VALUE;\n    public static final int ITEM_TYPE = 0;\n    private final List<T> mList = new ArrayList<>();\n    private boolean hasMore = true, isLoading = true;\n\n\n\n    public static class FooterViewHolder extends RecyclerView.ViewHolder {\n\n        public final ProgressBar progressBar;\n        public final TextView textView;\n        public FooterViewHolder(View itemView) {\n            super(itemView);\n            progressBar = (ProgressBar) itemView.findViewById(R.id.progress_view);\n            textView = (TextView) itemView.findViewById(R.id.tv_content);\n        }\n    }\n\n    public void setLoading(boolean loading) {\n        isLoading = loading;\n    }\n\n    @Override\n    public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {\n        if (holder instanceof FooterViewHolder) {\n            if (hasMore) {\n                ((FooterViewHolder)holder).progressBar.setVisibility(View.VISIBLE);\n                ((FooterViewHolder)holder).textView.setText(\"正在加载...\");\n            } else {\n                ((FooterViewHolder)holder).progressBar.setVisibility(View.GONE);\n                ((FooterViewHolder)holder).textView.setText(\"已全部加载\");\n            }\n        } else {\n            onBindItemViewHolder((VH)holder, mList.get(position), position);\n        }\n    }\n\n    @Override\n    public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n        if (viewType == TYPE_FOOTER) {\n            View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_loading_footer_view, parent, false);\n            return new FooterViewHolder(view);\n        } else {\n            return onCreateItemViewHolder(parent, viewType);\n        }\n    }\n\n    public abstract void onBindItemViewHolder(VH holder, T data, int position);\n    public abstract VH onCreateItemViewHolder(ViewGroup parent, int viewType);\n\n    @Override\n    public int getItemViewType(int position) {\n        if (position == mList.size()) {\n            return TYPE_FOOTER;\n        } else {\n            return ITEM_TYPE;\n        }\n    }\n\n    @Override\n    public int getItemCount() {\n        return mList.size() + 1;\n    }\n\n    public void addLoadMoreData(List<T> data) {\n        if (data == null) return;\n        this.mList.addAll(data);\n        this.hasMore = data.size() == Constants.PAGE_SIZE;\n        this.isLoading = false;\n        notifyDataSetChanged();\n    }\n\n    public void addRefreshData(List<T> data) {\n        if (data == null) return;\n        this.mList.clear();\n        this.mList.addAll(data);\n        this.hasMore = data.size() == Constants.PAGE_SIZE;\n        this.isLoading = false;\n        notifyDataSetChanged();\n    }\n    public boolean canLoadMore() {\n        return hasMore && !isLoading;\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/BaseOnScrollListener.java",
    "content": "package com.wkw.hot.base;\n\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\n\n/**\n * Created by wukewei on 16/6/1.\n */\npublic abstract class BaseOnScrollListener extends RecyclerView.OnScrollListener {\n    protected int lastVisibleItem;\n\n    @Override\n    public void onScrolled(RecyclerView recyclerView, int dx, int dy) {\n        super.onScrolled(recyclerView, dx, dy);\n        lastVisibleItem = ((LinearLayoutManager)recyclerView.getLayoutManager()).findLastVisibleItemPosition();\n\n    }\n\n    @Override\n    public void onScrollStateChanged(RecyclerView recyclerView, int newState) {\n        super.onScrollStateChanged(recyclerView, newState);\n        if (newState == RecyclerView.SCROLL_STATE_IDLE\n                && lastVisibleItem + 1 == recyclerView.getAdapter().getItemCount()) {\n               onLoadMore();\n        }\n    }\n\n    public abstract void onLoadMore();\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/BasePresenter.java",
    "content": "package com.wkw.hot.base;\n\nimport android.app.Activity;\n\nimport com.wkw.common_lib.utils.ToashUtils;\nimport com.wkw.hot.data.DataManager;\nimport com.wkw.common_lib.rx.error.ErrorHanding;\n\nimport rx.Subscription;\nimport rx.subscriptions.CompositeSubscription;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic abstract class BasePresenter<T extends IView> implements IPresenter<T> {\n\n    protected T mView;\n    protected CompositeSubscription mCompositeSubscription;\n\n    @Override\n    public void attachView(T view) {\n        this.mView = view;\n    }\n\n\n\n    protected void unSubscribe() {\n        if (mCompositeSubscription != null) {\n            mCompositeSubscription.unsubscribe();\n        }\n    }\n\n    protected void addSubscribe(Subscription subscription) {\n        if (mCompositeSubscription == null) {\n            mCompositeSubscription = new CompositeSubscription();\n        }\n        mCompositeSubscription.add(subscription);\n    }\n\n    @Override\n    public void detachView() {\n        this.mView = null;\n        unSubscribe();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/ILoadingView.java",
    "content": "package com.wkw.hot.base;\n\nimport android.content.Context;\n\n/**\n * Created by wukewei on 16/6/1.\n */\npublic interface ILoadingView extends IView {\n    void showLoading();\n    void showContent();\n    void showNotData();\n    void showError(String msg);\n    Context context();\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/IPresenter.java",
    "content": "package com.wkw.hot.base;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic interface IPresenter<T extends IView> {\n    void attachView(T view);\n    void detachView();\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/IView.java",
    "content": "package com.wkw.hot.base;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic interface IView {\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/page/BaseLazyPageFragment.java",
    "content": "package com.wkw.hot.base.page;\n\nimport android.os.Bundle;\nimport android.support.v4.app.Fragment;\nimport com.wkw.hot.base.BaseFragment;\nimport com.wkw.hot.base.IPresenter;\nimport java.lang.reflect.Field;\n\n/**\n * Created by wukewei on 16/7/26.\n */\npublic abstract class BaseLazyPageFragment<T extends IPresenter> extends BasePageFragment<T>{\n\n    private boolean isFirstResume = true;\n    private boolean isFirstVisible = true;\n    private boolean isFirstInvisible = true;\n    private boolean isPrepared;\n\n\n    @Override\n    public void onDetach() {\n        super.onDetach();\n        // for bug ---> java.lang.IllegalStateException: Activity has been destroyed\n        try {\n            Field childFragmentManager = Fragment.class.getDeclaredField(\"mChildFragmentManager\");\n            childFragmentManager.setAccessible(true);\n            childFragmentManager.set(this, null);\n\n        } catch (NoSuchFieldException e) {\n            throw new RuntimeException(e);\n        } catch (IllegalAccessException e) {\n            throw new RuntimeException(e);\n        }\n    }\n\n    @Override\n    public void onActivityCreated(Bundle savedInstanceState) {\n        super.onActivityCreated(savedInstanceState);\n        initPrepare();\n    }\n\n    @Override\n    public void onResume() {\n        super.onResume();\n        if (isFirstResume) {\n            isFirstResume = false;\n            return;\n        }\n        if (getUserVisibleHint()) {\n            onUserVisible();\n        }\n    }\n\n    @Override\n    public void onPause() {\n        super.onPause();\n        if (getUserVisibleHint()) {\n            onUserInvisible();\n        }\n    }\n\n    @Override\n    public void setUserVisibleHint(boolean isVisibleToUser) {\n        super.setUserVisibleHint(isVisibleToUser);\n        if (isVisibleToUser) {\n            if (isFirstVisible) {\n                isFirstVisible = false;\n                initPrepare();\n            } else {\n                onUserVisible();\n            }\n        } else {\n            if (isFirstInvisible) {\n                isFirstInvisible = false;\n                onFirstUserInvisible();\n            } else {\n                onUserInvisible();\n            }\n        }\n    }\n\n    private synchronized void initPrepare() {\n        if (isPrepared) {\n            onFirstUserVisible();\n        } else {\n            isPrepared = true;\n        }\n    }\n\n    /**\n     * when fragment is visible for the first time, here we can do some initialized work or refresh data only once\n     */\n    protected abstract void onFirstUserVisible();\n\n    /**\n     * this method like the fragment's lifecycle method onResume()\n     */\n    protected abstract void onUserVisible();\n\n    /**\n     * when fragment is invisible for the first time\n     */\n    private void onFirstUserInvisible() {\n        // here we do not recommend do something\n    }\n\n    /**\n     * this method like the fragment's lifecycle method onPause()\n     */\n    protected abstract void onUserInvisible();\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/page/BaseListAdapter.java",
    "content": "package com.wkw.hot.base.page;\n\nimport android.support.v7.widget.RecyclerView;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/12/6.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic abstract class BaseListAdapter<MODEL> extends RecyclerView.Adapter {\n\n    protected List<MODEL> mData = new ArrayList<MODEL>();\n\n\n    @Override public int getItemCount() {\n        return mData.size();\n    }\n\n    public void addLoadMoreData(List<MODEL> data) {\n        if (data == null) return;\n        this.mData.addAll(data);\n        notifyDataSetChanged();\n    }\n\n    public void addRefreshData(List<MODEL> data) {\n        if (data == null) return;\n        this.mData.clear();\n        this.mData.addAll(data);\n        notifyDataSetChanged();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/page/BasePageFragment.java",
    "content": "package com.wkw.hot.base.page;\n\nimport android.content.Context;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.support.v7.widget.RecyclerView;\nimport butterknife.Bind;\nimport com.wkw.common_lib.widget.ProgressLayout;\nimport com.wkw.common_lib.widget.loadmore.OnLoadMoreListener;\nimport com.wkw.common_lib.widget.loadmore.RecyclerViewWithFooter;\nimport com.wkw.hot.R;\nimport com.wkw.hot.base.BaseFragment;\nimport com.wkw.hot.base.ILoadingView;\nimport com.wkw.hot.base.IPresenter;\nimport com.wkw.hot.common.Constants;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/12/6.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic abstract class BasePageFragment<T extends IPresenter> extends BaseFragment<T> implements\n    IDataVIew {\n\n    @Bind(R.id.recycler_view) RecyclerViewWithFooter mRecyclerViewWithFooter;\n    @Bind(R.id.swipe_refresh_layout) SwipeRefreshLayout mSwipeRefreshLayout;\n    @Bind(R.id.progress_layout) ProgressLayout mProgressLayout;\n\n\n    public int mCurrentPage = 1;\n\n    public boolean mIsFetching = false;\n\n    public boolean isInit = true;\n\n\n    @Override protected void initEventAndData() {\n        mSwipeRefreshLayout.setOnRefreshListener(mOnRefreshListener);\n        mRecyclerViewWithFooter.setOnLoadMoreListener(mLoadMoreListener);\n        mRecyclerViewWithFooter.setAdapter(getAdapter());\n        mRecyclerViewWithFooter.setLayoutManager(getLayoutManager());\n    }\n\n\n    @Override protected int getLayoutId() {\n        return R.layout.fragment_list;\n    }\n\n\n    public OnLoadMoreListener mLoadMoreListener = () -> {\n        mCurrentPage++;\n        fetchData(mCurrentPage);\n    };\n\n    public SwipeRefreshLayout.OnRefreshListener mOnRefreshListener = () -> {\n        if (!mIsFetching && mSwipeRefreshLayout != null &&\n            mSwipeRefreshLayout.isRefreshing()) {\n            mCurrentPage = 1;\n            mRecyclerViewWithFooter.setPullToLoad();\n        }\n    };\n\n\n    @Override public void showContent() {\n        if (mProgressLayout != null) {\n            mProgressLayout.showContent();\n        }\n    }\n\n\n    @Override public void showLoading() {\n        mIsFetching = true;\n        if (mCurrentPage == 1 && isInit) {\n            if (mProgressLayout != null) {\n                mProgressLayout.showLoading();\n            }\n        }\n        isInit = false;\n    }\n\n\n    @Override public void showError(String msg) {\n        mIsFetching = false;\n        setOnRefresh();\n        if (mCurrentPage == 1 && mProgressLayout != null) {\n            mProgressLayout.showError(msg, v -> fetchData(mCurrentPage));\n        }\n    }\n\n\n    public void setOnRefresh() {\n        if (mSwipeRefreshLayout != null) {\n            mSwipeRefreshLayout.postDelayed(() -> mSwipeRefreshLayout.setRefreshing(false),\n                800);\n        }\n    }\n\n\n    @Override public void showNotData() {\n        if (mProgressLayout != null) {\n            mProgressLayout.showNotData(v -> fetchData(mCurrentPage));\n        }\n        if (mCurrentPage == 1) {\n            setOnRefresh();\n        }\n        mIsFetching = false;\n    }\n\n\n    public void setData(List data) {\n        if (data == null) {\n            showNotData();\n            return;\n        }\n        if (mCurrentPage == 1) {\n            getAdapter().addRefreshData(data);\n        } else {\n            getAdapter().addLoadMoreData(data);\n        }\n\n        if (data.size() < Constants.PAGE_SIZE) {\n            mRecyclerViewWithFooter.setEnd();\n        } else {\n            mRecyclerViewWithFooter.setPullToLoad();\n        }\n\n        RecyclerView.Adapter adapter = mRecyclerViewWithFooter.getAdapter();\n        if (mCurrentPage == 1 &&\n            mRecyclerViewWithFooter != null &&\n            adapter != null &&\n            (adapter.getItemCount() == 0\n                || (adapter.getItemCount() == 1 &&\n                (adapter.getItemViewType(0) == RecyclerViewWithFooter.\n                    LoadMoreAdapter.LOAD_MORE_VIEW_TYPE ||\n                    adapter.getItemViewType(0) == RecyclerViewWithFooter.\n                        LoadMoreAdapter.EMPTY_VIEW_TYPE)))) {\n            isInit = true;\n            showNotData();\n            return;\n        }\n\n\n\n        if (mProgressLayout != null) {\n            mProgressLayout.showContent();\n        }\n        if (mCurrentPage == 1) {\n            setOnRefresh();\n        }\n        mCurrentPage++;\n        mIsFetching = false;\n    }\n\n\n    @Override public Context context() {\n        return getActivity();\n    }\n\n\n    protected abstract void fetchData(int currentPageIndex);\n\n\n    protected abstract BaseListAdapter getAdapter();\n\n    protected abstract RecyclerView.LayoutManager getLayoutManager();\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/base/page/IDataVIew.java",
    "content": "package com.wkw.hot.base.page;\n\nimport android.content.Context;\nimport com.wkw.hot.base.IView;\n\n/**\n * Created by wukewei on 16/12/6.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic interface IDataVIew extends IView{\n    void showLoading();\n    void showContent();\n    void showNotData();\n    void showError(String msg);\n    Context context();\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/cache/CacheLoader.java",
    "content": "package com.wkw.hot.cache;\n\nimport android.app.Application;\nimport android.content.Context;\nimport android.util.Log;\n\nimport rx.Observable;\nimport rx.functions.Action1;\nimport rx.functions.Func1;\n\n/**\n * Created by wukewei on 16/6/19.\n */\npublic class CacheLoader {\n    private static Application application;\n\n    public static Application getApplication() {\n        return application;\n    }\n\n    private ICache mMemoryCache, mDiskCache;\n\n    private CacheLoader() {\n\n        mMemoryCache = new MemoryCache();\n        mDiskCache = new DiskCache();\n    }\n    private static CacheLoader loader;\n\n    public static CacheLoader getInstance(Context context) {\n        application = (Application) context.getApplicationContext();\n        if (loader == null) {\n            synchronized (CacheLoader.class) {\n                if (loader == null) {\n                    loader = new CacheLoader();\n                }\n            }\n        }\n        return loader;\n    }\n\n\n    public <T> Observable<T> asDataObservable(String key, Class<T> cls, NetworkCache<T> networkCache) {\n\n        Observable observable = Observable.concat(\n                memory(key, cls),\n                disk(key, cls),\n                network(key, cls, networkCache))\n                .first(new Func1<T, Boolean>() {\n                    @Override\n                    public Boolean call(T t) {\n                        return t != null;\n                    }\n                });\n        return observable;\n    }\n\n    private <T> Observable<T> memory(String key, Class<T> cls) {\n\n        return mMemoryCache.get(key, cls).doOnNext(new Action1<T>() {\n            @Override\n            public void call(T t) {\n                if (null != t) {\n                    Log.d(\"我是来自内存\",\"我是来自内存\");\n                }\n            }\n        });\n    }\n\n    private <T> Observable<T> disk(final String key, Class<T> cls) {\n\n        return mDiskCache.get(key, cls)\n                .doOnNext(new Action1<T>() {\n                    @Override\n                    public void call(T t) {\n                        if (null != t) {\n                            Log.d(\"我是来自磁盘\",\"我是来自磁盘\");\n                            mMemoryCache.put(key, t);\n                        }\n                    }\n                });\n    }\n\n    public  <T> void upNewData(final String key, T t) {\n        Observable.just(t)\n                .doOnNext(new Action1<T>() {\n                    @Override\n                    public void call(T t) {\n                        if (null != t) {\n                            Log.d(\"更新数据\",\"更新数据\");\n                            mDiskCache.put(key, t);\n                            mMemoryCache.put(key, t);\n                        }\n                    }\n                }).subscribe();\n    }\n\n    private <T> Observable<T> network(final String key, Class<T> cls\n            , NetworkCache<T> networkCache) {\n\n        return networkCache.get(key, cls)\n                .doOnNext(new Action1<T>() {\n                    @Override\n                    public void call(T t) {\n                        if (null != t) {\n                            Log.d(\"我是来自网络\",\"我是来自网络\");\n                            mDiskCache.put(key, t);\n                            mMemoryCache.put(key, t);\n                        }\n                    }\n                });\n    }\n\n\n    public void clearMemory(String key) {\n        ((MemoryCache)mMemoryCache).clearMemory(key);\n    }\n\n\n\n    public void clearMemoryDisk(String key) {\n        ((MemoryCache)mMemoryCache).clearMemory(key);\n        ((DiskCache)mDiskCache).clearDisk(key);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/cache/DiskCache.java",
    "content": "package com.wkw.hot.cache;\n\nimport android.util.Log;\n\nimport com.wkw.hot.ui.App;\n\nimport java.io.Closeable;\nimport java.io.File;\nimport java.io.FileInputStream;\nimport java.io.FileOutputStream;\nimport java.io.IOException;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectOutputStream;\nimport java.io.StreamCorruptedException;\n\nimport rx.Observable;\nimport rx.Subscriber;\nimport rx.android.schedulers.AndroidSchedulers;\nimport rx.schedulers.Schedulers;\n\n/**\n * Created by wukewei on 16/6/19.\n */\npublic class DiskCache implements ICache{\n\n    private static final String NAME = \".db\";\n    public static long OTHER_CACHE_TIME = 10 * 60 * 1000;\n    public static long WIFI_CACHE_TIME = 30 * 60 * 1000;\n    File fileDir;\n    public DiskCache() {\n        fileDir = CacheLoader.getApplication().getCacheDir();\n    }\n\n    @Override\n    public <T> Observable<T> get(final String key, final Class<T> cls) {\n        return Observable.create(new Observable.OnSubscribe<T>() {\n            @Override\n            public void call(Subscriber<? super T> subscriber) {\n\n                T t = (T) getDiskData(key + NAME);\n\n                if (subscriber.isUnsubscribed()) {\n                    return;\n                }\n\n                if (t == null) {\n                    subscriber.onNext(null);\n                } else {\n                    subscriber.onNext(t);\n                }\n\n                subscriber.onCompleted();\n            }\n        })\n                .subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread());\n\n    }\n\n    @Override\n    public <T> void put(final String key, final T t) {\n        Observable.create(new Observable.OnSubscribe<T>() {\n            @Override\n            public void call(Subscriber<? super T> subscriber) {\n\n                boolean isSuccess = isSave(key + NAME, t);\n\n                if (!subscriber.isUnsubscribed() && isSuccess) {\n\n                    subscriber.onNext(t);\n                    subscriber.onCompleted();\n                }\n            }\n        })\n                .subscribeOn(Schedulers.io())\n                .observeOn(AndroidSchedulers.mainThread())\n                .subscribe();\n    }\n\n    /**\n     * 保存数据\n     */\n    private <T> boolean isSave(String fileName, T t) {\n        File file = new File(fileDir, fileName);\n\n        ObjectOutputStream objectOut = null;\n        boolean isSuccess = false;\n        try {\n            FileOutputStream out = new FileOutputStream(file);\n                    objectOut = new ObjectOutputStream(out);\n            objectOut.writeObject(t);\n            objectOut.flush();\n            isSuccess=true;\n        } catch (IOException e) {\n            Log.e(\"写入缓存错误\",e.getMessage());\n        } catch (Exception e) {\n            Log.e(\"写入缓存错误\",e.getMessage());\n        } finally {\n            closeSilently(objectOut);\n        }\n        return isSuccess;\n    }\n\n    /**\n     * 获取保存的数据\n     */\n    private Object getDiskData(String fileName) {\n        File file = new File(fileDir, fileName);\n        if (!file.exists()) {\n            return null;\n        }\n\n        if (isCacheDataFailure(file)) {\n            return null;\n        }\n\n        Object o = null;\n        ObjectInputStream read = null;\n        try {\n            read = new ObjectInputStream(new FileInputStream(file));\n            o = read.readObject();\n        } catch (StreamCorruptedException e) {\n            Log.e(\"读取错误\", e.getMessage());\n        } catch (IOException e) {\n            Log.e(\"读取错误\", e.getMessage());\n        } catch (ClassNotFoundException e) {\n            Log.e(\"错误\", e.getMessage());\n        } finally {\n            closeSilently(read);\n        }\n        return o;\n    }\n\n\n\n    private void closeSilently(Closeable closeable) {\n        if (closeable != null) {\n            try {\n                closeable.close();\n            } catch (Exception ignored) {\n            }\n        }\n    }\n\n\n\n    /**\n     * 判断缓存是否已经失效\n     */\n    private boolean isCacheDataFailure(File dataFile) {\n        if (!dataFile.exists()) {\n            return true;\n        }\n        long existTime = System.currentTimeMillis() - dataFile.lastModified();\n        boolean failure = false;\n\n        if (!App.ExtImpl.g().isAvailable()) {\n            return failure;\n        }\n        if (App.ExtImpl.g().isWifi()) {\n            failure = existTime > WIFI_CACHE_TIME ? true : false;\n        } else {\n            failure = existTime > OTHER_CACHE_TIME ? true : false;\n        }\n        return failure;\n    }\n\n    public void clearDisk(String key) {\n        File file = new File(fileDir, key + NAME);\n        if (file.exists()) file.delete();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/cache/ICache.java",
    "content": "package com.wkw.hot.cache;\n\nimport rx.Observable;\n\n/**\n * Created by wukewei on 16/6/19.\n */\npublic interface ICache {\n    <T> Observable<T> get(String key, Class<T> cls);\n\n    <T> void put(String key, T t);\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/cache/MemoryCache.java",
    "content": "package com.wkw.hot.cache;\n\nimport android.text.TextUtils;\nimport android.util.LruCache;\n\nimport com.google.gson.Gson;\n\nimport java.io.UnsupportedEncodingException;\n\nimport rx.Observable;\nimport rx.Subscriber;\n\n/**\n * Created by wukewei on 16/6/19.\n */\npublic class MemoryCache implements ICache{\n\n    private LruCache<String, String> mCache;\n\n    public MemoryCache() {\n        final int maxMemory = (int) Runtime.getRuntime().maxMemory();\n        final int cacheSize = maxMemory / 8;\n        mCache = new LruCache<String, String>(cacheSize) {\n            @Override\n            protected int sizeOf(String key, String value) {\n                try {\n                    return value.getBytes(\"UTF-8\").length;\n                } catch (UnsupportedEncodingException e) {\n                    e.printStackTrace();\n                    return value.getBytes().length;\n                }\n            }\n        };\n    }\n\n    @Override\n    public <T> Observable<T> get(final String key, final Class<T> cls) {\n        return Observable.create(new Observable.OnSubscribe<T>() {\n            @Override\n            public void call(Subscriber<? super T> subscriber) {\n\n                String result = mCache.get(key);\n\n                if (subscriber.isUnsubscribed()) {\n                    return;\n                }\n\n                if (TextUtils.isEmpty(result)) {\n                    subscriber.onNext(null);\n                } else {\n                    T t = new Gson().fromJson(result, cls);\n                    subscriber.onNext(t);\n                }\n\n                subscriber.onCompleted();\n            }\n        });\n    }\n\n    @Override\n    public <T> void put(String key, T t) {\n        if (null != t) {\n            mCache.put(key, new Gson().toJson(t));\n        }\n    }\n\n    public void clearMemory(String key) {\n        mCache.remove(key);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/cache/NetworkCache.java",
    "content": "package com.wkw.hot.cache;\n\nimport rx.Observable;\n\n/**\n * Created by wukewei on 16/6/19.\n */\npublic abstract class NetworkCache<T> {\n    public abstract Observable<T> get(String key, final Class<T> cls);\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/common/Constants.java",
    "content": "package com.wkw.hot.common;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class Constants {\n    public static final String Base_Url = \"http://route.showapi.com/\";\n    public static final String Api_Key = \"c12cf1979a384b119ebe7583f5dea18c\";\n    public static final String Showapi_appid = \"37613\";\n    public static final String NEW_LIST = \"new_list\";\n    public static final int HTTP_CONNECT_TIMEOUT = 16000;\n    public static final int PAGE_SIZE = 20;\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/data/DataManager.java",
    "content": "package com.wkw.hot.data;\n\nimport com.wkw.hot.cache.CacheLoader;\nimport com.wkw.hot.cache.NetworkCache;\nimport com.wkw.hot.common.Constants;\nimport com.wkw.hot.data.api.HotApi;\nimport com.wkw.hot.entity.ListPopularEntity;\nimport com.wkw.hot.entity.PagePopularEntity;\nimport com.wkw.hot.entity.PopularEntity;\nimport com.wkw.common_lib.rx.RxResultHelper;\nimport com.wkw.common_lib.rx.SchedulersCompat;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport javax.inject.Inject;\n\nimport rx.Observable;\nimport rx.Subscriber;\nimport rx.functions.Func1;\n\n/**\n * Created by wukewei on 16/7/12.\n * 这个类是管理app的数据来源无论从网络获取.内存.还是磁盘\n */\npublic class DataManager {\n\n    private  HotApi mHotApi;\n    private  CacheLoader cacheLoader;\n\n\n    @Inject\n    public DataManager(HotApi hotApi, CacheLoader cacheLoader) {\n        this.mHotApi = hotApi;\n        this.cacheLoader = cacheLoader;\n    }\n\n    /***\n     * 获取分类的类型\n     * @param\n     * @param\n     * @return\n     */\n    public List<String> getTabs() {\n        List<String> tabs = new ArrayList<>();\n        tabs.add(\"科技\");\n        tabs.add(\"美女\");\n        tabs.add(\"生活\");\n        tabs.add(\"娱乐\");\n        tabs.add(\"搞笑\");\n        tabs.add(\"宅男\");\n        return tabs;\n    }\n\n    /***\n     * 获取列表\n     * @param pn 页码\n     * @param type 类别名称\n     * @return\n     */\n    public Observable<List<PopularEntity>> getPopular(int pn, String type) {\n        return mHotApi.getPopular(pn, type, Constants.Showapi_appid, Constants.Api_Key)\n                .compose(SchedulersCompat.applyIoSchedulers())\n                .compose(RxResultHelper.handleResult())\n                .doOnNext(populars -> {\n                    if (pn == 1) {\n                        ListPopularEntity popular = new ListPopularEntity(populars.getPagebean().getContentlist());\n                        cacheLoader.upNewData(type, popular);\n                    }\n                })\n            .flatMap(new Func1<PagePopularEntity, Observable<List<PopularEntity>>>() {\n                @Override public Observable<List<PopularEntity>> call(PagePopularEntity pagePopularEntity) {\n                    return Observable.just(pagePopularEntity.getPagebean().getContentlist());\n                }\n            });\n    }\n\n    /***\n     * 获取缓存信息 默认只缓存第一页\n     * @param type 类别名称\n     * @param\n     * @return\n     */\n    public Observable<List<PopularEntity>> getCachePopular(String type) {\n        NetworkCache<ListPopularEntity> networkCache = new NetworkCache<ListPopularEntity>() {\n            @Override\n            public Observable<ListPopularEntity> get(String key, Class<ListPopularEntity> cls) {\n                return getPopular(1, type)\n                        .flatMap(populars -> {\n                            ListPopularEntity popular = new ListPopularEntity(populars);\n                            return Observable.create(new Observable.OnSubscribe<ListPopularEntity>() {\n                                @Override\n                                public void call(Subscriber<? super ListPopularEntity> subscriber) {\n                                    if (subscriber.isUnsubscribed())\n                                        return;\n                                    subscriber.onNext(popular);\n                                    subscriber.onCompleted();\n                                }\n                            });\n                        });\n            }\n        };\n\n        return cacheLoader.asDataObservable(Constants.NEW_LIST + type, ListPopularEntity.class, networkCache)\n                .map(listPopular -> listPopular.data);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/data/api/HotApi.java",
    "content": "package com.wkw.hot.data.api;\n\nimport com.wkw.common_lib.rx.ApiResponse;\nimport com.wkw.hot.entity.PagePopularEntity;\nimport retrofit2.http.GET;\nimport retrofit2.http.Query;\nimport rx.Observable;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic interface HotApi {\n\n    @GET(\"582-2\")\n    Observable<ApiResponse<PagePopularEntity>> getPopular(@Query(\"page\") int page, @Query(\"key\") String word,\n                                                          @Query(\"showapi_appid\") String showapi_appid,\n                                                          @Query(\"showapi_sign\") String showapi_sign);\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/entity/ListPopularEntity.java",
    "content": "package com.wkw.hot.entity;\n\nimport java.io.Serializable;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/6/25.\n */\npublic class ListPopularEntity implements Serializable {\n    public List<PopularEntity> data;\n\n    public ListPopularEntity(List<PopularEntity> data) {\n        this.data = data;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/entity/PagePopularEntity.java",
    "content": "package com.wkw.hot.entity;\n\nimport com.google.gson.annotations.SerializedName;\nimport java.util.List;\n\n/**\n * Created by wukewei on 17/5/8.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class PagePopularEntity {\n    @SerializedName(\"ret_code\")\n    private int retCode;\n    @SerializedName(\"pagebean\")\n    private  Pagebean pagebean;\n\n\n    public int getRetCode() {\n        return retCode;\n    }\n\n\n    public void setRetCode(int retCode) {\n        this.retCode = retCode;\n    }\n\n\n    public Pagebean getPagebean() {\n        return pagebean;\n    }\n\n\n    public void setPagebean(Pagebean pagebean) {\n        this.pagebean = pagebean;\n    }\n\n\n    public static class Pagebean {\n        @SerializedName(\"allPages\")\n        private int allPages;\n        @SerializedName(\"contentlist\")\n        private List<PopularEntity> contentlist;\n        @SerializedName(\"currentPage\")\n        private int currentPage;\n        @SerializedName(\"allNum\")\n        private int allNum;\n        @SerializedName(\"maxResult\")\n        private int maxResult;\n\n\n        public int getMaxResult() {\n            return maxResult;\n        }\n\n\n        public void setMaxResult(int maxResult) {\n            this.maxResult = maxResult;\n        }\n\n\n        public int getAllPages() {\n            return allPages;\n        }\n\n\n        public void setAllPages(int allPages) {\n            this.allPages = allPages;\n        }\n\n\n        public List<PopularEntity> getContentlist() {\n            return contentlist;\n        }\n\n\n        public void setContentlist(List<PopularEntity> contentlist) {\n            this.contentlist = contentlist;\n        }\n\n\n        public int getCurrentPage() {\n            return currentPage;\n        }\n\n\n        public void setCurrentPage(int currentPage) {\n            this.currentPage = currentPage;\n        }\n\n\n        public int getAllNum() {\n            return allNum;\n        }\n\n\n        public void setAllNum(int allNum) {\n            this.allNum = allNum;\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/entity/PopularEntity.java",
    "content": "package com.wkw.hot.entity;\n\nimport com.google.gson.annotations.SerializedName;\nimport java.io.Serializable;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class PopularEntity implements Serializable{\n\n\n    @Override\n    public String toString() {\n        return \"Popular{\" +\n                \"ctime='\" + ctime + '\\'' +\n                \", title='\" + title + '\\'' +\n                \", description='\" + description + '\\'' +\n                \", picUrl='\" + picUrl + '\\'' +\n                \", url='\" + url + '\\'' +\n                '}';\n    }\n\n    /**\n     * ctime : 2016-05-25\n     * title : 李仁港怎么注入ROCK范儿？井宝如何撒野？《盗墓笔记》的方方面面请看这里！\n     * description : 南都全娱乐\n     * picUrl : http://zxpic.gtimg.com/infonew/0/wechat_pics_-5707820.jpg/640\n     * url : http://mp.weixin.qq.com/s?__biz=MjM5MTE1ODI2MA==&idx=2&mid=2651787931&sn=009a0d9df1accebef2adba14cc61ac9d\n     */\n\n    @SerializedName(\"date\")\n    private String ctime;\n    @SerializedName(\"title\")\n    private String title;\n    @SerializedName(\"userName\")\n    private String description;\n    @SerializedName(\"contentImg\")\n    private String picUrl;\n    @SerializedName(\"url\")\n    private String url;\n\n    public String getCtime() {\n        return ctime;\n    }\n\n    public void setCtime(String ctime) {\n        this.ctime = ctime;\n    }\n\n    public String getTitle() {\n        return title;\n    }\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n    public String getDescription() {\n        return description;\n    }\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n\n    public String getPicUrl() {\n        return picUrl;\n    }\n\n    public void setPicUrl(String picUrl) {\n        this.picUrl = picUrl;\n    }\n\n    public String getUrl() {\n        return url;\n    }\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/mapper/PopularModelDataMapper.java",
    "content": "package com.wkw.hot.mapper;\n\nimport com.wkw.hot.entity.PopularEntity;\nimport com.wkw.hot.model.PopularModel;\nimport com.wkw.hot.reject.PerActivity;\nimport java.util.ArrayList;\nimport java.util.List;\nimport javax.inject.Inject;\n\n/**\n * Created by wukewei on 16/12/2.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\npublic class PopularModelDataMapper {\n\n    @Inject\n    public PopularModelDataMapper() {\n\n    }\n\n    public PopularModel transform(PopularEntity popularEntity) {\n        if (popularEntity == null) {\n            throw  new IllegalArgumentException(\"Cannot transform a null value\");\n        }\n        PopularModel popularModel = new PopularModel();\n        popularModel.setCtime(popularEntity.getCtime());\n        popularModel.setDescription(popularEntity.getDescription());\n        popularModel.setPicUrl(popularEntity.getPicUrl());\n        popularModel.setTitle(popularEntity.getTitle());\n        popularModel.setUrl(popularEntity.getUrl());\n        return popularModel;\n    }\n\n\n    public List<PopularModel> transform(List<PopularEntity> popularList) {\n        List<PopularModel> popularModelsList = new ArrayList<>();\n        if (popularList != null && !popularList.isEmpty()) {\n            for (PopularEntity popularEntity : popularList) {\n                popularModelsList.add(transform(popularEntity));\n            }\n        }\n        return popularModelsList;\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/model/PopularModel.java",
    "content": "package com.wkw.hot.model;\n\n/**\n * Created by wukewei on 16/12/2.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class PopularModel {\n\n    private String ctime;\n    private String title;\n    private String description;\n    private String picUrl;\n    private String url;\n\n\n    @Override public String toString() {\n        return \"PopularModel{\" +\n            \"ctime='\" + ctime + '\\'' +\n            \", title='\" + title + '\\'' +\n            \", description='\" + description + '\\'' +\n            \", picUrl='\" + picUrl + '\\'' +\n            \", url='\" + url + '\\'' +\n            '}';\n    }\n\n\n    public String getCtime() {\n        return ctime;\n    }\n\n\n    public void setCtime(String ctime) {\n        this.ctime = ctime;\n    }\n\n\n    public String getDescription() {\n        return description;\n    }\n\n\n    public void setDescription(String description) {\n        this.description = description;\n    }\n\n\n    public String getTitle() {\n        return title;\n    }\n\n\n    public void setTitle(String title) {\n        this.title = title;\n    }\n\n\n    public String getPicUrl() {\n        return picUrl;\n    }\n\n\n    public void setPicUrl(String picUrl) {\n        this.picUrl = picUrl;\n    }\n\n\n    public String getUrl() {\n        return url;\n    }\n\n\n    public void setUrl(String url) {\n        this.url = url;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/navigator/Navigator.java",
    "content": "package com.wkw.hot.navigator;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport com.wkw.hot.ui.AboutActivity;\nimport com.wkw.hot.ui.react.MyReactActivity;\nimport javax.inject.Inject;\n\n/**\n * Created by wukewei on 16/9/14.\n */\npublic class Navigator {\n\n    @Inject\n    public Navigator() {\n\n    }\n\n    public void navigateToAbout(Context context) {\n        if (context != null) {\n            Intent intent = new Intent(context, AboutActivity.class);\n            context.startActivity(intent);\n        }\n    }\n    public void navigateToMyReact(Context context) {\n        if (context != null) {\n            Intent intent = new Intent(context, MyReactActivity.class);\n            context.startActivity(intent);\n        }\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/ContextLife.java",
    "content": "package com.wkw.hot.reject;\n\nimport java.lang.annotation.Documented;\nimport java.lang.annotation.Retention;\n\nimport javax.inject.Qualifier;\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n/**\n * Created by wukewei on 16/7/19.\n */\n@Qualifier\n@Documented\n@Retention(RUNTIME)\npublic @interface ContextLife {\n    String value() default \"Application\";\n}\n\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/PerActivity.java",
    "content": "package com.wkw.hot.reject;\n\nimport java.lang.annotation.Retention;\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\nimport javax.inject.Scope;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@Scope\n@Retention(RUNTIME)\npublic @interface PerActivity {\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/PerFragment.java",
    "content": "package com.wkw.hot.reject;\n\nimport java.lang.annotation.Retention;\n\nimport javax.inject.Scope;\n\nimport static java.lang.annotation.RetentionPolicy.RUNTIME;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@Scope\n@Retention(RUNTIME)\npublic @interface PerFragment {\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/component/ActivityComponent.java",
    "content": "package com.wkw.hot.reject.component;\n\nimport android.app.Activity;\n\nimport com.wkw.hot.data.DataManager;\nimport com.wkw.hot.reject.PerActivity;\nimport com.wkw.hot.reject.module.ActivityModule;\nimport com.wkw.hot.ui.main.MainActivity;\nimport com.wkw.hot.ui.search.SearchActivity;\nimport com.wkw.hot.ui.web.WebActivity;\n\nimport dagger.Component;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@PerActivity\n@Component(dependencies = AppComponent.class, modules = ActivityModule.class)\npublic interface ActivityComponent {\n\n    DataManager getDataManager();\n\n    Activity getActivity();\n\n    void inject(MainActivity mainActivity);\n    void inject(WebActivity webActivity);\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/component/AppComponent.java",
    "content": "package com.wkw.hot.reject.component;\n\nimport com.wkw.hot.data.DataManager;\nimport com.wkw.hot.reject.ContextLife;\nimport com.wkw.hot.reject.module.AppModule;\nimport com.wkw.hot.ui.App;\n\nimport javax.inject.Singleton;\n\nimport dagger.Component;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@Singleton\n@Component(modules = AppModule.class)\npublic interface AppComponent {\n\n    @ContextLife(\"Application\")\n    App getContext();\n\n    DataManager getDataManager();\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/component/FragmentComponent.java",
    "content": "package com.wkw.hot.reject.component;\n\nimport android.app.Activity;\n\nimport com.wkw.hot.data.DataManager;\nimport com.wkw.hot.reject.PerFragment;\nimport com.wkw.hot.reject.module.FragmentModule;\nimport com.wkw.hot.ui.item.ItemFragment;\n\nimport dagger.Component;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@PerFragment\n@Component(dependencies = AppComponent.class, modules = FragmentModule.class)\npublic interface FragmentComponent {\n\n    DataManager getDataManager();\n\n    Activity getActivity();\n\n    void inject(ItemFragment itemFragment);\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/module/ActivityModule.java",
    "content": "package com.wkw.hot.reject.module;\n\nimport android.app.Activity;\n\nimport com.wkw.hot.reject.PerActivity;\n\nimport dagger.Module;\nimport dagger.Provides;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@Module\npublic class ActivityModule {\n    private Activity mActivity;\n\n    public ActivityModule(Activity activity) {\n        this.mActivity = activity;\n    }\n\n    @Provides\n    @PerActivity\n    public Activity provideActivity() {\n        return mActivity;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/module/AppModule.java",
    "content": "package com.wkw.hot.reject.module;\n\nimport com.wkw.hot.cache.CacheLoader;\nimport com.wkw.hot.common.Constants;\nimport com.wkw.hot.data.DataManager;\nimport com.wkw.hot.data.api.HotApi;\nimport com.wkw.hot.navigator.Navigator;\nimport com.wkw.hot.reject.ContextLife;\nimport com.wkw.hot.ui.App;\n\nimport java.io.File;\nimport java.util.concurrent.TimeUnit;\n\nimport javax.inject.Singleton;\n\nimport dagger.Module;\nimport dagger.Provides;\nimport okhttp3.Cache;\nimport okhttp3.Interceptor;\nimport okhttp3.OkHttpClient;\nimport okhttp3.logging.HttpLoggingInterceptor;\nimport retrofit2.Retrofit;\nimport retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;\nimport retrofit2.converter.gson.GsonConverterFactory;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@Module\npublic class AppModule {\n\n    private App application;\n\n    public AppModule(App application) {\n        this.application = application;\n    }\n\n\n    @Provides\n    @Singleton\n    @ContextLife(\"Application\")\n    public App provideApp() {\n        return application;\n    }\n\n\n    @Provides\n    @Singleton\n    OkHttpClient provideOkHttpClient() {\n        HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();\n        loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);\n\n        Interceptor apikey = chain -> chain.proceed(chain.request().newBuilder()\n                .addHeader(\"apikey\", Constants.Api_Key).build());\n\n\n        OkHttpClient okHttpClient = new OkHttpClient.Builder()\n                .readTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)\n                .connectTimeout(Constants.HTTP_CONNECT_TIMEOUT, TimeUnit.MILLISECONDS)\n                .addInterceptor(apikey)\n                .addInterceptor(loggingInterceptor)\n                .build();\n\n        return okHttpClient;\n    }\n\n    @Provides\n    @Singleton\n    HotApi provideHotApi(OkHttpClient okHttpClient) {\n        Retrofit retrofit1 = new Retrofit.Builder()\n                .baseUrl(Constants.Base_Url)\n                .client(okHttpClient)\n                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())\n                .addConverterFactory(GsonConverterFactory.create())\n                .build();\n        HotApi hotApi = retrofit1.create(HotApi.class);\n\n        return hotApi;\n    }\n\n    @Provides\n    @Singleton\n    Navigator provideNavigator(Navigator navigator) {\n        return navigator;\n    }\n\n    @Provides\n    @Singleton\n    CacheLoader provideCacheLoader() {\n        return CacheLoader.getInstance(application);\n    }\n\n    @Provides\n    @Singleton\n    DataManager provideDataManager(HotApi hotApi, CacheLoader cacheLoader) {\n        return new DataManager(hotApi, cacheLoader);\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/reject/module/FragmentModule.java",
    "content": "package com.wkw.hot.reject.module;\n\nimport android.app.Activity;\nimport android.support.v4.app.Fragment;\n\nimport com.wkw.hot.reject.PerActivity;\nimport com.wkw.hot.reject.PerFragment;\n\nimport dagger.Module;\nimport dagger.Provides;\n\n/**\n * Created by wukewei on 16/7/19.\n */\n@Module\npublic class FragmentModule {\n\n    private Fragment fragment;\n\n    public FragmentModule(Fragment fragment) {\n        this.fragment = fragment;\n    }\n\n    @Provides\n    @PerFragment\n    public Activity provideActivity() {\n        return fragment.getActivity();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/AboutActivity.java",
    "content": "package com.wkw.hot.ui;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.support.design.widget.CollapsingToolbarLayout;\nimport android.support.v7.widget.Toolbar;\nimport android.widget.TextView;\n\nimport com.wkw.hot.BuildConfig;\nimport com.wkw.hot.R;\nimport com.wkw.hot.base.BaseActivity;\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.module.ActivityModule;\n\nimport butterknife.Bind;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic class AboutActivity extends BaseActivity {\n    @Bind(R.id.tv_version)\n    TextView mVersionTv;\n    @Bind(R.id.toolbar)\n    Toolbar mToolbar;\n    @Bind(R.id.about_collapsing_tool)\n    CollapsingToolbarLayout mCollapsingToolbarLayout;\n\n\n    public static void startActivity(Context context) {\n        Intent intent = new Intent(context, AboutActivity.class);\n        context.startActivity(intent);\n    }\n\n    @Override\n    protected void setupActivityComponent(AppComponent appComponent, ActivityModule activityModule) {\n\n    }\n\n    @Override\n    protected int getLayout() {\n        return R.layout.activity_about;\n    }\n\n    @Override\n    protected void initEventAndData() {\n        mCollapsingToolbarLayout.setTitle(getString(R.string.app_name));\n        setSupportActionBar(mToolbar);\n        getSupportActionBar().setDisplayHomeAsUpEnabled(true);\n        mToolbar.setNavigationOnClickListener(v -> AboutActivity.this.onBackPressed());\n        mVersionTv.setText(\"Version \" + BuildConfig.VERSION_NAME);\n    }\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/App.java",
    "content": "package com.wkw.hot.ui;\n\nimport android.app.Application;\n\nimport com.facebook.react.ReactApplication;\nimport com.facebook.react.ReactNativeHost;\nimport com.facebook.react.ReactPackage;\nimport com.facebook.react.shell.MainReactPackage;\nimport com.wkw.common_lib.Ext;\nimport com.wkw.common_lib.image.ImageLoader;\nimport com.wkw.common_lib.image.glide.GlideImageLoaderStrategy;\nimport com.wkw.common_lib.network.Network;\nimport com.wkw.common_lib.utils.ProcessUtils;\nimport com.wkw.common_lib.utils.ViewUtils;\nimport com.wkw.hot.BuildConfig;\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.component.DaggerAppComponent;\nimport com.wkw.hot.reject.module.AppModule;\n\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class App extends Application implements ReactApplication{\n\n    private static App appContext;\n    private static AppComponent mAppComponent;\n\n    private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {\n        @Override\n        protected boolean getUseDeveloperSupport() {\n            return BuildConfig.DEBUG;\n        }\n\n        @Override\n        protected List<ReactPackage> getPackages() {\n            return Arrays.<ReactPackage>asList(\n                    new MainReactPackage()\n            );\n        }\n    };\n    @Override\n    public void onCreate() {\n        super.onCreate();\n        appContext = this;\n        if (!ProcessUtils.isMainProcess(this)) {\n            return;\n        }\n        mAppComponent = DaggerAppComponent.builder()\n                .appModule(new AppModule(this))\n                .build();\n        initImageLoader();\n        initExtension();\n    }\n\n\n    private void initImageLoader() {\n        ImageLoader.getInstance().setImageLoaderStragety(new GlideImageLoaderStrategy());\n    }\n\n\n    private void initExtension() {\n        Ext.init(this, new ExtImpl());\n    }\n\n    @Override\n    public ReactNativeHost getReactNativeHost() {\n        return mReactNativeHost;\n    }\n\n    public static final class ExtImpl extends Ext {\n\n        @Override\n        public String getCurOpenId() {\n            return null;\n        }\n\n        @Override\n        public String getDeviceInfo() {\n            return null;\n        }\n\n        @Override\n        public String getPackageNameForResource() {\n            return \"com.wkw.hot\";\n        }\n\n        @Override\n        public int getScreenHeight() {\n            return ViewUtils.getScreenHeight();\n        }\n\n        @Override\n        public int getScreenWidth() {\n            return ViewUtils.getScreenWidth();\n        }\n\n        @Override\n        public boolean isAvailable() {\n            return Network.isAvailable();\n        }\n\n        @Override\n        public boolean isWap() {\n            return Network.isWap();\n        }\n\n        @Override\n        public boolean isMobile() {\n            return Network.isMobile();\n        }\n\n        @Override\n        public boolean is2G() {\n            return Network.is2G();\n        }\n\n        @Override\n        public boolean is3G() {\n            return Network.is3G();\n        }\n\n        @Override\n        public boolean isWifi() {\n            return Network.isWifi();\n        }\n\n        @Override\n        public boolean isEthernet() {\n            return Network.isEthernet();\n        }\n    }\n\n    public static AppComponent getAppComponent() {\n        return mAppComponent;\n    }\n    public static App getAppContext() {\n        return appContext;\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/item/ItemAdapter.java",
    "content": "package com.wkw.hot.ui.item;\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;\n\nimport com.wkw.common_lib.image.ImageLoader;\nimport com.wkw.common_lib.image.glide.GlideImageConfig;\nimport com.wkw.hot.R;\nimport com.wkw.hot.base.BaseLoadMoreAdapter;\nimport com.wkw.hot.entity.PopularEntity;\nimport com.wkw.hot.model.PopularModel;\nimport com.wkw.hot.utils.GlideManager;\n\nimport butterknife.Bind;\nimport butterknife.ButterKnife;\n\n/**\n * Created by wukewei on 16/6/1.\n */\npublic class ItemAdapter extends BaseLoadMoreAdapter<PopularModel, ItemAdapter.ViewHolder> {\n\n\n    private OnItemClickListener listener;\n\n    public void setOnItemClickListener(OnItemClickListener listener) {\n        this.listener = listener;\n    }\n\n    @Override\n    public void onBindItemViewHolder(ViewHolder holder, PopularModel data, int position) {\n        ImageLoader.getInstance().displayImage(holder.imgItem.getContext(),\n            GlideImageConfig.builder()\n                .url(data.getPicUrl())\n                .imagerView(holder.imgItem)\n                .build());\n        //GlideManager.loadListImageView(holder.imgItem.getContext(), data.getPicUrl(), holder.imgItem);\n        holder.tvTitle.setText(data.getTitle());\n        holder.tvDate.setText(\"来自:\"+data.getDescription());\n        holder.mPopular = data;\n    }\n\n    @Override\n    public ViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {\n        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.layout_item, parent, false);\n        return new ViewHolder(view);\n    }\n\n\n    public class ViewHolder extends RecyclerView.ViewHolder {\n        @Bind(R.id.img_item)\n        ImageView imgItem;\n        @Bind(R.id.tv_title)\n        TextView tvTitle;\n        @Bind(R.id.tv_date)\n        TextView tvDate;\n        @Bind(R.id.card_view)\n        CardView cardView;\n        PopularModel mPopular;\n        public ViewHolder(View itemView) {\n            super(itemView);\n            ButterKnife.bind(this, itemView);\n            cardView.setOnClickListener(v -> {\n                if (listener != null) {\n                    listener.onItemClick(mPopular.getUrl(), mPopular.getTitle());\n                }\n            });\n        }\n    }\n\n    public interface OnItemClickListener {\n        void onItemClick(String url, String title);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/item/ItemContract.java",
    "content": "package com.wkw.hot.ui.item;\n\nimport com.wkw.hot.base.ILoadingView;\nimport com.wkw.hot.base.IPresenter;\nimport com.wkw.hot.entity.PopularEntity;\n\nimport com.wkw.hot.model.PopularModel;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/5/30.\n */\npublic class ItemContract {\n    interface View extends ILoadingView {\n        void addLoadMoreData(List<PopularModel> data);\n        void addRefreshData(List<PopularModel> data);\n    }\n    interface Presenter extends IPresenter<View> {\n        void getListData(String type);\n        void getCacheData(String type);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/item/ItemFragment.java",
    "content": "package com.wkw.hot.ui.item;\n\nimport android.content.Context;\nimport android.os.Bundle;\nimport android.support.v4.widget.SwipeRefreshLayout;\nimport android.support.v7.widget.DefaultItemAnimator;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.view.View;\nimport android.widget.LinearLayout;\n\nimport com.wkw.common_lib.network.Network;\nimport com.wkw.common_lib.network.NetworkState;\nimport com.wkw.common_lib.network.NetworkStateListener;\nimport com.wkw.hot.R;\nimport com.wkw.hot.base.BaseLazyFragment;\nimport com.wkw.hot.base.BaseOnScrollListener;\nimport com.wkw.hot.model.PopularModel;\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.component.DaggerFragmentComponent;\nimport com.wkw.hot.reject.module.FragmentModule;\nimport com.wkw.hot.ui.web.WebActivity;\nimport com.wkw.common_lib.widget.ProgressLayout;\n\nimport java.util.List;\n\nimport butterknife.Bind;\nimport butterknife.OnClick;\n\n/**\n * Created by wukewei on 16/5/30.\n */\npublic class ItemFragment extends BaseLazyFragment<ItemPresenter> implements ItemContract.View {\n    public static final String TYPE = \"type\";\n\n    protected String type;\n    @Bind(R.id.recycler_view)\n    RecyclerView recyclerView;\n    @Bind(R.id.swipe_refresh_layout)\n    SwipeRefreshLayout swipeRefreshLayout;\n    @Bind(R.id.progress_layout)\n    ProgressLayout progressLayout;\n\n    View.OnClickListener tryClick;\n    @Bind(R.id.llyt_network)\n    LinearLayout llytNetwork;\n    private ItemAdapter mAdapter;\n\n    public static ItemFragment newInstance(String type) {\n        ItemFragment fragment = new ItemFragment();\n        Bundle bundle = new Bundle();\n        bundle.putString(TYPE, type);\n        fragment.setArguments(bundle);\n        return fragment;\n    }\n\n\n    private NetworkChangeListener mNetworkChangeListener;\n\n    @Override\n    protected void onFirstUserVisible() {\n        mPresenter.getCacheData(type);\n\n    }\n\n    @Override\n    protected void onUserVisible() {\n\n    }\n\n    @Override\n    protected void onUserInvisible() {\n\n    }\n\n    class NetworkChangeListener implements NetworkStateListener {\n\n        @Override\n        public void onNetworkStateChanged(NetworkState lastState, NetworkState newState) {\n            if (!newState.isConnected()) {\n                showNetWorkLayout();\n            } else {\n                hideNetWorkLayout();\n            }\n\n        }\n    }\n\n\n    @Override\n    protected void setupActivityComponent(AppComponent appComponent, FragmentModule fragmentModule) {\n        DaggerFragmentComponent.builder()\n                .appComponent(appComponent)\n                .fragmentModule(fragmentModule)\n                .build()\n                .inject(this);\n    }\n\n    @Override\n    protected int getLayoutId() {\n        return R.layout.fragment_item;\n    }\n\n    @Override\n    protected void initEventAndData() {\n\n        mNetworkChangeListener = new NetworkChangeListener();\n        Network.addListener(mNetworkChangeListener);\n        tryClick = v -> {\n            mPresenter.replacePn();\n            mPresenter.getListData(type);\n        };\n        mAdapter = new ItemAdapter();\n        mAdapter.setOnItemClickListener((url, title) -> {\n            WebActivity.startActivity(mContext, url, title);\n        });\n        recyclerView.setItemAnimator(new DefaultItemAnimator());\n        recyclerView.setLayoutManager(new LinearLayoutManager(mContext));\n        recyclerView.setAdapter(mAdapter);\n        type = getArguments().getString(TYPE);\n        recyclerView.addOnScrollListener(new BaseOnScrollListener() {\n            @Override\n            public void onLoadMore() {\n                if (mAdapter.canLoadMore()) {\n                    mAdapter.setLoading(true);\n                    mPresenter.pn++;\n                    mPresenter.getListData(type);\n                }\n            }\n        });\n        swipeRefreshLayout.setOnRefreshListener(() -> {\n            mPresenter.replacePn();\n            mPresenter.getListData(type);\n        });\n    }\n\n\n    @Override\n    public void addLoadMoreData(List<PopularModel> data) {\n        mAdapter.addLoadMoreData(data);\n    }\n\n    @Override\n    public void addRefreshData(List<PopularModel> data) {\n        hideRefreshLayout();\n        mAdapter.addRefreshData(data);\n    }\n\n    @Override\n    public void showLoading() {\n        if (!progressLayout.isContent())\n            progressLayout.showLoading();\n    }\n\n    private void hideRefreshLayout() {\n        if (swipeRefreshLayout.isRefreshing()) {\n            swipeRefreshLayout.postDelayed(() -> {\n                swipeRefreshLayout.setRefreshing(false);\n            }, 800);\n        }\n    }\n\n    @Override\n    public void showContent() {\n        if (!progressLayout.isContent()) progressLayout.showContent();\n    }\n\n    @Override\n    public void showNotData() {\n        progressLayout.showNotData(tryClick);\n    }\n\n    @Override\n    public void showError(String msg) {\n        hideRefreshLayout();\n        progressLayout.showError(msg, tryClick);\n    }\n\n\n    @Override public Context context() {\n        return getActivity().getApplication();\n    }\n\n\n    @OnClick(value = R.id.img_delete)\n    public void onDelete(View view) {\n        hideNetWorkLayout();\n    }\n\n    private void showNetWorkLayout() {\n        if (llytNetwork.getVisibility() == View.GONE) {\n            llytNetwork.setVisibility(View.VISIBLE);\n        }\n    }\n    private void hideNetWorkLayout() {\n        if (llytNetwork.getVisibility() == View.VISIBLE) {\n            llytNetwork.setVisibility(View.GONE);\n        }\n    }\n\n\n    @Override\n    public void onDestroy() {\n        Network.removeListener(mNetworkChangeListener);\n        super.onDestroy();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/item/ItemPresenter.java",
    "content": "package com.wkw.hot.ui.item;\n\nimport com.wkw.common_lib.rx.RxSubscriber;\nimport com.wkw.hot.base.BasePresenter;\nimport com.wkw.hot.data.DataManager;\nimport com.wkw.hot.entity.PopularEntity;\nimport com.wkw.hot.mapper.PopularModelDataMapper;\nimport com.wkw.hot.model.PopularModel;\nimport java.util.List;\nimport javax.inject.Inject;\nimport rx.Subscription;\n\n/**\n * Created by wukewei on 16/5/30.\n */\npublic class ItemPresenter extends BasePresenter<ItemContract.View> implements ItemContract.Presenter {\n\n    protected int pn = 1;\n    private final DataManager mDataManager;\n    private final PopularModelDataMapper mPopularModelDataMapper;\n\n    protected void replacePn() {\n        pn = 1;\n    }\n\n    private boolean isRefresh() {\n        return pn == 1;\n    }\n\n    @Inject\n    public ItemPresenter(DataManager dataManager, PopularModelDataMapper popularModelDataMapper) {\n        mDataManager = dataManager;\n        mPopularModelDataMapper = popularModelDataMapper;\n    }\n\n    @Override\n    public void getListData(String type) {\n        mView.showLoading();\n        Subscription subscription = mDataManager.getPopular(pn, type)\n            .map(popularEntityList -> mPopularModelDataMapper.transform(popularEntityList))\n            .subscribe(new RxSubscriber<List<PopularModel>>() {\n                    @Override\n                    public void _noNext(List<PopularModel> populars) {\n                        mView.showContent();\n                        if (isRefresh()) {\n                            if (populars.size() == 0) mView.showNotData();\n                            mView.addRefreshData(populars);\n                        } else {\n                            mView.addLoadMoreData(populars);\n                        }\n                    }\n\n                    @Override\n                    public void _onError(String msg) {\n                        if (isRefresh())\n                            mView.showError(msg);\n                    }\n            });\n\n        addSubscribe(subscription);\n\n    }\n\n    @Override\n    public void getCacheData(String type) {\n        mView.showLoading();\n        Subscription subscription = mDataManager.getCachePopular(type)\n            .map(popularEntityList -> mPopularModelDataMapper.transform(popularEntityList))\n            .subscribe(new RxSubscriber<List<PopularModel>>() {\n                    @Override\n                    public void _noNext(List<PopularModel> populars) {\n                        mView.showContent();\n                        mView.addLoadMoreData(populars);\n                    }\n\n                    @Override\n                    public void _onError(String msg) {\n                        mView.showError(msg);\n                    }\n            });\n\n        addSubscribe(subscription);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/main/MainActivity.java",
    "content": "package com.wkw.hot.ui.main;\n\nimport android.content.Intent;\nimport android.speech.RecognizerIntent;\nimport android.support.design.widget.NavigationView;\nimport android.support.design.widget.TabLayout;\nimport android.support.v4.view.GravityCompat;\nimport android.support.v4.view.ViewPager;\nimport android.support.v4.widget.DrawerLayout;\nimport android.support.v7.app.ActionBarDrawerToggle;\nimport android.support.v7.widget.Toolbar;\nimport android.text.TextUtils;\nimport android.view.Menu;\nimport android.view.MenuItem;\n\nimport com.github.markzhai.react.preloader.ReactPreLoader;\nimport com.miguelcatalan.materialsearchview.MaterialSearchView;\nimport com.wkw.common_lib.utils.ToashUtils;\nimport com.wkw.hot.R;\nimport com.wkw.hot.adapter.FragmentAdapter;\nimport com.wkw.hot.base.BaseActivity;\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.component.DaggerActivityComponent;\nimport com.wkw.hot.reject.module.ActivityModule;\nimport com.wkw.hot.ui.AboutActivity;\nimport com.wkw.hot.ui.item.ItemFragment;\nimport com.wkw.hot.ui.react.MyReactActivity;\n\nimport com.wkw.hot.ui.search.SearchActivity;\nimport java.util.ArrayList;\nimport java.util.List;\n\nimport butterknife.Bind;\n\npublic class MainActivity extends BaseActivity<MainPresenter>\n        implements NavigationView.OnNavigationItemSelectedListener, MainContract.View {\n\n    @Bind(R.id.toolbar)\n    Toolbar toolbar;\n\n    @Bind(R.id.drawer_layout)\n    DrawerLayout drawer;\n\n    @Bind(R.id.tabs)\n    TabLayout tabLayout;\n\n    @Bind(R.id.viewpager)\n    ViewPager viewpager;\n\n\n    @Bind(R.id.nav_view)\n    NavigationView navView;\n\n    @Bind(R.id.search_view)\n    MaterialSearchView searchView;\n    protected FragmentAdapter mAdapter;\n\n\n\n    @Override\n    protected void setupActivityComponent(AppComponent appComponent, ActivityModule activityModule) {\n\n        DaggerActivityComponent.builder()\n                .appComponent(appComponent)\n                .activityModule(activityModule)\n                .build()\n                .inject(this);\n    }\n\n    @Override\n    protected int getLayout() {\n        return R.layout.activity_main;\n    }\n\n    @Override\n    protected void initEventAndData() {\n\n        setSupportActionBar(toolbar);\n        ActionBarDrawerToggle toggle = new ActionBarDrawerToggle(\n                this, drawer, toolbar, R.string.navigation_drawer_open, R.string.navigation_drawer_close);\n        drawer.setDrawerListener(toggle);\n        toggle.syncState();\n        mPresenter.getTabs();\n        navView.setNavigationItemSelectedListener(this);\n        ReactPreLoader.init(this, MyReactActivity.reactInfo);\n\n        searchView.setVoiceSearch(false);\n        searchView.setCursorDrawable(R.drawable.custom_cursor);\n        searchView.setEllipsize(true);\n        searchView.setHint(getString(R.string.search));\n        searchView.setSuggestions(getResources().getStringArray(R.array.query_suggestions));\n        searchView.setOnQueryTextListener(new MaterialSearchView.OnQueryTextListener() {\n            @Override\n            public boolean onQueryTextSubmit(String query) {\n                SearchActivity.startActivity(mContext, query);\n                return false;\n            }\n\n            @Override\n            public boolean onQueryTextChange(String newText) {\n                //Do some magic\n                return false;\n            }\n        });\n\n        searchView.setOnSearchViewListener(new MaterialSearchView.SearchViewListener() {\n            @Override\n            public void onSearchViewShown() {\n                //Do some magic\n            }\n\n            @Override\n            public void onSearchViewClosed() {\n                //Do some magic\n            }\n        });\n    }\n\n    @Override\n    public void onBackPressed() {\n        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);\n        if (drawer.isDrawerOpen(GravityCompat.START)) {\n            drawer.closeDrawer(GravityCompat.START);\n        } else {\n            if (searchView.isSearchOpen()) {\n                searchView.closeSearch();\n            } else {\n                super.onBackPressed();\n            }\n        }\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        // Inflate the menu; this adds items to the action bar if it is present.\n        getMenuInflater().inflate(R.menu.main, menu);\n\n        MenuItem item = menu.findItem(R.id.action_search);\n        searchView.setMenuItem(item);\n\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        int id = item.getItemId();\n        return super.onOptionsItemSelected(item);\n    }\n\n    @SuppressWarnings(\"StatementWithEmptyBody\")\n    @Override\n    public boolean onNavigationItemSelected(MenuItem item) {\n\n        DrawerLayout drawer = (DrawerLayout) findViewById(R.id.drawer_layout);\n        drawer.closeDrawer(GravityCompat.START);\n        int id = item.getItemId();\n        if (id == R.id.nav_sports) {\n            navigator.navigateToMyReact(mContext);\n        } else if (id == R.id.nav_about) {\n            navigator.navigateToAbout(mContext);\n        }\n        return true;\n    }\n\n    @Override\n    public void addTabs(List<String> tabs) {\n        mAdapter = new FragmentAdapter(getSupportFragmentManager());\n        for (String tab : tabs) {\n            ItemFragment fragment = ItemFragment.newInstance(tab);\n            mAdapter.addFragment(fragment, tab);\n        }\n        viewpager.setAdapter(mAdapter);\n        tabLayout.setupWithViewPager(viewpager);\n    }\n\n    @Override\n    protected void onActivityResult(int requestCode, int resultCode, Intent data) {\n        if (requestCode == MaterialSearchView.REQUEST_VOICE && resultCode == RESULT_OK) {\n            ArrayList<String> matches = data.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS);\n            if (matches != null && matches.size() > 0) {\n                String searchWrd = matches.get(0);\n                if (!TextUtils.isEmpty(searchWrd)) {\n                    searchView.setQuery(searchWrd, false);\n                }\n            }\n\n            return;\n        }\n        super.onActivityResult(requestCode, resultCode, data);\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/main/MainContract.java",
    "content": "package com.wkw.hot.ui.main;\n\nimport com.wkw.hot.base.IPresenter;\nimport com.wkw.hot.base.IView;\n\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic interface MainContract {\n\n    interface View extends IView {\n        void addTabs(List<String> tabs);\n\n    }\n\n    interface Presenter extends IPresenter<View> {\n        void getTabs();\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/main/MainPresenter.java",
    "content": "package com.wkw.hot.ui.main;\n\nimport com.wkw.hot.base.BasePresenter;\nimport com.wkw.hot.data.DataManager;\nimport javax.inject.Inject;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class MainPresenter extends BasePresenter<MainContract.View> implements MainContract.Presenter {\n\n    private final DataManager mDataManager;\n    @Inject\n    public MainPresenter(DataManager dataManager) {\n        mDataManager = dataManager;\n    }\n\n    @Override\n    public void getTabs() {\n        //类型暂时先写死\n        mView.addTabs(mDataManager.getTabs());\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/react/MyReactActivity.java",
    "content": "package com.wkw.hot.ui.react;\n\nimport com.github.markzhai.react.preloader.MrReactActivity;\nimport com.github.markzhai.react.preloader.ReactInfo;\n\n/**\n * Created by wukewei on 16/8/15.\n */\npublic class MyReactActivity extends MrReactActivity {\n    public static final ReactInfo reactInfo = new ReactInfo(\"MyHot\", null);\n\n\n    @Override\n    protected String getMainComponentName() {\n        return reactInfo.getMainComponentName();\n    }\n\n    @Override\n    public ReactInfo getReactInfo() {\n        return reactInfo;\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/search/SearchActivity.java",
    "content": "package com.wkw.hot.ui.search;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.os.Bundle;\nimport android.support.annotation.Nullable;\nimport android.support.v4.app.Fragment;\nimport android.support.v7.widget.Toolbar;\nimport butterknife.Bind;\nimport com.wkw.hot.R;\nimport com.wkw.hot.base.BaseActivity;\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.module.ActivityModule;\nimport com.wkw.hot.ui.item.ItemFragment;\n\n/**\n * Created by wukewei on 16/9/14.\n */\npublic class SearchActivity extends BaseActivity {\n\n    public static final String TYPE = \"TYPE\";\n    @Bind(R.id.toolbar) Toolbar toolbar;\n    private String type;\n\n\n    public static void startActivity(Context context, String type) {\n        Intent intent = new Intent(context, SearchActivity.class);\n        intent.putExtra(TYPE, type);\n        context.startActivity(intent);\n    }\n\n\n    @Override protected void onCreate(@Nullable Bundle savedInstanceState) {\n        super.onCreate(savedInstanceState);\n        type = getIntent().getStringExtra(TYPE);\n        setCommonBackToolBack(toolbar, type);\n        if (savedInstanceState == null) {\n            ItemFragment fragment = ItemFragment.newInstance(type);\n            loadFragment(fragment);\n        }\n    }\n\n\n    private void loadFragment(Fragment fragment) {\n        getSupportFragmentManager().beginTransaction()\n            .add(R.id.container, fragment, fragment.getClass().getName())\n            .commit();\n        fragment.setUserVisibleHint(true);\n    }\n\n\n    @Override\n    protected void setupActivityComponent(AppComponent appComponent, ActivityModule activityModule) {\n\n    }\n\n\n    @Override protected int getLayout() {\n        return R.layout.activity_search;\n    }\n\n\n    @Override protected void initEventAndData() {\n\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/web/WebActivity.java",
    "content": "package com.wkw.hot.ui.web;\n\nimport android.content.Context;\nimport android.content.Intent;\nimport android.support.v7.app.AppCompatActivity;\nimport android.support.v7.widget.Toolbar;\nimport android.view.KeyEvent;\nimport android.view.Menu;\nimport android.view.MenuItem;\nimport android.view.View;\nimport android.webkit.WebChromeClient;\nimport android.webkit.WebSettings;\nimport android.webkit.WebView;\nimport android.webkit.WebViewClient;\nimport android.widget.ProgressBar;\n\nimport com.wkw.common_lib.utils.AndroidUtils;\nimport com.wkw.hot.R;\nimport com.wkw.hot.base.BaseActivity;\nimport com.wkw.hot.base.IPresenter;\nimport com.wkw.hot.reject.component.AppComponent;\nimport com.wkw.hot.reject.component.DaggerActivityComponent;\nimport com.wkw.hot.reject.module.ActivityModule;\nimport com.wkw.hot.ui.AboutActivity;\n\nimport butterknife.Bind;\n\n/**\n * Created by wukewei on 16/6/2.\n */\npublic class WebActivity extends BaseActivity<WebPresenter> implements WebContract.View {\n\n\n    private static final String URL = \"url\";\n    private static final String TITLE = \"title\";\n    @Bind(R.id.toolbar)\n    Toolbar toolbar;\n    @Bind(R.id.webView)\n    WebView webView;\n    @Bind(R.id.progress_bar)\n    ProgressBar progressBar;\n\n\n    private String url, title;\n\n    public static void startActivity(Context context, String url, String title) {\n        Intent intent = new Intent(context,WebActivity.class);\n        intent.putExtra(URL, url);\n        intent.putExtra(TITLE, title);\n        context.startActivity(intent);\n    }\n\n\n    @Override\n    protected int getLayout() {\n        return R.layout.activity_web;\n    }\n\n    @Override\n    protected void initEventAndData() {\n        url = getIntent().getStringExtra(URL);\n        title = getIntent().getStringExtra(TITLE);\n        setCommonBackToolBack(toolbar, title);\n        WebSettings settings = webView.getSettings();\n        settings.setJavaScriptEnabled(true);\n        settings.setLoadWithOverviewMode(true);\n        settings.setAppCacheEnabled(true);\n        settings.setLayoutAlgorithm(WebSettings.LayoutAlgorithm.SINGLE_COLUMN);\n        settings.setSupportZoom(true);\n        webView.setWebChromeClient(new ChromeClient());\n        webView.setWebViewClient(new Client());\n        webView.loadUrl(url);\n    }\n\n\n    @Override\n    protected void onResume() {\n        super.onResume();\n        if (webView != null) webView.onResume();\n    }\n\n    @Override\n    protected void onPause() {\n        super.onPause();\n        if (webView != null) webView.onPause();\n    }\n\n    @Override\n    public boolean onKeyDown(int keyCode, KeyEvent event) {\n        if (event.getAction() == KeyEvent.ACTION_DOWN) {\n            switch (keyCode) {\n                case KeyEvent.KEYCODE_BACK:\n                    if (webView.canGoBack()) {\n                        webView.goBack();\n                    } else {\n                        finish();\n                    }\n                    return true;\n            }\n        }\n        return super.onKeyDown(keyCode, event);\n    }\n\n\n\n    @Override\n    protected void setupActivityComponent(AppComponent appComponent, ActivityModule activityModule) {\n        DaggerActivityComponent.builder()\n                .appComponent(appComponent)\n                .activityModule(activityModule)\n                .build()\n                .inject(this);\n    }\n\n    @Override\n    public boolean onCreateOptionsMenu(Menu menu) {\n        // Inflate the menu; this adds items to the action bar if it is present.\n        getMenuInflater().inflate(R.menu.menu_web, menu);\n        return true;\n    }\n\n    @Override\n    public boolean onOptionsItemSelected(MenuItem item) {\n        int id = item.getItemId();\n\n        switch (id) {\n            case  R.id.action_other_browser:\n                AndroidUtils.openBrowser(mContext, url);\n                return true;\n\n            case R.id.action_cory_url:\n                AndroidUtils.copyToClipBoard(mContext, webView.getUrl());\n                return true;\n\n            case R.id.action_share:\n                AndroidUtils.showSystemShareOption(mContext, getString(R.string.share_title), url);\n                return true;\n        }\n\n        return super.onOptionsItemSelected(item);\n    }\n\n    @Override\n    protected void onDestroy() {\n        super.onDestroy();\n        if (webView != null) {\n            webView.removeAllViews();\n            webView.destroy();\n        }\n    }\n\n    private class ChromeClient extends WebChromeClient {\n        @Override\n        public void onProgressChanged(WebView view, int newProgress) {\n            progressBar.setProgress(newProgress);\n            if (newProgress == 100) {\n                progressBar.setVisibility(View.GONE);\n            } else {\n                progressBar.setVisibility(View.VISIBLE);\n            }\n            super.onProgressChanged(view, newProgress);\n        }\n\n        @Override\n        public void onReceivedTitle(WebView view, String title) {\n            super.onReceivedTitle(view, title);\n        }\n    }\n    private class Client extends WebViewClient {\n        @Override\n        public boolean shouldOverrideUrlLoading(WebView view, String url) {\n            if (url!=null) view.loadUrl(url);\n            return  true;\n        }\n    }\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/web/WebContract.java",
    "content": "package com.wkw.hot.ui.web;\n\nimport com.wkw.hot.base.IPresenter;\nimport com.wkw.hot.base.IView;\n\n/**\n * Created by wukewei on 16/5/30.\n */\npublic class WebContract {\n    interface View extends IView {\n    }\n    interface Presenter extends IPresenter<View> {\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/ui/web/WebPresenter.java",
    "content": "package com.wkw.hot.ui.web;\n\nimport com.wkw.hot.base.BasePresenter;\nimport com.wkw.hot.data.DataManager;\nimport javax.inject.Inject;\n\n/**\n * Created by wukewei on 16/5/30.\n */\npublic class WebPresenter extends BasePresenter<WebContract.View> implements WebContract.Presenter {\n\n\n    @Inject\n    public WebPresenter() {\n\n    }\n\n\n\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/utils/GlideManager.java",
    "content": "package com.wkw.hot.utils;\n\nimport android.content.Context;\nimport android.widget.ImageView;\n\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\n\n/**\n * Created by wukewei on 16/6/30.\n */\npublic class GlideManager {\n\n    public static void loadListImageView(Context context, String url, ImageView imageView) {\n        Glide.with(context)\n                .load(url)\n                .diskCacheStrategy(DiskCacheStrategy.ALL)\n                .into(imageView);\n    }\n}\n"
  },
  {
    "path": "app/src/main/java/com/wkw/hot/utils/Logger.java",
    "content": "package com.wkw.hot.utils;\n\nimport android.util.Log;\n\n/**\n * Created by wukewei on 16/6/1.\n */\npublic class Logger {\n\n    public static boolean isDebug = true;\n    public static final String TAG = \"HOT_TAG\";\n\n    public static void d(String msg) {\n        if (isDebug)\n            Log.d(TAG, msg);\n\n    }\n\n    public static void i(String msg) {\n        if (isDebug)\n            Log.i(TAG, msg);\n    }\n\n    public static void e(String msg) {\n        if (isDebug)\n            Log.e(TAG, msg);\n    }\n\n    public static void w(String msg) {\n        if (isDebug)\n            Log.w(TAG, msg);\n    }\n    public static void v(String msg) {\n        if (isDebug)\n            Log.v(TAG, msg);\n    }\n}\n"
  },
  {
    "path": "app/src/main/res/drawable/custom_cursor.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<shape xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <size android:width=\"2dp\" />\n    <solid android:color=\"@color/colorPrimary\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable/progress_bar_bg.xml",
    "content": "<layer-list xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <item android:id=\"@android:id/background\">\n        <shape>\n            <corners android:radius=\"5dip\" />\n            <gradient\n                android:angle=\"0\"\n                android:centerColor=\"#ffffff\"\n                android:centerY=\"0.75\"\n                android:endColor=\"#ffffff\"\n                android:startColor=\"#ffffff\" />\n        </shape>\n    </item>\n\n    <item android:id=\"@android:id/secondaryProgress\">\n        <clip>\n            <shape>\n                <corners android:radius=\"5dip\" />\n                <gradient\n                    android:angle=\"0\"\n                    android:centerColor=\"#ffffff\"\n                    android:centerY=\"0.75\"\n                    android:endColor=\"#ffffff\"\n                    android:startColor=\"#ffffff\" />\n            </shape>\n        </clip>\n    </item>\n\n    <item android:id=\"@android:id/progress\">\n        <clip>\n            <shape>\n                <corners android:radius=\"5dip\" />\n                <gradient\n                    android:angle=\"0\"\n                    android:endColor=\"#FF4081\"\n                    android:startColor=\"#FF4081\" />\n            </shape>\n        </clip>\n    </item>\n\n</layer-list>"
  },
  {
    "path": "app/src/main/res/drawable/side_nav_bar.xml",
    "content": "<shape xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:shape=\"rectangle\">\n    <gradient\n        android:angle=\"135\"\n        android:centerColor=\"#4CAF50\"\n        android:endColor=\"#2E7D32\"\n        android:startColor=\"#81C784\"\n        android:type=\"linear\" />\n</shape>"
  },
  {
    "path": "app/src/main/res/drawable-v21/ic_menu_camera.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportHeight=\"24.0\"\n    android:viewportWidth=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0\" />\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M9,2L7.17,4H4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2V6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2H9zm3,15c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable-v21/ic_menu_gallery.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportHeight=\"24.0\"\n    android:viewportWidth=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M22,16V4c0,-1.1 -0.9,-2 -2,-2H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2zm-11,-4l2.03,2.71L16,11l4,5H8l3,-4zM2,6v14c0,1.1 0.9,2 2,2h14v-2H4V6H2z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable-v21/ic_menu_manage.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportHeight=\"24.0\"\n    android:viewportWidth=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M22.7,19l-9.1,-9.1c0.9,-2.3 0.4,-5 -1.5,-6.9 -2,-2 -5,-2.4 -7.4,-1.3L9,6 6,9 1.6,4.7C0.4,7.1 0.9,10.1 2.9,12.1c1.9,1.9 4.6,2.4 6.9,1.5l9.1,9.1c0.4,0.4 1,0.4 1.4,0l2.3,-2.3c0.5,-0.4 0.5,-1.1 0.1,-1.4z\" />\n</vector>"
  },
  {
    "path": "app/src/main/res/drawable-v21/ic_menu_send.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportHeight=\"24.0\"\n    android:viewportWidth=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable-v21/ic_menu_share.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportHeight=\"24.0\"\n    android:viewportWidth=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/drawable-v21/ic_menu_slideshow.xml",
    "content": "<vector xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:width=\"24dp\"\n    android:height=\"24dp\"\n    android:viewportHeight=\"24.0\"\n    android:viewportWidth=\"24.0\">\n    <path\n        android:fillColor=\"#FF000000\"\n        android:pathData=\"M4,6H2v14c0,1.1 0.9,2 2,2h14v-2H4V6zm16,-4H8c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h12c1.1,0 2,-0.9 2,-2V4c0,-1.1 -0.9,-2 -2,-2zm-8,12.5v-9l6,4.5 -6,4.5z\" />\n</vector>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_about.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    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/main_content\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <android.support.design.widget.AppBarLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"@dimen/about_header_height\"\n        android:theme=\"@style/ThemeOverlay.AppCompat.Dark.ActionBar\">\n\n        <android.support.design.widget.CollapsingToolbarLayout\n            android:id=\"@+id/about_collapsing_tool\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            app:contentScrim=\"?attr/colorPrimary\"\n            app:expandedTitleTextAppearance=\"@style/CollapsingToolbarTitleStyle\"\n            app:layout_scrollFlags=\"scroll|exitUntilCollapsed\">\n\n\n            <LinearLayout\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                android:background=\"@color/colorPrimary\"\n                android:gravity=\"center\"\n                android:orientation=\"vertical\">\n\n                <ImageView\n                    android:layout_width=\"96dp\"\n                    android:layout_height=\"96dp\"\n                    android:layout_marginTop=\"24dp\"\n                    android:src=\"@mipmap/h\" />\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginTop=\"8dp\"\n                    android:gravity=\"center\"\n                    android:text=\"@string/app_introduce\"\n                    android:textColor=\"@color/white\"\n                    android:textSize=\"18sp\" />\n\n                <TextView\n                    android:id=\"@+id/tv_version\"\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_marginTop=\"8dp\"\n                    android:textColor=\"@color/white\"\n                    android:textSize=\"14sp\"\n                    tools:text=\"Version 1.0.0\" />\n            </LinearLayout>\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=\"@android:color/transparent\"\n                app:layout_collapseMode=\"pin\" />\n\n        </android.support.design.widget.CollapsingToolbarLayout>\n    </android.support.design.widget.AppBarLayout>\n\n    <android.support.v4.widget.NestedScrollView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"\n        app:layout_behavior=\"@string/appbar_scrolling_view_behavior\">\n\n\n        <LinearLayout\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:orientation=\"vertical\"\n            android:padding=\"@dimen/about_padding\">\n\n            <TextView\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:textSize=\"16sp\"\n                android:text=\"项目介绍\" />\n\n            <android.support.v7.widget.CardView\n                android:layout_margin=\"@dimen/about_text_margin\"\n                android:layout_marginTop=\"@dimen/about_padding\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                app:cardCornerRadius=\"4dp\"\n                app:cardElevation=\"4dp\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_margin=\"@dimen/about_text_margin\"\n                    android:text=\"@string/introduce\" />\n            </android.support.v7.widget.CardView>\n\n\n\n            <TextView\n                android:layout_marginTop=\"20dp\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:textSize=\"16sp\"\n                android:text=\"关于我\" />\n\n            <android.support.v7.widget.CardView\n                android:layout_margin=\"@dimen/about_text_margin\"\n                android:layout_marginTop=\"@dimen/about_padding\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                app:cardCornerRadius=\"4dp\"\n                app:cardElevation=\"4dp\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_margin=\"@dimen/about_text_margin\"\n                    android:lineSpacingExtra=\"2dp\"\n                    android:text=\"@string/about_me\" />\n            </android.support.v7.widget.CardView>\n\n\n            <TextView\n                android:layout_marginTop=\"20dp\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:textSize=\"16sp\"\n                android:text=\"用到的第三方库\" />\n\n            <android.support.v7.widget.CardView\n                android:layout_margin=\"@dimen/about_text_margin\"\n                android:layout_marginTop=\"@dimen/about_padding\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"wrap_content\"\n                app:cardCornerRadius=\"4dp\"\n                app:cardElevation=\"4dp\">\n\n                <TextView\n                    android:layout_width=\"wrap_content\"\n                    android:layout_height=\"wrap_content\"\n                    android:layout_margin=\"@dimen/about_text_margin\"\n                    android:text=\"@string/app_store\" />\n            </android.support.v7.widget.CardView>\n\n\n\n        </LinearLayout>\n    </android.support.v4.widget.NestedScrollView>\n\n\n</android.support.design.widget.CoordinatorLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_main.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    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:id=\"@+id/drawer_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    android:fitsSystemWindows=\"true\"\n    tools:openDrawer=\"start\">\n\n    <include\n        layout=\"@layout/app_bar_main\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\" />\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_main\"\n        app:menu=\"@menu/activity_main_drawer\" />\n\n</android.support.v4.widget.DrawerLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_search.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:orientation=\"vertical\"\n    android:layout_height=\"match_parent\">\n\n    <include layout=\"@layout/layout_toolbar_view\"></include>\n    <FrameLayout\n        android:id=\"@+id/container\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n    </FrameLayout>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/activity_web.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\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:orientation=\"vertical\">\n\n    <include layout=\"@layout/layout_toolbar_view\"></include>\n\n    <ProgressBar\n        android:id=\"@+id/progress_bar\"\n        style=\"?android:progressBarStyleHorizontal\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"3dp\"\n        android:max=\"100\"\n        android:progressDrawable=\"@drawable/progress_bar_bg\" />\n\n    <WebView\n        android:id=\"@+id/webView\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\"></WebView>\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/app_bar_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    xmlns:tools=\"http://schemas.android.com/tools\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\"\n    tools:context=\".ui.main.MainActivity\">\n\n    <android.support.design.widget.AppBarLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        app:elevation=\"@dimen/app_bar_default_elevation\"\n        android:theme=\"@style/AppTheme.AppBarOverlay\">\n\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/AppTheme.PopupOverlay\"/>\n\n\n\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:tabGravity=\"fill\"\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    <com.miguelcatalan.materialsearchview.MaterialSearchView\n        android:id=\"@+id/search_view\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:visibility=\"visible\" />\n</android.support.design.widget.CoordinatorLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_item.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\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:background=\"@android:color/white\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:visibility=\"gone\"\n        android:id=\"@+id/llyt_network\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_above=\"@+id/app_bar_layout\"\n        android:background=\"@color/network_bg\"\n        android:gravity=\"center_vertical\"\n        android:orientation=\"horizontal\"\n        android:paddingBottom=\"@dimen/padding_top\"\n        android:paddingLeft=\"@dimen/padding_left\"\n        android:paddingRight=\"@dimen/padding_left\"\n        android:paddingTop=\"@dimen/padding_top\">\n\n        <ImageView\n            android:layout_width=\"25dp\"\n            android:layout_height=\"25dp\"\n            android:src=\"@drawable/network_error\" />\n\n        <TextView\n            android:layout_width=\"0dp\"\n            android:layout_height=\"wrap_content\"\n            android:layout_marginLeft=\"@dimen/padding_top\"\n            android:layout_marginRight=\"@dimen/padding_top\"\n            android:layout_weight=\"1\"\n            android:text=\"@string/network_error\" />\n\n        <ImageView\n            android:id=\"@+id/img_delete\"\n            android:layout_width=\"15dp\"\n            android:layout_height=\"15dp\"\n            android:src=\"@drawable/delete\" />\n    </LinearLayout>\n\n    <com.wkw.common_lib.widget.ProgressLayout\n        android:id=\"@+id/progress_layout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <android.support.v4.widget.SwipeRefreshLayout\n            android:id=\"@+id/swipe_refresh_layout\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n            <android.support.v7.widget.RecyclerView\n                android:id=\"@+id/recycler_view\"\n                android:layout_width=\"match_parent\"\n                android:layout_height=\"match_parent\"></android.support.v7.widget.RecyclerView>\n\n        </android.support.v4.widget.SwipeRefreshLayout>\n\n    </com.wkw.common_lib.widget.ProgressLayout>\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/fragment_list.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<com.wkw.common_lib.widget.ProgressLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/progress_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <android.support.v4.widget.SwipeRefreshLayout\n        android:id=\"@id/swipe_refresh_layout\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"match_parent\">\n\n        <com.wkw.common_lib.widget.loadmore.RecyclerViewWithFooter\n            android:id=\"@+id/recycler_view\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\">\n\n        </com.wkw.common_lib.widget.loadmore.RecyclerViewWithFooter>\n    </android.support.v4.widget.SwipeRefreshLayout>\n\n</com.wkw.common_lib.widget.ProgressLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/layout_item.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:id=\"@+id/card_view\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    app:cardElevation=\"4dp\"\n    android:layout_margin=\"8dp\">\n\n    <LinearLayout\n        android:padding=\"5dp\"\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:orientation=\"horizontal\">\n\n        <ImageView\n            android:id=\"@+id/img_item\"\n            android:layout_width=\"120dp\"\n            android:layout_height=\"80dp\" />\n\n        <LinearLayout\n            android:layout_marginLeft=\"10dp\"\n            android:layout_width=\"match_parent\"\n            android:layout_height=\"match_parent\"\n            android:orientation=\"vertical\">\n\n            <TextView\n                android:textSize=\"18sp\"\n                android:id=\"@+id/tv_title\"\n                android:lines=\"2\"\n                android:ellipsize=\"end\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"wue\" />\n\n            <TextView\n                android:id=\"@+id/tv_date\"\n                android:layout_width=\"wrap_content\"\n                android:layout_height=\"wrap_content\"\n                android:text=\"wue\" />\n\n        </LinearLayout>\n    </LinearLayout>\n</android.support.v7.widget.CardView>\n"
  },
  {
    "path": "app/src/main/res/layout/layout_toolbar_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<android.support.design.widget.AppBarLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\"\n    android:id=\"@+id/app_bar_layout\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:theme=\"@style/AppTheme.AppBarOverlay\"\n    app:elevation=\"3dp\">\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/AppTheme.PopupOverlay\">\n\n    </android.support.v7.widget.Toolbar>\n</android.support.design.widget.AppBarLayout>\n"
  },
  {
    "path": "app/src/main/res/layout/nav_header_main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"@dimen/nav_header_height\"\n    android:background=\"@color/colorPrimary\"\n    android:gravity=\"bottom\"\n    android:orientation=\"vertical\"\n    android:paddingBottom=\"@dimen/activity_vertical_margin\"\n    android:paddingLeft=\"@dimen/activity_horizontal_margin\"\n    android:paddingRight=\"@dimen/activity_horizontal_margin\"\n    android:paddingTop=\"@dimen/activity_vertical_margin\"\n    android:theme=\"@style/ThemeOverlay.AppCompat.Dark\">\n\n    <ImageView\n        android:id=\"@+id/imageView\"\n        android:layout_width=\"50dp\"\n        android:layout_height=\"50dp\"\n        android:paddingTop=\"@dimen/nav_header_vertical_spacing\"\n        android:src=\"@mipmap/h\" />\n\n    <TextView\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:paddingTop=\"@dimen/nav_header_vertical_spacing\"\n        android:text=\"微信头条分享\"\n        android:textAppearance=\"@style/TextAppearance.AppCompat.Body1\" />\n\n    <TextView\n        android:id=\"@+id/textView\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:text=\"@string/github\" />\n\n</LinearLayout>\n"
  },
  {
    "path": "app/src/main/res/menu/activity_main_drawer.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\">\n\n    <group android:checkableBehavior=\"single\">\n        <item\n            android:id=\"@+id/nav_sports\"\n            android:icon=\"@drawable/sports\"\n            android:title=\"体育\" />\n        <item\n            android:id=\"@+id/nav_about\"\n            android:icon=\"@drawable/about\"\n            android:title=\"关于\" />\n        <item\n            android:id=\"@+id/nav_slideshow\"\n            android:icon=\"@drawable/ic_menu_slideshow\"\n            android:title=\"Slideshow\" />\n        <item\n            android:id=\"@+id/nav_manage\"\n            android:icon=\"@drawable/ic_menu_manage\"\n            android:title=\"Tools\" />\n    </group>\n\n    <item android:title=\"Communicate\">\n        <menu>\n            <item\n                android:id=\"@+id/nav_share\"\n                android:icon=\"@drawable/ic_menu_share\"\n                android:title=\"Share\" />\n            <item\n                android:id=\"@+id/nav_send\"\n                android:icon=\"@drawable/ic_menu_send\"\n                android:title=\"Send\" />\n        </menu>\n    </item>\n\n</menu>\n"
  },
  {
    "path": "app/src/main/res/menu/main.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<menu xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n    <item\n        android:id=\"@+id/action_search\"\n        android:icon=\"@drawable/ic_action_action_search\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/abc_search_hint\"\n        app:showAsAction=\"always\" />\n</menu>\n"
  },
  {
    "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    xmlns:app=\"http://schemas.android.com/apk/res-auto\">\n\n    <item\n        android:id=\"@+id/action_cory_url\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/cory_url\"\n        app:showAsAction=\"never\" />\n\n    <item\n        android:id=\"@+id/action_other_browser\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/other_browser\"\n        app:showAsAction=\"never\" />\n\n    <item\n        android:id=\"@+id/action_share\"\n        android:orderInCategory=\"100\"\n        android:title=\"@string/share\"\n        app:showAsAction=\"never\" />\n</menu>\n"
  },
  {
    "path": "app/src/main/res/values/arrays.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <string-array name=\"query_suggestions\">\n        <item>科技</item>\n        <item>美女</item>\n        <item>生活</item>\n        <item>娱乐</item>\n        <item>搞笑</item>\n        <item>宅男</item>\n    </string-array>\n</resources>"
  },
  {
    "path": "app/src/main/res/values/colors.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n    <color name=\"colorPrimary\">#3F51B5</color>\n    <color name=\"colorPrimaryDark\">#303F9F</color>\n    <color name=\"colorAccent\">#FF4081</color>\n    <color name=\"network_bg\">#EED6CC</color>\n    <color name=\"white\">#FFFFFF</color>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"nav_header_vertical_spacing\">16dp</dimen>\n    <dimen name=\"nav_header_height\">160dp</dimen>\n    <!-- Default screen margins, per the Android Design guidelines. -->\n    <dimen name=\"activity_horizontal_margin\">16dp</dimen>\n    <dimen name=\"activity_vertical_margin\">16dp</dimen>\n    <dimen name=\"fab_margin\">16dp</dimen>\n    <dimen name=\"padding_top\">8dp</dimen>\n    <dimen name=\"padding_left\">18dp</dimen>\n    <dimen name=\"about_header_height\">230dp</dimen>\n    <dimen name=\"about_padding\">12dp</dimen>\n    <dimen name=\"about_text_margin\">8dp</dimen>\n    <dimen name=\"app_bar_default_elevation\">0dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/drawables.xml",
    "content": "<resources xmlns:android=\"http://schemas.android.com/apk/res/android\">\n    <item name=\"ic_menu_camera\" type=\"drawable\">@android:drawable/ic_menu_camera</item>\n    <item name=\"ic_menu_gallery\" type=\"drawable\">@android:drawable/ic_menu_gallery</item>\n    <item name=\"ic_menu_slideshow\" type=\"drawable\">@android:drawable/ic_menu_slideshow</item>\n    <item name=\"ic_menu_manage\" type=\"drawable\">@android:drawable/ic_menu_manage</item>\n    <item name=\"ic_menu_share\" type=\"drawable\">@android:drawable/ic_menu_share</item>\n    <item name=\"ic_menu_send\" type=\"drawable\">@android:drawable/ic_menu_send</item>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">Hot</string>\n\n    <string name=\"navigation_drawer_open\">Open navigation drawer</string>\n    <string name=\"navigation_drawer_close\">Close navigation drawer</string>\n\n    <string name=\"action_settings\">Settings</string>\n    <string name=\"action_about\">关于</string>\n    <string name=\"github\">https://github.com/zj-wukewei/Hot</string>\n    <string name=\"network_error\">网络不可用,请检查网络设置</string>\n    <string name=\"app_introduce\">头条&amp;Hot - 每日热门分享</string>\n    <string name=\"other_browser\">用浏览器打开</string>\n    <string name=\"cory_url\">复杂链接</string>\n    <string name=\"share\">分享</string>\n    <string name=\"search\">请输入搜索类型</string>\n    <string name=\"share_title\">微信热门分享</string>\n\n    <string name=\"about_me\">我是个毕业于三流的本科学校,还是个android小菜鸟,通过不断的学习和不断的看些大牛的源码进行成长,代码之路还很遥远还要不断的努力,希望通过自己的不断学习能早日的入android的门</string>\n    <string name=\"app_store\">\n            \"com.android.support:appcompat-v7:23.2.0\"\\n\n            \"com.android.support:design:23.2.0\"\\n\n            \"com.android.support:cardview-v7:23.2.0\"\\n\n            \"com.android.support:recyclerview-v7:23.2.0\"\\n\n            \"com.squareup.retrofit2:retrofit:2.0.2\"\\n\n            \"com.squareup.okhttp3:logging-interceptor:3.3.0\"\\n\n            \"io.reactivex:rxandroid:1.2.0\"\\n\n            \"com.squareup.retrofit2:converter-gson:2.0.2\"\\n\n            \"com.squareup.retrofit2:adapter-rxjava:2.0.2\"\\n\n            \"com.google.showapi_res_code.gson:gson:2.6.2\"\\n\n            \"com.github.bumptech.glide:glide:3.7.0\"\\n\n            \"com.jakewharton:butterknife:7.0.1\"\\n\n            \"com.google.dagger:dagger:2.0\"\\n\n            \"com.google.dagger:dagger-compiler:2.0\"\\n\n            \"org.glassfish:javax.annotation:10.0-b28\"\n    </string>\n    <string name=\"introduce\">这是一个关于微信热门头条分享的app,每天都会更新不同的热门分享\\n\\n数据来源于百度开放者平台的api,只要去申请\n    个apikey即可,里面有很多其它api可以供大家使用\\n\\n 项目采用的技术是 MVP+Rxjava+Retrofit+Dagger2来实现的,这个项目是我在学习新的技术\n        的时候来练习的一个项目,我像一个产品级的app来对待的\\n\\n本项目中common_lib下的有些是参考大帅的代码,这里非常的感谢大神的开源项目,让我学习到了很多\\n\\n\n    项目Github地址:https://github.com/zj-wukewei/Hot欢迎star</string>\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        <!-- Customize your theme here. -->\n        <item name=\"colorPrimary\">@color/colorPrimary</item>\n        <item name=\"colorPrimaryDark\">@color/colorPrimaryDark</item>\n        <item name=\"colorAccent\">@color/colorAccent</item>\n    </style>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n    </style>\n\n    <style name=\"AppTheme.AppBarOverlay\" parent=\"ThemeOverlay.AppCompat.Dark.ActionBar\" />\n\n    <style name=\"AppTheme.PopupOverlay\" parent=\"ThemeOverlay.AppCompat.Light\" />\n\n    <style name=\"CollapsingToolbarTitleStyle\"\n        parent=\"@android:style/TextAppearance\">\n        <item name=\"android:textColor\">@android:color/transparent</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-v21/styles.xml",
    "content": "<resources>\n\n    <style name=\"AppTheme.NoActionBar\">\n        <item name=\"windowActionBar\">false</item>\n        <item name=\"windowNoTitle\">true</item>\n        <item name=\"android:windowDrawsSystemBarBackgrounds\">true</item>\n        <item name=\"android:statusBarColor\">@android:color/transparent</item>\n    </style>\n</resources>\n"
  },
  {
    "path": "app/src/main/res/values-w820dp/dimens.xml",
    "content": "<resources>\n    <!-- Example customization of dimensions originally defined in res/values/dimens.xml\n         (such as screen margins) for screens with more than 820dp of available width. This\n         would include 7\" and 10\" devices in landscape (~960dp and ~1280dp respectively). -->\n    <dimen name=\"activity_horizontal_margin\">64dp</dimen>\n</resources>\n"
  },
  {
    "path": "app/src/test/java/com/wkw/hot/ExampleUnitTest.java",
    "content": "package com.wkw.hot;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "build.gradle",
    "content": "// Top-level build file where you can add configuration options common to all sub-projects/modules.\napply from: \"version.gradle\"\nbuildscript {\n    repositories {\n        jcenter()\n    }\n    dependencies {\n        classpath 'com.android.tools.build:gradle:2.2.2'\n        classpath 'com.neenbedankt.gradle.plugins:android-apt:1.8'\n        classpath 'me.tatarka:gradle-retrolambda:3.2.0'\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        mavenLocal()\n        jcenter()\n        maven {\n            // All of React Native (JS, Android binaries) is installed from npm\n            url \"$rootDir/node_modules/react-native/android\"\n        }\n    }\n}\n\ntask clean(type: Delete) {\n    delete rootProject.buildDir\n}\n"
  },
  {
    "path": "common_lib/.gitignore",
    "content": "/build\n"
  },
  {
    "path": "common_lib/build.gradle",
    "content": "apply plugin: 'com.android.library'\n\nandroid {\n    compileSdkVersion rootProject.ext.android.compileSdkVersion\n    buildToolsVersion rootProject.ext.android.buildToolsVersion\n\n    defaultConfig {\n        minSdkVersion rootProject.ext.android.minSdkVersion\n        targetSdkVersion rootProject.ext.android.targetSdkVersion\n        versionCode rootProject.ext.android.versionCode\n        versionName rootProject.ext.android.versionName\n    }\n    buildTypes {\n        release {\n            minifyEnabled false\n            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'\n        }\n    }\n}\n\ndependencies {\n    compile fileTree(dir: 'libs', include: ['*.jar'])\n    testCompile 'junit:junit:4.12'\n    compile rootProject.ext.dependencies[\"appcompat-v7\"]\n    compile rootProject.ext.dependencies[\"recyclerview-v7\"]\n    compile rootProject.ext.dependencies[\"glide\"]\n    compile rootProject.ext.dependencies[\"rxandroid\"]\n}\n"
  },
  {
    "path": "common_lib/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/wukewei/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": "common_lib/src/androidTest/java/com/wkw/common_lib/ApplicationTest.java",
    "content": "package com.wkw.common_lib;\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": "common_lib/src/main/AndroidManifest.xml",
    "content": "<manifest xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    package=\"com.wkw.common_lib\">\n\n    <uses-permission android:name=\"android.permission.ACCESS_WIFI_STATE\" />\n    <application\n        android:allowBackup=\"true\"\n        android:label=\"@string/app_name\"\n        android:supportsRtl=\"true\">\n\n    </application>\n\n</manifest>\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/Ext.java",
    "content": "package com.wkw.common_lib;\n\nimport android.app.Application;\nimport android.content.Context;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.util.Log;\n\n/**\n * Created by wukewei on 16/7/24.\n */\npublic abstract class Ext {\n    private static final String TAG = \"Ext\";\n\n    private static Context sContext = null;\n    private static Application sApplication = null;\n\n    private static String sPackageName;\n    private static String sVersionName;\n    private static String sBuildNumber;\n    private static int sVersionCode = 0;\n\n    private static Ext sInstance = null;\n\n    public static Ext g() {\n        if (sInstance == null) {\n            throw new RuntimeException(\"Ext 没有初始化!\");\n        }\n        return sInstance;\n    }\n\n    public static void init(Application app, Ext instance) {\n        sContext = app.getApplicationContext();\n        sApplication = app;\n        sInstance = instance;\n        sPackageName = sApplication.getPackageName();\n        initVersionCodeAndName(sApplication);\n    }\n\n    private static void initVersionCodeAndName(Context context) {\n        String version = \"\";\n        try {\n            PackageInfo info = context.getPackageManager().getPackageInfo(sPackageName, 0);\n            sVersionCode = info.versionCode;\n            version = info.versionName;\n        } catch (PackageManager.NameNotFoundException e) {\n            Log.e(TAG, \"initVersionCodeAndName\");\n        }\n        sVersionName = version.substring(0, version.lastIndexOf('.'));\n        sBuildNumber = version.substring(version.lastIndexOf('.') + 1, version.length());\n    }\n\n    public static Context getContext() {\n        return sContext;\n    }\n\n    public static Application getApplication() {\n        return sApplication;\n    }\n\n    public abstract String getCurOpenId();\n\n    public abstract String getDeviceInfo();\n\n    public abstract String getPackageNameForResource();\n\n    public String getPackageName() {\n        return sPackageName;\n    }\n\n    public int getVersionCode() {\n        return sVersionCode;\n    }\n\n    public String getVersionName() {\n        return sVersionName;\n    }\n\n    public String getBuilderNumber() {\n        return sBuildNumber;\n    }\n\n    public abstract int getScreenHeight();\n\n    public abstract int getScreenWidth();\n\n    // Network\n    public abstract boolean isAvailable();\n\n    public abstract boolean isWap();\n\n    public abstract boolean isMobile();\n\n    public abstract boolean is2G();\n\n    public abstract boolean is3G();\n\n    public abstract boolean isWifi();\n\n    public abstract boolean isEthernet();\n\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/image/ImageConfig.java",
    "content": "package com.wkw.common_lib.image;\n\nimport android.widget.ImageView;\n\n/**\n * Created by wukewei on 16/12/22.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class ImageConfig {\n\n    protected ImageView imageView;\n    protected String url;\n    protected int placeholder;\n    protected int errorPic;\n\n\n    public String getUrl() {\n        return url;\n    }\n\n\n    public ImageView getImageView() {\n        return imageView;\n    }\n\n\n    public int getPlaceholder() {\n        return placeholder;\n    }\n\n\n    public int getErrorPic() {\n        return errorPic;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/image/ImageLoader.java",
    "content": "package com.wkw.common_lib.image;\n\nimport android.content.Context;\nimport com.wkw.common_lib.image.glide.GlideImageConfig;\n\nimport static com.wkw.common_lib.image.glide.GlideImageConfig.*;\n\n/**\n * Created by wukewei on 16/12/22.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class ImageLoader {\n\n    private ImageLoaderStrategy mImageLoaderStrategy;\n\n    public ImageLoader() {\n    }\n\n\n    public void setImageLoaderStragety(ImageLoaderStrategy imageLoaderStrategy) {\n        this.mImageLoaderStrategy = imageLoaderStrategy;\n    }\n\n\n    public <T extends ImageConfig> void  displayImage(Context context, T config) {\n        this.mImageLoaderStrategy.loadImage(context, config);\n    }\n\n\n\n    public static ImageLoader getInstance() {\n        return ImageLoaderInstance.mImageLoader;\n    }\n\n\n    public static class ImageLoaderInstance {\n        private final static ImageLoader mImageLoader = new ImageLoader();\n    }\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/image/ImageLoaderStrategy.java",
    "content": "package com.wkw.common_lib.image;\n\nimport android.content.Context;\n\n/**\n * Created by wukewei on 16/12/22.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic interface ImageLoaderStrategy<T extends ImageConfig> {\n    void loadImage(Context context, T t);\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/image/glide/GlideImageConfig.java",
    "content": "package com.wkw.common_lib.image.glide;\n\nimport android.widget.ImageView;\nimport com.wkw.common_lib.image.ImageConfig;\n\n/**\n * Created by wukewei on 16/12/22.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class GlideImageConfig extends ImageConfig {\n    private int cacheStrategy;\n\n\n    public GlideImageConfig(Builder builder) {\n        this.url = builder.url;\n        this.imageView = builder.imageView;\n        this.placeholder = builder.placeholder;\n        this.errorPic = builder.errorPic;\n        this.cacheStrategy = builder.cacheStrategy;\n    }\n\n\n    public int getCacheStrategy() {\n        return cacheStrategy;\n    }\n\n\n    public void setCacheStrategy(int cacheStrategy) {\n        this.cacheStrategy = cacheStrategy;\n    }\n\n    public static Builder builder() {\n        return new Builder();\n    }\n\n    public static final class Builder {\n        private String url;\n        private ImageView imageView;\n        private int placeholder;\n        private int errorPic;\n        private int cacheStrategy;//0对应DiskCacheStrategy.all,1对应DiskCacheStrategy.NONE,2对应DiskCacheStrategy.SOURCE,3对应DiskCacheStrategy.RESULT\n\n        private Builder() {\n        }\n\n        public Builder url(String url) {\n            this.url = url;\n            return this;\n        }\n\n        public Builder placeholder(int placeholder) {\n            this.placeholder = placeholder;\n            return this;\n        }\n\n        public Builder errorPic(int errorPic){\n            this.errorPic = errorPic;\n            return this;\n        }\n\n        public Builder imagerView(ImageView imageView) {\n            this.imageView = imageView;\n            return this;\n        }\n\n        public Builder cacheStrategy(int cacheStrategy) {\n            this.cacheStrategy = cacheStrategy;\n            return this;\n        }\n\n\n        public GlideImageConfig build() {\n            if (url == null) throw new IllegalStateException(\"url is required\");\n            if (imageView == null) throw new IllegalStateException(\"imageview is required\");\n            return new GlideImageConfig(this);\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/image/glide/GlideImageLoaderStrategy.java",
    "content": "package com.wkw.common_lib.image.glide;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport com.bumptech.glide.DrawableRequestBuilder;\nimport com.bumptech.glide.Glide;\nimport com.bumptech.glide.RequestManager;\nimport com.bumptech.glide.load.engine.DiskCacheStrategy;\nimport com.wkw.common_lib.image.ImageLoaderStrategy;\n\n/**\n * Created by wukewei on 16/12/22.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class GlideImageLoaderStrategy implements ImageLoaderStrategy<GlideImageConfig> {\n\n    @Override public void loadImage(Context context, GlideImageConfig imageConfig) {\n        RequestManager manager;\n        if (context instanceof Activity) {\n            manager = Glide.with((Activity) context);\n        } else {\n            manager = Glide.with(context);\n        }\n\n        DrawableRequestBuilder<String> request = manager.load(imageConfig.getUrl())\n            .crossFade()\n            .centerCrop();\n        switch (imageConfig.getCacheStrategy()) {\n            case 0:\n                request.diskCacheStrategy(DiskCacheStrategy.ALL);\n                break;\n            case 1:\n                request.diskCacheStrategy(DiskCacheStrategy.NONE);\n                break;\n            case 2:\n                request.diskCacheStrategy(DiskCacheStrategy.SOURCE);\n                break;\n            case 3:\n                request.diskCacheStrategy(DiskCacheStrategy.RESULT);\n                break;\n            default:\n                break;\n        }\n\n        if (imageConfig.getPlaceholder() != 0) {\n            request.placeholder(imageConfig.getPlaceholder());\n        }\n        if (imageConfig.getErrorPic() != 0) {\n            request.error(imageConfig.getErrorPic());\n        }\n\n        request.into(imageConfig.getImageView());\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/AccessPoint.java",
    "content": "package com.wkw.common_lib.network;\n\nimport com.wkw.common_lib.utils.StringUtils;\n\nimport java.util.HashMap;\n\n/**\n * Created by wukewei on 16/7/25.\n */\nenum  AccessPoint {\n    /**\n     * 接入点不可用，通常是无网络或者非移动网络\n     */\n    NONE(StringUtils.EMPTY, ServiceProvider.NONE, false),\n    /**\n     * 未知的接入点\n     */\n    NEVER_HEARD(\"I don't know\", ServiceProvider.NEVER_HEARD, false), // 未知接入点\n    /**\n     * 中国移动 cmnet\n     */\n    CMNET(\"cmnet\", ServiceProvider.CHINA_MOBILE, false), // 中国移动 NET\n    /**\n     * 中国移动 cmwap\n     */\n    CMWAP(\"cmwap\", ServiceProvider.CHINA_MOBILE, true), // 中国移动 WAP\n    /**\n     * 中国联通 2G uninet\n     */\n    UNINET(\"uninet\", ServiceProvider.CHINA_UNICOM, false), // 中国联通 2G NET\n    /**\n     * 中国联通 2G uniwap\n     */\n    UNIWAP(\"uniwap\", ServiceProvider.CHINA_UNICOM, true), // 中国联通 2G WAP\n    /**\n     * 中国联通 3G 3gnet\n     */\n    _3GNET(\"3gnet\", ServiceProvider.CHINA_UNICOM, false), // 中国联通 3G NET\n    /**\n     * 中国联通 3G 3gwap\n     */\n    _3GWAP(\"3gwap\", ServiceProvider.CHINA_UNICOM, true), // 中国联通 3G WAP\n    /**\n     * 中国电信 ctnet\n     */\n    CTNET(\"ctnet\", ServiceProvider.CHINA_TELECOM, false), // 中国电信 NET\n    /**\n     * 中国电信 ctwap\n     */\n    CTWAP(\"ctwap\", ServiceProvider.CHINA_TELECOM, true), // 中国电信 WAP\n    /**\n     * 中国电信 #777\n     */\n    SHARP777(\"#777\", ServiceProvider.CHINA_TELECOM, false), // 中国电信 #777\n    ;\n\n    private static HashMap<String, AccessPoint> ACCESS_POINT_MAP = new HashMap<String, AccessPoint>();\n\n    static {\n        // 初始化所有已知的接入点\n        for (AccessPoint accessPoint : AccessPoint.values()) {\n            ACCESS_POINT_MAP.put(accessPoint.getName(), accessPoint);\n        }\n    }\n\n    private String name;\n    private ServiceProvider provider;\n    private boolean wap;\n\n    AccessPoint(String name, ServiceProvider provider, boolean isWap) {\n        setName(name);\n        setProvider(provider);\n        setWap(isWap);\n    }\n\n    /**\n     * 获得对应的接入点对象\n     *\n     * @param name 接入点名称\n     * @return 接入点枚举对象<br>\n     * <br>\n     * 如果名称为空，得到{@link AccessPoint}.NONE<br>\n     * 如果并非此枚举中的范围，得到{@link AccessPoint}.NEVER_HEARD\n     */\n    public static AccessPoint forName(String name) {\n        if (name == null) {\n            return NONE;\n        }\n\n        AccessPoint accessPoint = ACCESS_POINT_MAP.get(name.toLowerCase());\n\n        return ((accessPoint == null) ? NEVER_HEARD : accessPoint);\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    /**\n     * 获取接入点所属于的服务运营商\n     *\n     * @return 运营商枚举\n     */\n    public ServiceProvider getProvider() {\n        return provider;\n    }\n\n    public void setProvider(ServiceProvider provider) {\n        this.provider = provider;\n    }\n\n    /**\n     * 判断是否是WAP接入点\n     *\n     * @return 是否是WAP接入点\n     */\n    public boolean isWap() {\n        return wap;\n    }\n\n    public void setWap(boolean wap) {\n        this.wap = wap;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/Network.java",
    "content": "package com.wkw.common_lib.network;\n\nimport android.support.annotation.RequiresPermission;\n\nimport com.wkw.common_lib.Ext;\nimport com.wkw.common_lib.utils.NetWorkUtils;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic class Network extends NetworkDash {\n    /**\n     * 系统代理信息\n     */\n    public static abstract class Proxy {\n        public static int getPort() {\n            return android.net.Proxy.getDefaultPort();\n        }\n\n        public static String getHost() {\n            return android.net.Proxy.getDefaultHost();\n        }\n    }\n\n    /**\n     * WIFI网卡信息\n     */\n    public static class Wifi extends WifiDash {\n\n    }\n\n    public static class Dns {\n        @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)\n        public static NetWorkUtils.DNS getDNS() {\n            return NetWorkUtils.getDNS(Ext.getContext());\n        }\n    }\n}"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/NetworkDash.java",
    "content": "package com.wkw.common_lib.network;\n\nimport android.content.Context;\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\nimport android.os.Handler;\nimport android.telephony.TelephonyManager;\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.wkw.common_lib.Ext;\nimport com.wkw.common_lib.utils.NetWorkUtils;\nimport com.wkw.common_lib.utils.StringUtils;\n\nimport java.lang.ref.WeakReference;\nimport java.lang.reflect.Method;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/7/25.\n */\nclass NetworkDash {\n    private static final String TAG = \"NetworkDash\";\n    private static final List<WeakReference<NetworkStateListener>> OBSERVER_LIST = new ArrayList<WeakReference<NetworkStateListener>>();\n    private static NetworkState currState;\n    private static NetworkState lastState;\n    private static Handler mainHandler;\n\n    /**\n     * IMSI的运营商，为了减少IPC通信，只在网络变更的时候更新它\n     */\n    private static ServiceProvider imsiProvider = null;\n    private static final NetworkObserver OBSERVER = new NetworkObserver() {\n        @Override\n        public void onNetworkChanged() {\n            updateNetworkState();\n        }\n\n    };\n\n    static {\n        // 初始化当前网络状态\n        updateNetworkState();\n        // 开始监听网络变化\n        OBSERVER.startListen();\n    }\n\n    /**\n     * 判断当前网络是否可用，这将刷新当前网络信息\n     *\n     * @return 网络是否已经连接上\n     */\n    public static boolean isAvailable() {\n        updateNetworkState();\n\n        NetworkState state = getCurrState();\n\n        return state != null && state.isConnected();\n    }\n\n    /**\n     * 比 {@link #isAvailable()}快\n     *\n     * @return 网络是否已经连接上\n     */\n    public static boolean isAvailableFast() {\n        NetworkState state = getCurrState();\n        return state != null && state.isConnected();\n    }\n\n    /**\n     * 获得当前移动网络的接入点<br>\n     * <br>\n     * 如果无网络/并非移动网络，得到{@link AccessPoint}.NONE<br>\n     * 如果并非{@link AccessPoint}枚举中的范围，得到{@link AccessPoint}.NEVER_HEARD\n     *\n     * @return 接入点枚举\n     * @see AccessPoint\n     */\n    public static AccessPoint getAccessPoint() {\n        NetworkState state = getCurrState();\n\n        if (state != null) {\n            return state.getAccessPoint();\n        } else {\n            return AccessPoint.NONE;\n        }\n    }\n\n    /**\n     * 获得当前本地IP\n     */\n    public static String getLocalIP() {\n        return NetWorkUtils.getLocalIP();\n    }\n\n    /**\n     * 获得当前的网络类型\n     *\n     * @return 网络类型枚举\n     * @see NetworkType\n     */\n    public static NetworkType getType() {\n        NetworkState state = getCurrState();\n\n        if (state != null) {\n            return state.getType();\n        } else {\n            return NetworkType.NONE;\n        }\n    }\n\n    /**\n     * 获得当前的接入点名称\n     * <p/>\n     * 建议只在需要未知接入点或者具体接入点名称时使用，若要对接入点进行逻辑分支，\n     * 请使用getAccessPoint()方法\n     *\n     * @return 接入点名称\n     * @see AccessPoint\n     */\n    public static String getApnName() {\n        NetworkState state = getCurrState();\n\n        if (state != null) {\n            return state.getApnName();\n        } else {\n            return StringUtils.EMPTY;\n        }\n    }\n\n    /**\n     * 获得接入点名字或者\"wifi\"字样\n     *\n     * @return 接入点名字或者\"wifi\"\n     */\n    public static String getApnNameOrWifi() {\n        if (!isAvailable()) {\n            return StringUtils.EMPTY;\n        } else {\n            if (isWifi()) {\n                return \"wifi\";\n            } else {\n                return getApnName();\n            }\n        }\n    }\n\n    /**\n     * 获得接入点名字或者\"wifi\"字样或者\"ethernet\"字样\n     */\n    public static String getApnNameOrWifiOrEthernet() {\n        if (!isAvailable()) {\n            return StringUtils.EMPTY;\n        } else {\n            if (isWifi()) {\n                return \"wifi\";\n            } else if (isEthernet()) {\n                return \"ethernet\";\n            } else {\n                return getApnName();\n            }\n        }\n    }\n\n    /**\n     * 获得当前的运营商，使用APN\n     *\n     * @return 运营商\n     * @see ServiceProvider\n     */\n    public static ServiceProvider getProvider() {\n        NetworkState state = getCurrState();\n\n        if (state != null) {\n            return state.getAccessPoint().getProvider();\n        } else {\n            return ServiceProvider.NONE;\n        }\n    }\n\n    /**\n     * 获得当前的运营商\n     *\n     * @param useIMSIFirst 优先使用IMSI判断\n     * @return 运营商\n     * @see ServiceProvider\n     */\n    public static ServiceProvider getProvider(boolean useIMSIFirst) {\n        ServiceProvider provider = ServiceProvider.NONE;\n\n        if (useIMSIFirst) {\n            provider = getIMSIProvider();\n\n            if (!ServiceProvider.NONE.equals(provider)) {\n                return provider;\n            }\n        }\n\n        provider = getProvider();\n\n        return provider;\n    }\n\n    /**\n     * 获得当前的运营商，根据IMSI中的MNC和MCC记录，即可刷新\n     */\n    public static ServiceProvider updateIMSIProvider() {\n        // 防止权限问题和IPC通信问题\n        try {\n            synchronized (NetworkDash.class) {\n                String IMSI = getIMSI();\n\n                imsiProvider = ServiceProvider.fromIMSI(IMSI);\n\n                Log.v(TAG, IMSI + \" => \" + imsiProvider);\n\n                return imsiProvider;\n            }\n        } catch (Exception e) {\n            return ServiceProvider.NONE;\n        }\n    }\n\n    public static String getIMSI() {\n        try {\n            TelephonyManager telephonyManager = (TelephonyManager) Ext.getContext().getSystemService(Context.TELEPHONY_SERVICE);\n\n            String IMSI1 = telephonyManager.getSimOperator();\n            // 处理双卡手机\n            if (TextUtils.isEmpty(IMSI1)) {\n                IMSI1 = getDeviceIdBySlot(Ext.getContext(), 0);\n            }\n            if (TextUtils.isEmpty(IMSI1)) {\n                IMSI1 = getDeviceIdBySlot(Ext.getContext(), 1);\n            }\n\n            Log.v(TAG, \"imsi: \" + IMSI1);\n\n            return IMSI1;\n        } catch (Exception e) {\n            return null;\n        }\n    }\n\n    // 获取双卡双待IMEI\n    public static String getDeviceIdBySlot(Context context, int slotID) {\n        Log.v(TAG, \"isDeviceIdBySlot:\" + slotID);\n        if (context == null)\n            return null;\n        if (slotID < 0 || slotID > 1)\n            return null;\n\n        String imei = null;\n        try {\n            TelephonyManager telephonyManager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);\n            Class<?> mLoadClass = Class.forName(\"android.telephony.TelephonyManager\");\n\n            Class<?>[] parameter = new Class[1];\n            parameter[0] = int.class;\n            Method getSimStateGemini = mLoadClass.getMethod(\"getSimOperatorGemini\", parameter);\n\n            Object[] obParameter = new Object[1];\n            obParameter[0] = slotID;\n            Object ob_phone = getSimStateGemini.invoke(telephonyManager, obParameter);\n\n            if (ob_phone != null) {\n                imei = ob_phone.toString();\n            }\n        } catch (Exception e) {\n            Log.w(TAG, \"getDeviceIdBySlot\", e);\n        }\n        return imei;\n    }\n\n    /**\n     * 获得当前的运营商，根据IMSI中的MNC和MCC记录\n     *\n     * @return the imsiProvider\n     */\n    public static ServiceProvider getIMSIProvider() {\n        if (imsiProvider == null) {\n            updateIMSIProvider();\n        }\n\n        return imsiProvider;\n    }\n\n    /**\n     * 判断当前是否是WAP网络\n     *\n     * @return 若是移动网络且接入点是WAP接入点，返回true，否则返回false，包括非wap网络、非移动网络和无网络\n     */\n    public static boolean isWap() {\n        return getAccessPoint().isWap();\n    }\n\n    /**\n     * 判断当前是否是移动网络\n     *\n     * @return 若是移动网络，返回true，否则返回false，包括非移动网络和无网络\n     */\n    public static boolean isMobile() {\n        NetworkType type = getType();\n\n        return NetworkType.MOBILE_4G.equals(type) || NetworkType.MOBILE_3G.equals(type)\n                || NetworkType.MOBILE_2G.equals(type);\n    }\n\n    public static boolean is2G() {\n        NetworkType type = getType();\n\n        return NetworkType.MOBILE_2G.equals(type);\n    }\n\n    public static boolean is3G() {\n        NetworkType type = getType();\n\n        return NetworkType.MOBILE_3G.equals(type);\n    }\n\n    /**\n     * 判断当前是否是WIFI网络\n     *\n     * @return 若是WIFI网络，返回true，否则返回false，包括非WIFI网络和无网络\n     */\n    public static boolean isWifi() {\n        return NetworkType.WIFI.equals(getType());\n    }\n\n    /**\n     * 判断当时是否是有线网络\n     *\n     * @return 若是有线网络，返回true，否则返回flase\n     */\n    public static boolean isEthernet() {\n        return NetworkType.ETHERNET.equals(getType());\n    }\n\n    /**\n     * 获得手机信号格数，和状态栏的提示理论上保持一致 <br>\n     * <br>\n     * <b>支持GSM/CDMA/EVDO网络，会自动处理<br>\n     * <b>至少需要Android 2.1及以上的API Level (7)</b>\n     *\n     * @return 从弱到强 0..4<br>\n     * 如果不支持或者尚未获得，返回 -1\n     */\n    public static int getCellLevel() {\n        return OBSERVER.getCellLevel();\n    }\n\n    /**\n     * 添加网络状态变化监听器\n     *\n     * @param listener 监听器\n     */\n    public static void addListener(NetworkStateListener listener) {\n        synchronized (OBSERVER_LIST) {\n            OBSERVER_LIST.add(new WeakReference<NetworkStateListener>(listener));\n        }\n    }\n\n    /**\n     * 移除网络状态变化监听器\n     *\n     * @param listener 监听器\n     */\n    public static void removeListener(NetworkStateListener listener) {\n        synchronized (OBSERVER_LIST) {\n            WeakReference<NetworkStateListener> reference = null;\n\n            for (WeakReference<NetworkStateListener> weakReference : OBSERVER_LIST) {\n                NetworkStateListener realListener = weakReference.get();\n\n                if (realListener != null) {\n                    if (realListener.equals(listener)) {\n                        reference = weakReference;\n                        break;\n                    }\n                }\n            }\n\n            OBSERVER_LIST.remove(reference);\n        }\n    }\n\n    private static void notifyNetworkStateChange() {\n        if (OBSERVER_LIST == null) {\n            return;\n        }\n\n        synchronized (OBSERVER_LIST) {\n            for (WeakReference<NetworkStateListener> listener : OBSERVER_LIST) {\n                NetworkStateListener realListener = listener.get();\n\n                if (realListener != null) {\n                    realListener.onNetworkStateChanged(getLastState(), getCurrState());\n                }\n            }\n        }\n    }\n\n    /**\n     * 刷新网络信息 <br>\n     *\n     * @return 网络信息是否变化\n     */\n    public static boolean updateNetworkState() {\n        synchronized (NetworkDash.class) {\n\n            NetworkInfo info = null;\n            try {\n                ConnectivityManager manager = (ConnectivityManager) Ext.getContext()\n                        .getSystemService(Context.CONNECTIVITY_SERVICE);\n\n                if (manager == null) {\n                    return false;\n                }\n                info = manager.getActiveNetworkInfo();\n\n            } catch (Error e1) {\n                info = null;\n            } catch (Exception e) {\n                info = null;\n            }\n            boolean changed = setCurrState(NetworkState.fromNetworkInfo(info));\n\n            if (changed) {\n                // 网络变动时，更新IMSI信息\n                updateIMSIProvider();\n\n                if (mainHandler == null) {\n                    mainHandler = new Handler(Ext.getContext().getMainLooper());\n                }\n\n                mainHandler.post(new Runnable() {\n                    @Override\n                    public void run() {\n                        notifyNetworkStateChange();\n                    }\n                });\n            }\n\n            return changed;\n        }\n    }\n\n    /**\n     * 获得当前的网络状态信息\n     *\n     * @return 网络状态信息\n     * @see NetworkState\n     */\n    public static NetworkState getCurrState() {\n        return currState;\n    }\n\n    protected static NetworkState getLastState() {\n        return lastState;\n    }\n\n    /**\n     * 更新当前的状态\n     *\n     * @return 若状态变化，则返回true; 否则返回false\n     */\n    protected static boolean setCurrState(NetworkState newState) {\n        synchronized (NetworkDash.class) {\n            boolean changed = false;\n\n            if (currState == null) {\n                NetworkDash.lastState = null;\n                NetworkDash.currState = newState;\n\n                changed = true;\n            } else if (!currState.equals(newState)) {\n                NetworkDash.lastState = NetworkDash.currState;\n                NetworkDash.currState = newState;\n\n                changed = true;\n            }\n\n            if (changed) {\n                Log.v(TAG, \"LAST -> \" + lastState);\n                Log.v(TAG, \"CURR -> \" + currState);\n            }\n\n            return changed;\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/NetworkObserver.java",
    "content": "package com.wkw.common_lib.network;\n\nimport android.annotation.SuppressLint;\nimport android.content.BroadcastReceiver;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.content.IntentFilter;\nimport android.net.ConnectivityManager;\nimport android.telephony.PhoneStateListener;\nimport android.telephony.SignalStrength;\nimport android.telephony.TelephonyManager;\nimport android.util.Log;\n\nimport com.wkw.common_lib.Ext;\n\n/**\n * Created by wukewei on 16/7/25.\n */\nabstract class NetworkObserver extends BroadcastReceiver{\n    private static final String TAG = \"NetworkObserver\";\n\n    private final boolean cellListenEnabled = (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.ECLAIR_MR1);\n    private PhoneStateListener signalListener;\n    private volatile int cellLevel = -1;\n\n    /**\n     * 当网络发生变化时回调\n     */\n    public abstract void onNetworkChanged();\n\n    public void startListen() {\n        IntentFilter intentFilter = new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION);\n\n        try {\n            Ext.getContext().registerReceiver(this, intentFilter);\n        } catch (Exception e) {\n            Log.w(TAG, \"startListen failed\");\n        }\n    }\n\n    public void stopListen() {\n        Ext.getContext().unregisterReceiver(this);\n    }\n\n    /**\n     * 获得手机信号格数，和状态栏的提示理论上保持一致\n     * <p>\n     * <b>至少需要Android 2.1及以上的API Level (7)</b>\n     *\n     * @return 从弱到强 0..4，如果不支持或者尚未获得，返回 -1\n     */\n    public int getCellLevel() {\n        return cellLevel;\n    }\n\n    @Override\n    public void onReceive(Context context, Intent intent) {\n        if (cellListenEnabled) {\n            if (signalListener == null) {\n                synchronized (this) {\n                    if (signalListener == null) {\n                        initSignalListen();\n                    }\n                }\n            }\n        }\n\n        if (ConnectivityManager.CONNECTIVITY_ACTION.equals(intent.getAction())) {\n            onNetworkChanged();\n        }\n    }\n\n    @SuppressLint(\"InlinedApi\")\n    private void initSignalListen() {\n        if (!cellListenEnabled) {\n            return;\n        }\n\n        signalListener = new PhoneStateListener() {\n            @Override\n            public void onSignalStrengthsChanged(SignalStrength signalStrength) {\n                cellLevel = getCellLevel(signalStrength);\n\n                super.onSignalStrengthsChanged(signalStrength);\n            }\n        };\n\n        TelephonyManager telephonyManager = (TelephonyManager) Ext.getContext().getSystemService(Context.TELEPHONY_SERVICE);\n\n        if (telephonyManager != null) {\n            telephonyManager.listen(signalListener, PhoneStateListener.LISTEN_SIGNAL_STRENGTHS);\n        } else {\n            // 监听失败\n            signalListener = null;\n        }\n    }\n\n    private int getCellLevel(SignalStrength signalStrength) {\n        int level = 0;\n\n        if (signalStrength == null) {\n            return -1;\n        }\n\n        if (signalStrength.isGsm()) {\n            level = getGsmLevel(signalStrength);\n        } else {\n            int cdmaLevel = getCdmaLevel(signalStrength);\n            int evdoLevel = getEvdoLevel(signalStrength);\n\n            if (evdoLevel == 0) {\n                level = cdmaLevel;\n            } else if (cdmaLevel == 0) {\n                level = evdoLevel;\n            } else {\n                level = evdoLevel > cdmaLevel ? cdmaLevel : evdoLevel;\n            }\n        }\n\n        return level;\n    }\n\n    private int getGsmLevel(SignalStrength signalStrength) {\n        int asu = signalStrength.getGsmSignalStrength();\n\n        // ASU ranges from 0 to 31 - TS 27.007 Sec 8.5\n        // asu = 0 (-113dB or less) is very weak\n        // signal, its better to show 0 bars to the user in such cases.\n        // asu = 99 is a special case, where the signal strength is unknown.\n        if (asu <= 2 || asu == 99)\n            return 0;\n        else if (asu >= 12)\n            return 4;\n        else if (asu >= 8)\n            return 3;\n        else if (asu >= 5)\n            return 2;\n        else\n            return 1;\n    }\n\n    // CDMA信号显示\n    private int getCdmaLevel(SignalStrength signalStrength) {\n        final int cdmaDbm = signalStrength.getCdmaDbm();\n        final int cdmaEcio = signalStrength.getCdmaEcio();\n        int levelDbm = 0;\n        int levelEcio = 0;\n\n        if (cdmaDbm >= -75)\n            levelDbm = 4;\n        else if (cdmaDbm >= -85)\n            levelDbm = 3;\n        else if (cdmaDbm >= -95)\n            levelDbm = 2;\n        else if (cdmaDbm >= -100)\n            levelDbm = 1;\n        else\n            levelDbm = 0;\n\n        // Ec/Io are in dB*10\n        if (cdmaEcio >= -90)\n            levelEcio = 4;\n        else if (cdmaEcio >= -110)\n            levelEcio = 3;\n        else if (cdmaEcio >= -130)\n            levelEcio = 2;\n        else if (cdmaEcio >= -150)\n            levelEcio = 1;\n        else\n            levelEcio = 0;\n\n        return (levelDbm < levelEcio) ? levelDbm : levelEcio;\n    }\n\n    // EVDO网络显示 CDMA2000 3G信号显示（例如电信天翼3G）\n    private int getEvdoLevel(SignalStrength signalStrength) {\n        int evdoDbm = signalStrength.getEvdoDbm();\n        int evdoSnr = signalStrength.getEvdoSnr();\n        int levelEvdoDbm = 0;\n        int levelEvdoSnr = 0;\n\n        if (evdoDbm >= -65)\n            levelEvdoDbm = 4;\n        else if (evdoDbm >= -75)\n            levelEvdoDbm = 3;\n        else if (evdoDbm >= -90)\n            levelEvdoDbm = 2;\n        else if (evdoDbm >= -105)\n            levelEvdoDbm = 1;\n        else\n            levelEvdoDbm = 0;\n\n        if (evdoSnr >= 7)\n            levelEvdoSnr = 4;\n        else if (evdoSnr >= 5)\n            levelEvdoSnr = 3;\n        else if (evdoSnr >= 3)\n            levelEvdoSnr = 2;\n        else if (evdoSnr >= 1)\n            levelEvdoSnr = 1;\n        else\n            levelEvdoSnr = 0;\n\n        return (levelEvdoDbm < levelEvdoSnr) ? levelEvdoDbm : levelEvdoSnr;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/NetworkState.java",
    "content": "package com.wkw.common_lib.network;\n\nimport android.net.ConnectivityManager;\nimport android.net.NetworkInfo;\n\nimport com.wkw.common_lib.utils.StringUtils;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic class NetworkState {\n    private static final NetworkState NONE = new NetworkState(false, null, AccessPoint.NONE, NetworkType.NONE);\n    /**\n     * 移动网络子类型常量\n     */\n    private static final int NETWORK_TYPE_UNKNOWN = 0;\n    private static final int NETWORK_TYPE_GPRS = 1;\n    private static final int NETWORK_TYPE_EDGE = 2;\n    private static final int NETWORK_TYPE_UMTS = 3;\n    private static final int NETWORK_TYPE_CDMA = 4;\n    private static final int NETWORK_TYPE_EVDO_0 = 5;\n    private static final int NETWORK_TYPE_EVDO_A = 6;\n    private static final int NETWORK_TYPE_1xRTT = 7;\n    private static final int NETWORK_TYPE_HSDPA = 8;\n    private static final int NETWORK_TYPE_HSUPA = 9;\n    private static final int NETWORK_TYPE_HSPA = 10;\n    private static final int NETWORK_TYPE_IDEN = 11;\n    private static final int NETWORK_TYPE_EVDO_B = 12;\n    private static final int NETWORK_TYPE_LTE = 13;\n    private static final int NETWORK_TYPE_EHRPD = 14;\n    private static final int NETWORK_TYPE_HSPAP = 15;\n    private boolean connected = false;\n    private String apnName = null;\n    private NetworkType type = NetworkType.NONE;\n    private AccessPoint accessPoint = AccessPoint.NONE;\n    private NetworkInfo moreInfo;\n\n    private NetworkState(boolean conn, String apn, AccessPoint ap, NetworkType tp) {\n        setConnected(conn);\n        setApnName(apn);\n        setAccessPoint(ap);\n        setType(tp);\n    }\n\n    private NetworkState() {\n\n    }\n\n    /**\n     * 从{@link android.net.NetworkInfo}构造网络状态信息\n     *\n     * @param info NetworkInfo对象\n     * @return 网络状态\n     */\n    public static NetworkState fromNetworkInfo(NetworkInfo info) {\n        // 得不到信息，返回NONE对象\n        if (info == null) {\n            return NetworkState.NONE;\n        }\n\n        NetworkState state = new NetworkState();\n\n        state.setConnected(info.isConnected());\n        state.setApnName(info.getExtraInfo());\n        state.setAccessPoint(AccessPoint.forName(state.getApnName()));\n\n        switch (info.getType()) {\n            // WIFI网络\n            case ConnectivityManager.TYPE_WIFI: {\n                state.setType(NetworkType.WIFI);\n                break;\n            }\n            // 有线网络\n            case ConnectivityManager.TYPE_ETHERNET: {\n                state.setType(NetworkType.ETHERNET);\n                break;\n            }\n            // 移动网络\n            case ConnectivityManager.TYPE_MOBILE:\n            case ConnectivityManager.TYPE_MOBILE_MMS:\n            case ConnectivityManager.TYPE_MOBILE_SUPL:\n            case ConnectivityManager.TYPE_MOBILE_DUN:\n            case ConnectivityManager.TYPE_MOBILE_HIPRI: {\n                // 根据速度判定是否是3G网络\n                state.setType(convertMobileType(info.getSubtype()));\n                break;\n            }\n            // 其他网络\n            default:\n                state.setType(NetworkType.OTHERS);\n                break;\n        }\n\n        // 保存额外的信息对象\n        state.setMoreInfo(info);\n\n        return state;\n    }\n\n    private static NetworkType convertMobileType(int subType) {\n        switch (subType) {\n            case NETWORK_TYPE_1xRTT:// ~ 50-100 kbps\n            case NETWORK_TYPE_CDMA:// ~ 14-64 kbps\n            case NETWORK_TYPE_GPRS:// ~ 100 kbps\n            case NETWORK_TYPE_EDGE:// ~ 50-100 kbps\n            case NETWORK_TYPE_IDEN:// ~ 25 kbps\n            case NETWORK_TYPE_UNKNOWN:\n                return NetworkType.MOBILE_2G;\n\n            case NETWORK_TYPE_EVDO_0:// ~ 400-1000 kbps\n            case NETWORK_TYPE_EVDO_A:// ~ 600-1400 kbps\n            case NETWORK_TYPE_HSDPA:// ~ 2-14 Mbps\n            case NETWORK_TYPE_HSPA:// ~ 700-1700 kbps\n            case NETWORK_TYPE_HSUPA:// ~ 1-23 Mbps\n            case NETWORK_TYPE_UMTS: // ~ 400-7000 kbps\n            case NETWORK_TYPE_EHRPD:// ~ 1-2 Mbps\n            case NETWORK_TYPE_EVDO_B:// ~ 5 Mbps\n            case NETWORK_TYPE_HSPAP:// ~ 10-20 Mbps\n                return NetworkType.MOBILE_3G;\n\n            case NETWORK_TYPE_LTE:// ~ 10+ Mbps\n                return NetworkType.MOBILE_4G;\n\n            default:\n                return NetworkType.OTHERS;\n        }\n    }\n\n    /**\n     * 判断子类型是否是快速网络，姑且认为快速网络即为3G网络\n     *\n     * @param type 网络子类型\n     * @return 3G网络，返回true; 2G网络或者未知网络，返回false\n     */\n    @Deprecated\n    private static boolean is3GMobileType(int type) {\n        NetworkType t = convertMobileType(type);\n\n        return (t == NetworkType.MOBILE_3G) || (t == NetworkType.MOBILE_4G);\n    }\n\n    @Override\n    public boolean equals(Object o) {\n        if (o == this) {\n            return true;\n        }\n\n        return o instanceof NetworkState &&\n                (((NetworkState) o).isConnected() == this.isConnected()) //\n                && (((NetworkState) o).getType().equals(this.getType())) //\n                && (((NetworkState) o).getApnName().equals(this.getApnName()));\n    }\n\n    public boolean isConnected() {\n        return connected;\n    }\n\n    public void setConnected(boolean connected) {\n        this.connected = connected;\n    }\n\n    public boolean isAvailable() {\n        return connected;\n    }\n\n    public String getApnName() {\n        if (apnName == null) {\n            return StringUtils.EMPTY;\n        } else {\n            return apnName;\n        }\n    }\n\n    public void setApnName(String apnName) {\n        this.apnName = apnName;\n    }\n\n    public NetworkType getType() {\n        return type;\n    }\n\n    public void setType(NetworkType type) {\n        this.type = type;\n    }\n\n    public AccessPoint getAccessPoint() {\n        return accessPoint;\n    }\n\n    public void setAccessPoint(AccessPoint accessPoint) {\n        this.accessPoint = accessPoint;\n    }\n\n    public NetworkInfo getMoreInfo() {\n        return moreInfo;\n    }\n\n    public void setMoreInfo(NetworkInfo moreInfo) {\n        this.moreInfo = moreInfo;\n    }\n\n    @Override\n    public String toString() {\n        return \"NetworkState [connected=\" + connected + \", apnName=\" + apnName + \", type=\" + type + \", accessPoint=\"\n                + accessPoint + \"]\";\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/NetworkStateListener.java",
    "content": "package com.wkw.common_lib.network;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic interface NetworkStateListener {\n\n    /**\n     * 当网络状态变化时，触发该事件 <br>\n     * <br>\n     * <b>该事件将在主线程中执行，不要执行耗时或阻塞操作，以免引发ANR</b>\n     *\n     * @param lastState 之前的网络状态\n     * @param newState  现在的网络状态\n     */\n    void onNetworkStateChanged(NetworkState lastState, NetworkState newState);\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/NetworkType.java",
    "content": "package com.wkw.common_lib.network;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic enum NetworkType {\n    /**\n     * 无网络，网络不可用\n     */\n    NONE(\"NONE\", false),\n    /**\n     * Wifi网络\n     */\n    WIFI(\"WIFI\", true),\n    /**\n     * 2G网络 / 低速移动网络\n     */\n    MOBILE_2G(\"2G\", true),\n    /**\n     * 3G网络 / 高速移动网络\n     */\n    MOBILE_3G(\"3G\", true),\n\n    /**\n     * 4G网络 / 超高速移动网络(Yeah!)\n     */\n    MOBILE_4G(\"4G\", true),\n    /**\n     * 有线网路\n     */\n    ETHERNET(\"ETHERNET\", true),\n    /**\n     * 其他网络，含蓝牙、WIFI P2P等\n     */\n    OTHERS(\"UNKNOWN\", true),;\n\n    private String name;\n    private boolean available;\n\n    NetworkType(String friendlyName, boolean available) {\n        setName(friendlyName);\n        setAvailable(available);\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    public void setName(String name) {\n        this.name = name;\n    }\n\n    public boolean isAvailable() {\n        return available;\n    }\n\n    public void setAvailable(boolean available) {\n        this.available = available;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/ServiceProvider.java",
    "content": "package com.wkw.common_lib.network;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic enum  ServiceProvider {\n    /**\n     * 运营商不可用，非移动网络或无网络\n     */\n    NONE(\"N/A\"),\n    /**\n     * 未知运营商，通常在未知接入点时\n     */\n    NEVER_HEARD(\"Unknown\"),\n    /**\n     * 中国移动 China Mobile\n     */\n    CHINA_MOBILE(\"China Mobile\"),\n    /**\n     * 中国联通 China Unicom\n     */\n    CHINA_UNICOM(\"China Unicom\"),\n    /**\n     * 中国电信 China Telecom\n     */\n    CHINA_TELECOM(\"China Telecom\"),;\n\n    private static final Map<String, ServiceProvider> IMSI_PROVIDER_MAP = new HashMap<String, ServiceProvider>();\n\n    static {\n        // 中国移动\n        IMSI_PROVIDER_MAP.put(\"46000\", CHINA_MOBILE);\n        IMSI_PROVIDER_MAP.put(\"46002\", CHINA_MOBILE);\n        IMSI_PROVIDER_MAP.put(\"46007\", CHINA_MOBILE);\n\n        // 中国电信\n        IMSI_PROVIDER_MAP.put(\"46003\", CHINA_TELECOM);\n        IMSI_PROVIDER_MAP.put(\"46005\", CHINA_TELECOM);\n\n        // 中国联通\n        IMSI_PROVIDER_MAP.put(\"46001\", CHINA_UNICOM);\n        IMSI_PROVIDER_MAP.put(\"46006\", CHINA_UNICOM);\n\n        // 中国铁通，算作移动\n        IMSI_PROVIDER_MAP.put(\"46020\", CHINA_MOBILE);\n    }\n\n    private String name;\n\n    ServiceProvider(String name) {\n        setName(name);\n    }\n\n    /**\n     * 根据IMSI中的MNC和MCC记录，计算运营商\n     *\n     * @return 运营商\n     */\n    public static ServiceProvider fromIMSI(String IMSI) {\n        if (IMSI == null) {\n            return ServiceProvider.NONE;\n        }\n\n        if (IMSI.length() < 5) {\n            return ServiceProvider.NONE;\n        }\n\n        ServiceProvider provider = IMSI_PROVIDER_MAP.get(IMSI.substring(0, 5));\n\n        if (provider != null) {\n            return provider;\n        } else {\n            return ServiceProvider.NEVER_HEARD;\n        }\n    }\n\n    public String getName() {\n        return name;\n    }\n\n    private void setName(String name) {\n        this.name = name;\n    }\n\n    @Override\n    public String toString() {\n        return getName();\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/network/WifiDash.java",
    "content": "package com.wkw.common_lib.network;\n\nimport android.content.Context;\nimport android.net.wifi.WifiInfo;\nimport android.net.wifi.WifiManager;\n\nimport com.wkw.common_lib.Ext;\nimport com.wkw.common_lib.utils.StringUtils;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic class WifiDash {\n    /**\n     * 获得当前接入点的BSSID<br>\n     * <br>\n     * <i>BSSID可以作为WIFI接入点的唯一标识</i>\n     *\n     * @return 形如MAC地址的字符串，{@code XX:XX:XX:XX:XX:XX}\n     * @see android.net.wifi.WifiInfo\n     */\n    public static String getBSSID() {\n        WifiManager wifiManager = (WifiManager) Ext.getContext().getSystemService(Context.WIFI_SERVICE);\n\n        if (wifiManager == null) {\n            return null;\n        }\n\n        WifiInfo wifiInfo = null;\n\n        try {\n            wifiInfo = wifiManager.getConnectionInfo();\n        } catch (Exception e) {\n            wifiInfo = null;\n        }\n\n        if (wifiInfo == null) {\n            return null;\n        }\n\n        String bssid = wifiInfo.getBSSID();\n\n        if (StringUtils.NOT_AVAILABLE.equals(bssid) || \"00:00:00:00:00:00\".equals(bssid)\n                || \"FF:FF:FF:FF:FF:FF\".equalsIgnoreCase(bssid)) {\n            return null;\n        } else {\n            return bssid;\n        }\n    }\n\n    public static String getSSID() {\n        WifiManager wifiManager = (WifiManager) Ext.getContext().getSystemService(Context.WIFI_SERVICE);\n\n        if (wifiManager == null) {\n            return null;\n        }\n\n        WifiInfo wifiInfo = null;\n\n        try {\n            wifiInfo = wifiManager.getConnectionInfo();\n        } catch (Exception e) {\n            wifiInfo = null;\n        }\n\n        if (wifiInfo == null) {\n            return null;\n        }\n\n        return wifiInfo.getSSID();\n    }\n\n    public static int getNetworkId() {\n        WifiManager wifiManager = (WifiManager) Ext.getContext().getSystemService(Context.WIFI_SERVICE);\n\n        if (wifiManager == null) {\n            return -1;\n        }\n\n        WifiInfo wifiInfo = null;\n\n        try {\n            wifiInfo = wifiManager.getConnectionInfo();\n        } catch (Exception e) {\n            wifiInfo = null;\n        }\n\n        if (wifiInfo == null) {\n            return -1;\n        }\n        return wifiInfo.getNetworkId();\n\n    }\n\n    public static int getSignalLevel() {\n        Object wifiInfo = queryWifiInfo(StringUtils.NOT_AVAILABLE);\n\n        if (wifiInfo == StringUtils.NOT_AVAILABLE) {\n            return -1;\n        }\n\n        return WifiManager.calculateSignalLevel(((WifiInfo) wifiInfo).getRssi(), 5);\n    }\n\n    private static Object queryWifiInfo(Object defValue) {\n        WifiManager wifiManager = (WifiManager) Ext.getContext().getSystemService(Context.WIFI_SERVICE);\n\n        if (wifiManager == null) {\n            return defValue;\n        }\n\n        WifiInfo wifiInfo = null;\n\n        try {\n            wifiInfo = wifiManager.getConnectionInfo();\n        } catch (Exception e) {\n            wifiInfo = null;\n        }\n\n        if (wifiInfo == null) {\n            return defValue;\n        }\n\n        return wifiInfo;\n    }\n\n    public static String getWifiInfo() {\n        WifiManager wifiManager = (WifiManager) Ext.getContext().getSystemService(Context.WIFI_SERVICE);\n\n        if (wifiManager == null) {\n            return \"[-]\";\n        }\n\n        WifiInfo wifiInfo = null;\n\n        try {\n            wifiInfo = wifiManager.getConnectionInfo();\n        } catch (Exception e) {\n            wifiInfo = null;\n        }\n\n        if (wifiInfo == null) {\n            return \"[-]\";\n        }\n\n        String ssid = wifiInfo.getSSID();\n\n        String signal = String.valueOf(WifiManager.calculateSignalLevel(wifiInfo.getRssi(), 5));\n\n        String speed = String.valueOf(wifiInfo.getLinkSpeed()) + \" \" + WifiInfo.LINK_SPEED_UNITS;\n\n        String bssid = wifiInfo.getBSSID();\n\n        StringBuffer buffer = new StringBuffer();\n\n        buffer.append('[').append(signal).append(\", \").append(ssid).append(\", \").append(speed).append(\", \")\n                .append(bssid).append(']');\n\n        return buffer.toString();\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/ApiResponse.java",
    "content": "package com.wkw.common_lib.rx;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class ApiResponse<T> {\n\n    public static final int SUCCESS_CODE = 0;\n\n    private int showapi_res_code;\n    private String showapi_res_error;\n    private T showapi_res_body;\n\n    public int getShowapi_res_code() {\n        return showapi_res_code;\n    }\n\n    public void setShowapi_res_code(int showapi_res_code) {\n        this.showapi_res_code = showapi_res_code;\n    }\n\n    public String getShowapi_res_error() {\n        return showapi_res_error;\n    }\n\n    public void setShowapi_res_error(String showapi_res_error) {\n        this.showapi_res_error = showapi_res_error;\n    }\n\n    public T getNewsList() {\n        return showapi_res_body;\n    }\n\n    public void setNewsList(T newsList) {\n        this.showapi_res_body = newsList;\n    }\n\n    public boolean isSuccess() {\n        if (this.showapi_res_code == SUCCESS_CODE) {\n            return true;\n        } else {\n            return false;\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/ProgressSubscriber.java",
    "content": "package com.wkw.common_lib.rx;\n\nimport android.app.ProgressDialog;\nimport android.content.Context;\n\nimport com.wkw.common_lib.rx.error.DefaultErrorBundle;\nimport com.wkw.common_lib.rx.error.ErrorHanding;\nimport com.wkw.common_lib.utils.DialogUtil;\n\nimport rx.Subscriber;\n\n/**\n * Created by wukewei on 16/8/17.\n */\npublic abstract class ProgressSubscriber<T> extends Subscriber<T> {\n\n    private ProgressDialog mProgressDialog;\n\n    public ProgressSubscriber(Context context, String message) {\n        mProgressDialog = DialogUtil.getWaitDialog(context, message);\n    }\n\n    @Override\n    public void onStart() {\n        super.onStart();\n        showProgress();\n    }\n\n    @Override\n    public void onCompleted() {\n        dismissProgress();\n    }\n\n    @Override\n    public void onNext(T t) {\n        _noNext(t);\n    }\n\n    @Override\n    public void onError(Throwable e) {\n        dismissProgress();\n        _onError(ErrorHanding.handleError(new DefaultErrorBundle((Exception) e)));\n    }\n\n\n\n    private void showProgress() {\n        if (mProgressDialog != null) {\n            mProgressDialog.show();\n        }\n    }\n\n    private void dismissProgress() {\n        if (mProgressDialog != null && mProgressDialog.isShowing()) {\n            mProgressDialog.dismiss();\n        }\n    }\n\n\n\n    public abstract void _noNext(T t);\n    public abstract void _onError(String msg);\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/RxBus.java",
    "content": "package com.wkw.common_lib.rx;\n\nimport rx.Observable;\nimport rx.subjects.PublishSubject;\nimport rx.subjects.SerializedSubject;\nimport rx.subjects.Subject;\n\n/**\n * Created by wukewei on 16/7/12.\n * http://www.jianshu.com/p/ca090f6e2fe2\n */\npublic class RxBus {\n    private static volatile RxBus defaultInstance;\n    /* 主题 */\n    private final Subject bus;\n    // PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者\n    public RxBus() {\n        bus = new SerializedSubject<>(PublishSubject.create());\n    }\n    // 单例RxBus\n    public static RxBus getDefault() {\n        RxBus rxBus = defaultInstance;\n        if (defaultInstance == null) {\n            synchronized (RxBus.class) {\n                rxBus = defaultInstance;\n                if (defaultInstance == null) {\n                    rxBus = new RxBus();\n                    defaultInstance = rxBus;\n                }\n            }\n        }\n        return rxBus;\n    }\n    // 提供了一个新的事件\n    public void post (Object o) {\n        bus.onNext(o);\n    }\n    // 根据传递的 eventType 类型返回特定类型(eventType)的 被观察者\n    public <T> Observable<T> toObserverable (Class<T> eventType) {\n        return bus.ofType(eventType);\n//        这里感谢小鄧子的提醒: ofType = filter + cast\n//        return bus.filter(new Func1<Object, Boolean>() {\n//            @Override\n//            public Boolean call(Object o) {\n//                return eventType.isInstance(o);\n//            }\n//        }) .cast(eventType);\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/RxResultHelper.java",
    "content": "package com.wkw.common_lib.rx;\n\nimport com.wkw.common_lib.rx.error.NetworkConnectionException;\nimport com.wkw.common_lib.rx.error.ServerException;\n\nimport rx.Observable;\nimport rx.Subscriber;\nimport rx.functions.Func1;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class RxResultHelper {\n\n    public static <T> Observable.Transformer<ApiResponse<T>, T> handleResult() {\n        return new Observable.Transformer<ApiResponse<T>, T>() {\n            @Override\n            public Observable<T> call(Observable<ApiResponse<T>> apiResponseObservable) {\n                return apiResponseObservable.flatMap(\n                        new Func1<ApiResponse<T>, Observable<T>>() {\n                            @Override\n                            public Observable<T> call(ApiResponse<T> tApiResponse) {\n                                if (tApiResponse == null) {\n                                    return Observable.error(new NetworkConnectionException());\n                                } else if (tApiResponse.isSuccess()) {\n                                    return createData(tApiResponse.getNewsList());\n                                } else {\n                                    return Observable.error(new ServerException(tApiResponse.getShowapi_res_code(),tApiResponse.getShowapi_res_error()));\n                                }\n                            }\n                        }\n                );\n            }\n        };\n    }\n\n\n    public static <T> Observable<T> createData(final T t) {\n        return Observable.create(new Observable.OnSubscribe<T>() {\n            @Override\n            public void call(Subscriber<? super T> subscriber) {\n                try {\n                    subscriber.onNext(t);\n                    subscriber.onCompleted();\n                } catch (Exception e) {\n                    subscriber.onError(e);\n                }\n            }\n        });\n    }\n}\n\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/RxSubscriber.java",
    "content": "package com.wkw.common_lib.rx;\n\nimport com.wkw.common_lib.rx.error.DefaultErrorBundle;\nimport com.wkw.common_lib.rx.error.ErrorHanding;\n\nimport rx.Subscriber;\n\n/**\n * Created by wukewei on 16/8/17.\n */\npublic abstract class RxSubscriber<T> extends Subscriber<T> {\n\n\n    @Override\n    public void onCompleted() {\n\n    }\n\n    @Override\n    public void onNext(T t) {\n        _noNext(t);\n    }\n\n    @Override\n    public void onError(Throwable e) {\n        _onError(ErrorHanding.handleError(new DefaultErrorBundle((Exception) e)));\n    }\n\n    public abstract void _noNext(T t);\n    public abstract void _onError(String msg);\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/SchedulersCompat.java",
    "content": "package com.wkw.common_lib.rx;\n\n\nimport rx.Observable;\nimport rx.android.schedulers.AndroidSchedulers;\nimport rx.schedulers.Schedulers;\n\n/**\n * Created by wukewei on 16/5/26.\n */\npublic class SchedulersCompat {\n\n\n    private final static Observable.Transformer ioTransformer = new Observable.Transformer() {\n        @Override\n        public Object call(Object o) {\n            return ((Observable)o).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread());\n        }\n    };\n\n    public static <T> Observable.Transformer<T, T> applyIoSchedulers() {\n        return (Observable.Transformer<T, T>) ioTransformer;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/error/DefaultErrorBundle.java",
    "content": "package com.wkw.common_lib.rx.error;\n\n/**\n * Created by wukewei on 16/8/17.\n */\npublic class DefaultErrorBundle implements ErrorBundle {\n    private static final String DEFAULT_ERROR_MSG = \"Unknown error\";\n\n    private final Exception exception;\n\n    public DefaultErrorBundle(Exception exception) {\n        this.exception = exception;\n    }\n\n    @Override\n    public Exception getException() {\n        return exception;\n    }\n\n    @Override\n    public String getErrorMessage() {\n        return (exception != null) ? this.exception.getMessage() : DEFAULT_ERROR_MSG;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/error/ErrorBundle.java",
    "content": "package com.wkw.common_lib.rx.error;\n\n/**\n * Created by wukewei on 16/8/17.\n */\npublic interface ErrorBundle {\n    Exception getException();\n    String getErrorMessage();\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/error/ErrorHanding.java",
    "content": "package com.wkw.common_lib.rx.error;\n\nimport com.wkw.common_lib.Ext;\n\nimport java.net.ConnectException;\nimport java.net.SocketTimeoutException;\n\n/**\n * Created by wukewei on 16/6/1.\n */\npublic class ErrorHanding {\n\n    public ErrorHanding() {\n    }\n\n    public static String handleError(ErrorBundle e) {\n        e.getException().printStackTrace();\n        String message;\n        Exception exception = e.getException();\n        if (!Ext.g().isAvailable()) {\n            message = \"网络中断，请检查您的网络状态\";\n        } else if (exception instanceof SocketTimeoutException) {\n            message = \"网络中断，请检查您的网络状态\";\n        } else if (exception instanceof ConnectException) {\n            message = \"网络中断，请检查您的网络状态\";\n        } else if (exception instanceof NetworkConnectionException) {\n            message = \"网络中断，请检查您的网络状态\";\n        } else if (exception instanceof ServerException) {\n            int code  = ((ServerException) exception).getCode();\n            //在这里你可以获取code来判断是什么类型  好比有些token失效了你就可以实现跳转到登录页面\n            message = e.getErrorMessage();\n        } else {\n            message = \"连接服务器失败,请稍后再试\";\n        }\n        return message;\n    }\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/error/NetworkConnectionException.java",
    "content": "/**\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 * <p>\n * http://www.apache.org/licenses/LICENSE-2.0\n * <p>\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.\n */\npackage com.wkw.common_lib.rx.error;\n\n/**\n * Exception throw by the application when a there is a\n * network connection exception.\n */\npublic class NetworkConnectionException extends Exception {\n\n    public NetworkConnectionException() {\n        super();\n    }\n\n    public NetworkConnectionException(final String message) {\n        super(message);\n    }\n\n    public NetworkConnectionException(final String message, final Throwable cause) {\n        super(message, cause);\n    }\n\n    public NetworkConnectionException(final Throwable cause) {\n        super(cause);\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/rx/error/ServerException.java",
    "content": "package com.wkw.common_lib.rx.error;\n\n/**\n * Created by wukewei on 16/5/30.\n */\npublic class ServerException extends Exception {\n\n\n    private int mCode;\n    public ServerException(int code,String msg) {\n        super(msg);\n        this.mCode = code;\n    }\n\n    /***\n     * 这里可以获取code来判断具体是什么错误\n     * @param\n     * @param\n     * @return\n     */\n    public int getCode() {\n        return mCode;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/sp/Once.java",
    "content": "package com.wkw.common_lib.sp;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.os.Build;\nimport android.support.annotation.IntDef;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.util.Date;\nimport java.util.concurrent.TimeUnit;\n\n/**\n * Created by wukewei on 16/7/24.\n */\n@TargetApi(Build.VERSION_CODES.GINGERBREAD)\npublic class Once {\n    public static final int THIS_APP_INSTALL = 0;\n    public static final int THIS_APP_VERSION = 1;\n\n    private static long lastAppUpdatedTime = -1;\n\n    private static PersistedMap tagLastSeenMap;\n\n    private Once() {\n    }\n\n    /**\n     * 初始化Once\n     *\n     * @param context Application context\n     */\n    public static void init(Context context) {\n        if (tagLastSeenMap == null) {\n            tagLastSeenMap = new PersistedMap(context, \"TagLastSeenMap\");\n        }\n\n        PackageManager packageManager = context.getPackageManager();\n        try {\n            PackageInfo packageInfo = packageManager.getPackageInfo(context.getPackageName(), 0);\n            lastAppUpdatedTime = packageInfo.lastUpdateTime;\n        } catch (PackageManager.NameNotFoundException ignored) {\n\n        }\n    }\n\n    /**\n     * 检查在给定scope内对应tag是否被标记过.\n     *\n     * @param scope 检查范围, {@code THIS_APP_INSTALL} 或 {@code THIS_APP_VERSION}.\n     * @param tag   唯一性标识该操作的字符串.\n     * @return {@code true} 如果和 {@code tag} 关联的操作在给定 {@code scope} 被标记过.\n     */\n    public static boolean beenDone(@Scope int scope, String tag) {\n\n        Long tagLastSeenDate = tagLastSeenMap.get(tag);\n\n        if (tagLastSeenDate == null) {\n            return false;\n        }\n\n        if (scope == THIS_APP_INSTALL) {\n            return true;\n        }\n\n        return tagLastSeenDate > lastAppUpdatedTime;\n    }\n\n    /**\n     * 检查某个tag是否在给定时间范围（如最近1小时）被标记过，如Once.beenDone(TimeUnit.HOURS, 1, \"a\")\n     *\n     * @param timeUnit 时间单位, 如@code TimeUnit.HOURS.\n     * @param amount   时间单位的数量.\n     * @param tag      唯一性标识该操作的字符串.\n     * @return {@code true} 如果和 {@code tag} 关联的操作在给定最近时间段被标记过.\n     */\n    public static boolean beenDone(TimeUnit timeUnit, long amount, String tag) {\n        long timeInMillis = timeUnit.toMillis(amount);\n        return beenDone(timeInMillis, tag);\n    }\n\n    /**\n     * 检查某个tag是否在给定最近时间段内被标记过\n     *\n     * @param timeSpanInMillis 最近时间，毫秒单位（millisecond）.\n     * @param tag              唯一性标识该操作的字符串.\n     * @return {@code true} 如果和 {@code tag} 关联的操作在最近X毫秒内被标记过.\n     */\n    public static boolean beenDone(long timeSpanInMillis, String tag) {\n        Long timeTagSeen = tagLastSeenMap.get(tag);\n\n        if (timeTagSeen == null) {\n            return false;\n        }\n\n        long sinceSinceCheckTime = new Date().getTime() - timeSpanInMillis;\n\n        return timeTagSeen > sinceSinceCheckTime;\n    }\n\n    /**\n     * 标记某个tag为done.\n     *\n     * @param tag 唯一性标识该操作的字符串.\n     */\n    public static void markDone(String tag) {\n        tagLastSeenMap.put(tag, new Date().getTime());\n    }\n\n    /**\n     * 清掉给定tag的记录. 所有对该tag的{@link #beenDone}操作在再次标记前都会返回true.\n     *\n     * @param tag 唯一性标识该操作的字符串.\n     */\n    public static void clearDone(String tag) {\n        tagLastSeenMap.remove(tag);\n    }\n\n    /**\n     * 清掉所有tag的记录. 所有{@link #beenDone}操作在再次标记前都会返回true.\n     */\n    public static void clearAll() {\n        tagLastSeenMap.clear();\n    }\n\n    @Retention(RetentionPolicy.SOURCE)\n    @IntDef({THIS_APP_INSTALL, THIS_APP_VERSION})\n    public @interface Scope {\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/sp/PersistedMap.java",
    "content": "package com.wkw.common_lib.sp;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.content.SharedPreferences;\nimport android.os.Build;\n\nimport java.util.Map;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * Created by wukewei on 16/7/24.\n */\n@TargetApi(Build.VERSION_CODES.GINGERBREAD)\nclass PersistedMap {\n\n    private static final long KEY_NOT_FOUND_VALUE = -1;\n    private final SharedPreferences preferences;\n    private Map<String, Long> map = new ConcurrentHashMap<>();\n\n    public PersistedMap(Context context, String mapName) {\n        preferences = context.getSharedPreferences(PersistedMap.class.getSimpleName() + mapName, Context.MODE_PRIVATE);\n        Map<String, ?> allPreferences = preferences.getAll();\n\n        for (String key : allPreferences.keySet()) {\n            long value = preferences.getLong(key, KEY_NOT_FOUND_VALUE);\n\n            if (value != KEY_NOT_FOUND_VALUE) {\n                map.put(key, value);\n            }\n        }\n    }\n\n    public Long get(String tag) {\n        return map.get(tag);\n    }\n\n    public void put(String tag, long timeSeen) {\n        map.put(tag, timeSeen);\n        SharedPreferences.Editor edit = preferences.edit();\n        edit.putLong(tag, timeSeen);\n        edit.apply();\n    }\n\n    public void remove(String tag) {\n        map.remove(tag);\n        SharedPreferences.Editor edit = preferences.edit();\n        edit.remove(tag);\n        edit.apply();\n    }\n\n    public void clear() {\n        map.clear();\n        SharedPreferences.Editor edit = preferences.edit();\n        edit.clear();\n        edit.apply();\n    }\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/AndroidUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.app.Activity;\nimport android.content.ClipData;\nimport android.content.ClipboardManager;\nimport android.content.Context;\nimport android.content.Intent;\nimport android.net.Uri;\n\nimport com.wkw.common_lib.R;\n\n/**\n * Created by wukewei on 16/7/26.\n */\npublic class AndroidUtils {\n\n    public static void copyToClipBoard(Context context, String text) {\n        ClipData clipData = ClipData.newPlainText(\"common_copy\", text);\n        ClipboardManager manager = (ClipboardManager) context.getSystemService(\n                Context.CLIPBOARD_SERVICE);\n        manager.setPrimaryClip(clipData);\n        ToashUtils.show(context, context.getString(R.string.copy_done));\n    }\n\n    public static void openBrowser(Context context, String url) {\n        Intent intent = new Intent();\n        intent.setAction(Intent.ACTION_VIEW);\n        Uri uri = Uri.parse(url);\n        intent.setData(uri);\n        if (intent.resolveActivity(context.getPackageManager()) != null) {\n            context.startActivity(intent);\n        } else {\n            ToashUtils.show(context, context.getString(R.string.open_failure));\n        }\n    }\n\n    /**\n     * 调用系统安装了的应用分享\n     *\n     * @param context\n     * @param title\n     * @param url\n     */\n    public static void showSystemShareOption(Activity context,\n                                             final String title, final String url) {\n        Intent intent = new Intent(Intent.ACTION_SEND);\n        intent.setType(\"text/plain\");\n        intent.putExtra(Intent.EXTRA_SUBJECT, \"分享：\" + title);\n        intent.putExtra(Intent.EXTRA_TEXT, title + \" \" + url);\n        context.startActivity(Intent.createChooser(intent, \"选择分享\"));\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/AppManager.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.app.Activity;\n\nimport java.util.Stack;\n\n/**\n * Created by wukewei on 16/7/26.\n */\npublic class AppManager {\n    private static Stack<Activity> activityStack;\n    private static AppManager mInstance;\n\n    private AppManager() {}\n\n\n    public static AppManager getAppManager() {\n        if (mInstance == null) {\n            synchronized (AppManager.class) {\n                if (mInstance == null) {\n                    mInstance = new AppManager();\n                }\n            }\n        }\n        return mInstance;\n    }\n\n    public void addActivity(Activity activity) {\n        if (activityStack == null) {\n            activityStack = new Stack<>();\n        }\n        activityStack.add(activity);\n    }\n\n    public void removeActivity(Activity activity) {\n        if (activity != null && activityStack.contains(activity)) {\n            activityStack.remove(activity);\n        }\n    }\n\n\n    public Activity curremtActivity() {\n        Activity activity = activityStack.lastElement();\n        return activity;\n    }\n\n\n    public void finishActivity(Activity activity) {\n        if (activity != null && activityStack.contains(activity) && !activity.isFinishing()) {\n            activityStack.remove(activity);\n            activity.finish();\n        }\n    }\n\n    public void finishAllActivity() {\n        for (int i= 0, size = activityStack.size(); i < size; i++) {\n            if (null != activityStack.get(i)) {\n                activityStack.get(i).finish();\n            }\n        }\n        activityStack.clear();\n    }\n\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/AppUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.app.ActivityManager;\nimport android.app.KeyguardManager;\nimport android.content.Context;\nimport android.content.pm.ApplicationInfo;\nimport android.content.pm.PackageInfo;\nimport android.content.pm.PackageManager;\nimport android.os.Bundle;\nimport android.text.TextUtils;\n\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic final class AppUtils {\n    private static Bundle sOwnAppMetaInfo;\n\n    private AppUtils() {\n        // static usage.\n    }\n\n    public static boolean isForeground(Context context) {\n        if (isScreenLocked(context)) {\n            return false;\n        }\n        ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n        List<ActivityManager.RunningTaskInfo> a = mActivityManager.getRunningTasks(1);\n        return context.getPackageName().equals(a.get(0).baseActivity.getPackageName())\n                && context.getPackageName().equals(a.get(0).topActivity.getPackageName());\n    }\n\n    private static boolean isScreenLocked(Context context) {\n        KeyguardManager mKeyguardManager = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);\n        return mKeyguardManager.inKeyguardRestrictedInputMode();\n    }\n\n    public static int getVersionCode(Context context) {\n        if (context == null) {\n            return 0;\n        }\n        try {\n            PackageInfo info = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);\n            return info.versionCode;\n        } catch (Throwable e) {\n            return 0;\n        }\n    }\n\n    /**\n     * 获取带有指定配置信息的ApplicationInfo\n     *\n     * @param flags 比如 {@link android.content.pm.PackageManager#GET_META_DATA}\n     * @see #getSimpleAppInfo(android.content.Context)\n     * @see <a href=\"https://code.google.com/p/android/issues/detail?id=37968\" >why this method</a>\n     */\n    public static ApplicationInfo getAppInfoWithFlags(Context ctx, int flags) {\n        try {\n            return ctx == null ? null : ctx.getPackageManager().getApplicationInfo(ctx.getPackageName(), PackageManager.GET_META_DATA);\n        } catch (PackageManager.NameNotFoundException e) {\n            e.printStackTrace();\n        }\n        return null;\n    }\n\n    /**\n     * 获取基本的applicationInfo\n     *\n     * @see #getAppInfoWithFlags(android.content.Context, int)\n     */\n    public static ApplicationInfo getSimpleAppInfo(Context ctx) {\n        return ctx == null ? null : ctx.getApplicationInfo();\n    }\n\n    /**\n     * Check whether corresponding package is installed.\n     *\n     * @param context     Application context.\n     * @param packageName Package name.\n     * @return Whether corresponding package is installed.\n     */\n    public static boolean isPackageInstalled(Context context, String packageName) {\n        if (!TextUtils.isEmpty(packageName)) {\n            try {\n                PackageInfo packageInfo = context.getPackageManager().getPackageInfo(packageName, 0);\n                return packageInfo != null;\n            } catch (PackageManager.NameNotFoundException e) {\n                // ignore.\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Get application info of own package.\n     *\n     * @param context Application context.\n     * @return Application info of own package.\n     */\n    public static Bundle getApplicationMetaInfo(Context context) {\n        if (sOwnAppMetaInfo == null) {\n            synchronized (AppUtils.class) {\n                if (sOwnAppMetaInfo == null) {\n                    sOwnAppMetaInfo = getApplicationMetaInfo(context, context.getPackageName());\n                }\n            }\n        }\n        return sOwnAppMetaInfo != null ? new Bundle(sOwnAppMetaInfo) : null;\n    }\n\n    /**\n     * Get application meta info of corresponding package.\n     *\n     * @param context     Application context.\n     * @param packageName Package name.\n     * @return Application meta info of corresponding package.\n     */\n    public static Bundle getApplicationMetaInfo(Context context, String packageName) {\n        ApplicationInfo appInfo = packageName.equals(context.getPackageName()) ?\n                context.getApplicationInfo() : null;\n        Bundle metaInfo = appInfo != null ? appInfo.metaData : null;\n        if (metaInfo == null) {\n            try {\n                appInfo = context.getPackageManager().getApplicationInfo(\n                        packageName, PackageManager.GET_META_DATA);\n                metaInfo = appInfo.metaData;\n            } catch (Throwable e) {\n                // ignore.\n            }\n        }\n        return metaInfo;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/DialogUtil.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.app.ProgressDialog;\nimport android.content.Context;\nimport android.content.DialogInterface;\nimport android.support.v7.app.AlertDialog;\nimport android.text.Html;\nimport android.text.TextUtils;\n\n/**\n * Created by wukewei on 16/8/17.\n */\npublic class DialogUtil {\n\n    /***\n     * 获取一个dialog\n     * @param context\n     * @param\n     * @return\n     */\n    public static AlertDialog.Builder getDialog(Context context) {\n        AlertDialog.Builder builder = new AlertDialog.Builder(context);\n        return builder;\n    }\n\n    public static ProgressDialog getWaitDialog(Context context, String message) {\n        ProgressDialog waitDialog = new ProgressDialog(context);\n        if (!TextUtils.isEmpty(message)) {\n            waitDialog.setMessage(message);\n        }\n        return waitDialog;\n    }\n\n    /***\n     * 获取一个信息对话框，注意需要自己手动调用show方法显示\n     * @param context\n     * @param message\n     * @param onClickListener\n     * @return\n     */\n    public static AlertDialog.Builder getMessageDialog(Context context, String message, DialogInterface.OnClickListener onClickListener) {\n        AlertDialog.Builder builder = getDialog(context);\n        builder.setMessage(message);\n        builder.setPositiveButton(\"确定\", onClickListener);\n        return builder;\n    }\n\n    public static AlertDialog.Builder getMessageDialog(Context context, String message) {\n        return getMessageDialog(context, message, null);\n    }\n\n    public static AlertDialog.Builder getConfirmDialog(Context context, String message, DialogInterface.OnClickListener onClickListener) {\n        AlertDialog.Builder builder = getDialog(context);\n        builder.setMessage(Html.fromHtml(message));\n        builder.setPositiveButton(\"确定\", onClickListener);\n        builder.setNegativeButton(\"取消\", null);\n        return builder;\n    }\n\n    public static AlertDialog.Builder getConfirmDialog(Context context, String message, DialogInterface.OnClickListener onOkClickListener, DialogInterface.OnClickListener onCancleClickListener) {\n        AlertDialog.Builder builder = getDialog(context);\n        builder.setMessage(message);\n        builder.setPositiveButton(\"确定\", onOkClickListener);\n        builder.setNegativeButton(\"取消\", onCancleClickListener);\n        return builder;\n    }\n\n    public static AlertDialog.Builder getConfirmDialog(Context context,\n                                                       String message,\n                                                       String okString,\n                                                       String cancleString,\n                                                       DialogInterface.OnClickListener onOkClickListener,\n                                                       DialogInterface.OnClickListener onCancleClickListener) {\n        return getConfirmDialog(context, \"\", message, okString, cancleString, onOkClickListener, onCancleClickListener);\n    }\n\n    public static AlertDialog.Builder getConfirmDialog(Context context,\n                                                       String title,\n                                                       String message,\n                                                       String okString,\n                                                       String cancleString,\n                                                       DialogInterface.OnClickListener onOkClickListener,\n                                                       DialogInterface.OnClickListener onCancleClickListener) {\n        AlertDialog.Builder builder = getDialog(context);\n        if (!TextUtils.isEmpty(title)) {\n            builder.setTitle(title);\n        }\n        builder.setMessage(message);\n        builder.setPositiveButton(okString, onOkClickListener);\n        builder.setNegativeButton(cancleString, onCancleClickListener);\n        return builder;\n    }\n\n    public static AlertDialog.Builder getSelectDialog(Context context, String title, String[] arrays, DialogInterface.OnClickListener onClickListener) {\n        AlertDialog.Builder builder = getDialog(context);\n        builder.setItems(arrays, onClickListener);\n        if (!TextUtils.isEmpty(title)) {\n            builder.setTitle(title);\n        }\n        builder.setPositiveButton(\"取消\", null);\n        return builder;\n    }\n\n    public static AlertDialog.Builder getSelectDialog(Context context, String[] arrays, DialogInterface.OnClickListener onClickListener) {\n        return getSelectDialog(context, \"\", arrays, onClickListener);\n    }\n\n    public static AlertDialog.Builder getSingleChoiceDialog(Context context, String title, String[] arrays, int selectIndex, DialogInterface.OnClickListener onClickListener) {\n        AlertDialog.Builder builder = getDialog(context);\n        builder.setSingleChoiceItems(arrays, selectIndex, onClickListener);\n        if (!TextUtils.isEmpty(title)) {\n            builder.setTitle(title);\n        }\n        builder.setNegativeButton(\"取消\", null);\n        return builder;\n    }\n\n    public static AlertDialog.Builder getSingleChoiceDialog(Context context, String[] arrays, int selectIndex, DialogInterface.OnClickListener onClickListener) {\n        return getSingleChoiceDialog(context, \"\", arrays, selectIndex, onClickListener);\n    }\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/HtmlUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport java.util.regex.Pattern;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic final class HtmlUtils {\n    /**\n     * 过滤html\n     */\n    public static String filterHtml(String inputString) {\n        String htmlStr = inputString; // 含html标签的字符串\n        String textStr = \"\";\n        Pattern p_script;\n        java.util.regex.Matcher m_script;\n        Pattern p_html;\n        java.util.regex.Matcher m_html;\n\n        try {\n            String regEx_html = \"<[^>]+>\"; // 定义HTML标签的正则表达式\n\n            String regEx_script = \"<[/s]*?script[^>]*?>[/s/S]*?<[/s]*?//[/s]*?script[/s]*?>\"; // 定义script的正则表达式{或<script[^>]*?>[/s/S]*?<//script>\n\n            p_script = Pattern.compile(regEx_script, Pattern.CASE_INSENSITIVE);\n            m_script = p_script.matcher(htmlStr);\n            htmlStr = m_script.replaceAll(\"\"); // 过滤script标签\n\n            p_html = Pattern.compile(regEx_html, Pattern.CASE_INSENSITIVE);\n            m_html = p_html.matcher(htmlStr);\n            htmlStr = m_html.replaceAll(\"\"); // 过滤html标签\n\n            textStr = htmlStr;\n\n        } catch (Exception e) {\n            System.err.println(\"Html2Text: \" + e.getMessage());\n        }\n\n        return textStr;// 返回文本字符串\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/NetWorkUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.content.Context;\nimport android.database.Cursor;\nimport android.net.ConnectivityManager;\nimport android.net.DhcpInfo;\nimport android.net.NetworkInfo;\nimport android.net.Proxy;\nimport android.net.Uri;\nimport android.net.wifi.WifiManager;\nimport android.os.Build;\nimport android.support.annotation.RequiresPermission;\nimport android.telephony.TelephonyManager;\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport com.wkw.common_lib.Ext;\n\nimport java.net.InetAddress;\nimport java.net.NetworkInterface;\nimport java.util.Enumeration;\nimport java.util.HashMap;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic final class NetWorkUtils {\n    // ------------------ common -------------------\n    public final static int NETWORK_TYPE_NONE = -1;\n    public final static int NETWORK_TYPE_UNKNOWN = 1;\n    public final static int NETWORK_TYPE_UNKNOWN_MOBILE = 2;\n    public final static int NETWORK_TYPE_2G = 3;\n    public final static int NETWORK_TYPE_3G = 4;\n    public final static int NETWORK_TYPE_4G = 5;\n    public final static int NETWORK_TYPE_WIFI = 10;\n    /**\n     * WIFI的APN名字..\n     */\n    public final static String APN_NAME_WIFI = \"wifi\";\n    private final static String TAG = \"NetworkUtil\";\n    private final static Uri PREFERRED_APN_URI\n            = Uri.parse(\"content://telephony/carriers/preferapn\");\n    private final static HashMap<String, NetworkProxy> sAPNProxies\n            = new HashMap<String, NetworkProxy>();\n\n    static {\n        sAPNProxies.put(\"cmwap\", new NetworkProxy(\"10.0.0.172\", 80));\n        sAPNProxies.put(\"3gwap\", new NetworkProxy(\"10.0.0.172\", 80));\n        sAPNProxies.put(\"uniwap\", new NetworkProxy(\"10.0.0.172\", 80));\n        sAPNProxies.put(\"ctwap\", new NetworkProxy(\"10.0.0.200\", 80));\n    }\n\n    /**\n     * 检查当前网络是否连接\n     */\n    public static boolean isNetworkConnected() {\n        return isNetworkConnected(Ext.getContext());\n    }\n\n    /**\n     * 检查当前网络是否连接\n     *\n     * @param context Application context.\n     * @return 当前网络是否连接\n     */\n    public static boolean isNetworkConnected(Context context) {\n        NetworkInfo info = getActiveNetworkInfo(context);\n        return info != null && info.isConnected();\n    }\n\n    public static boolean isWifiConnected() {\n        return isWifiConnected(Ext.getContext());\n    }\n\n    /**\n     * 检查当前Wifi网络是否连接\n     *\n     * @param context Application context.\n     * @return Whether wifi network is connected.\n     */\n    public static boolean isWifiConnected(Context context) {\n        if (context == null) {\n            return false;\n        }\n        NetworkInfo activeNetworkInfo = getActiveNetworkInfo(context);\n        return activeNetworkInfo != null && activeNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI;\n    }\n\n    /**\n     * 检查当前移动网络是否连接\n     *\n     * @param context Application context.\n     * @return Whether mobile network is connected.\n     */\n    public static boolean isMobileConnected(Context context) {\n        if (context == null) {\n            return false;\n        }\n        NetworkInfo activeNetworkInfo = getActiveNetworkInfo(context);\n        return activeNetworkInfo != null && activeNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE;\n    }\n\n    /**\n     * Returns details about the currently active default data network. When\n     * connected, this network is the default route for outgoing connections.\n     * You should always check {@link NetworkInfo#isConnected()} before initiating\n     * network traffic. This may return {@code null} when there is no default\n     * network.\n     *\n     * @param context Application context.\n     * @return a {@link NetworkInfo} object for the current default network\n     * or {@code null} if no network default network is currently active\n     * <p>\n     * <p>This method requires the call to hold the permission\n     * {@link android.Manifest.permission#ACCESS_NETWORK_STATE}.\n     */\n    public static NetworkInfo getActiveNetworkInfo(Context context) {\n        try {\n            ConnectivityManager connMgr = (ConnectivityManager) context\n                    .getSystemService(Context.CONNECTIVITY_SERVICE);\n            return connMgr.getActiveNetworkInfo();\n        } catch (Throwable e) {\n            Log.e(TAG, \"fail to get active network info\", e);\n            return null;\n        }\n    }\n\n    /**\n     * 返回当前活动网络的类型.\n     *\n     * @param context Application context.\n     * @return type of current active network, the alternation is {@link #NETWORK_TYPE_WIFI}, {@link #NETWORK_TYPE_4G},\n     * {@link #NETWORK_TYPE_3G}, {@link #NETWORK_TYPE_2G}, {@link #NETWORK_TYPE_UNKNOWN_MOBILE}, {@link #NETWORK_TYPE_UNKNOWN},\n     * {@link #NETWORK_TYPE_NONE}.\n     */\n    public static int getActiveNetworkType(Context context) {\n        return getNetworkType(context, getActiveNetworkInfo(context));\n    }\n\n    /**\n     * Returns type of corresponding network info.\n     *\n     * @param context Application context.\n     * @param info    Network info.\n     * @return type of current active network, the alternation is {@link #NETWORK_TYPE_WIFI}, {@link #NETWORK_TYPE_4G},\n     * {@link #NETWORK_TYPE_3G}, {@link #NETWORK_TYPE_2G}, {@link #NETWORK_TYPE_UNKNOWN_MOBILE}, {@link #NETWORK_TYPE_UNKNOWN},\n     * {@link #NETWORK_TYPE_NONE}.\n     */\n    public static int getNetworkType(Context context, NetworkInfo info) {\n        if (info != null) {\n            if (info.getType() == ConnectivityManager.TYPE_WIFI) {\n                return NETWORK_TYPE_WIFI;\n\n            } else if (info.getType() == ConnectivityManager.TYPE_MOBILE) {\n                int subType = info.getSubtype();\n                switch (subType) {\n                    // 2G\n                    case TelephonyManager.NETWORK_TYPE_EDGE: // ~25 kbps\n                    case TelephonyManager.NETWORK_TYPE_GPRS: // GPRS (2.5G)\n                    case TelephonyManager.NETWORK_TYPE_CDMA: // CDMA: Either IS95A or IS95B (2G)\n                    case TelephonyManager.NETWORK_TYPE_1xRTT: // 1xRTT (2G - Transitional)\n                    case TelephonyManager.NETWORK_TYPE_IDEN: // iDen (2G)\n                        return NETWORK_TYPE_2G;\n\n                    // 3G\n                    case TelephonyManager.NETWORK_TYPE_UMTS:\n                    case TelephonyManager.NETWORK_TYPE_EVDO_0: // EVDO revision 0 (3G)\n                    case TelephonyManager.NETWORK_TYPE_HSPA: // HSPA (3G - Transitional)\n                        return NETWORK_TYPE_3G;\n\n                    // 3.5G\n                    case TelephonyManager.NETWORK_TYPE_EVDO_A: // EVDO revision A (3G - Transitional)\n                    case TelephonyManager.NETWORK_TYPE_EVDO_B: // EVDO revision A (3G - Transitional)\n                    case TelephonyManager.NETWORK_TYPE_HSPAP: // HSPA+ (3G - Transitional)\n                    case TelephonyManager.NETWORK_TYPE_HSDPA: // HSDPA (3G - Transitional)\n                    case TelephonyManager.NETWORK_TYPE_HSUPA: // HSUPA (3G - Transitional)\n                        return NETWORK_TYPE_3G;\n\n                    // 4G\n                    case TelephonyManager.NETWORK_TYPE_LTE:\n                    case TelephonyManager.NETWORK_TYPE_EHRPD:\n                        return NETWORK_TYPE_4G;\n\n                    default:\n                        return NETWORK_TYPE_UNKNOWN_MOBILE;\n                }\n            }\n            return NETWORK_TYPE_UNKNOWN;\n        }\n        return NETWORK_TYPE_NONE;\n    }\n\n    /**\n     * 获取网络代理，需要指定是否通过APN去获取.\n     *\n     * @param context  Application context.\n     * @param apnProxy Control whether determine the proxy by system interface or by current apn.\n     * @return Current network proxy.\n     */\n    public static NetworkProxy getProxy(Context context, boolean apnProxy) {\n        return !apnProxy ? getProxy(context) : getProxyByAPN(context);\n    }\n\n    /**\n     * 通过系统的接口获取网络代理.\n     *\n     * @param context Application context.\n     * @return Current network proxy.\n     */\n    public static NetworkProxy getProxy(Context context) {\n        if (!isMobileConnected(context)) {\n            return null;\n        }\n        String proxyHost = getProxyHost(context);\n        int proxyPort = getProxyPort(context);\n        if (!isEmpty(proxyHost) && proxyPort >= 0) {\n            return new NetworkProxy(proxyHost, proxyPort);\n        }\n        return null;\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    private static String getProxyHost(Context context) {\n        String host = null;\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {\n            host = Proxy.getDefaultHost();\n        } else {\n            host = System.getProperty(\"http.proxyHost\");\n        }\n        return host;\n    }\n\n    @SuppressWarnings(\"deprecation\")\n    private static int getProxyPort(Context context) {\n        int port = -1;\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {\n            port = Proxy.getDefaultPort();\n        } else {\n            String portStr = System.getProperty(\"http.proxyPort\");\n            if (!isEmpty(portStr)) {\n                try {\n                    port = Integer.parseInt(portStr);\n                } catch (NumberFormatException e) {\n                    e.printStackTrace();\n                }\n            }\n        }\n        if (port < 0 || port > 65535) {\n            // ensure valid port.\n            port = -1;\n        }\n        return port;\n    }\n\n    /**\n     * 通过APN获取当前网络代理.\n     *\n     * @param context Application context.\n     * @return Current network proxy.\n     */\n    public static NetworkProxy getProxyByAPN(Context context) {\n        if (!isMobileConnected(context)) {\n            return null;\n        }\n        String apn = getAPN(context);\n        NetworkProxy proxy = sAPNProxies.get(apn);\n        return proxy == null ? null : proxy.copy();\n    }\n\n    /**\n     * 获得当前APN.\n     *\n     * @param context Application context.\n     * @return Current apn. If device is connected to wifi, then it will be {@link #APN_NAME_WIFI}.\n     */\n    public static String getAPN(Context context) {\n        NetworkInfo activeNetInfo = getActiveNetworkInfo(context);\n        if (activeNetInfo == null) {\n            // no active network.\n            return null;\n        }\n\n        String apn = null;\n        if (activeNetInfo.getType() == ConnectivityManager.TYPE_WIFI) {\n            apn = APN_NAME_WIFI;\n\n        } else if (activeNetInfo.getType() == ConnectivityManager.TYPE_MOBILE) {\n            if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN) {\n                Cursor cursor = null;\n                try {\n                    cursor = context.getContentResolver().query(PREFERRED_APN_URI, null, null, null, null);\n                    while (cursor != null && cursor.moveToNext()) {\n                        apn = cursor.getString(cursor.getColumnIndex(\"apn\"));\n                    }\n                } catch (Throwable e) {\n                    e.printStackTrace();\n                } finally {\n                    if (cursor != null) {\n                        cursor.close();\n                    }\n                }\n            }\n            if (TextUtils.isEmpty(apn)) {\n                apn = activeNetInfo.getExtraInfo();\n            }\n        }\n        if (apn != null) {\n            // convert apn to lower case.\n            apn = apn.toLowerCase();\n        }\n\n        return apn;\n    }\n\n    /**\n     * 获得当前DNS.\n     *\n     * @param context Application context.\n     * @return 当前DNS.\n     */\n    @RequiresPermission(android.Manifest.permission.ACCESS_WIFI_STATE)\n    public static DNS getDNS(Context context) {\n        DNS dns = new DNS();\n        if (context != null) {\n            if (isWifiConnected(context)) {\n                WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);\n                DhcpInfo dhcpInfo = wifiManager.getDhcpInfo();\n                if (dhcpInfo != null) {\n                    dns.primary = int32ToIPStr(dhcpInfo.dns1);\n                    dns.secondary = int32ToIPStr(dhcpInfo.dns2);\n                }\n            }\n        }\n        if (dns.primary == null && dns.secondary == null) {\n            // retrieve dns with property.\n            dns.primary = PropertyUtils.get(PropertyUtils.PROPERTY_DNS_PRIMARY, null);\n            dns.secondary = PropertyUtils.get(PropertyUtils.PROPERTY_DNS_SECONDARY, null);\n        }\n        return dns;\n    }\n\n    private static String int32ToIPStr(int ip) {\n        StringBuffer buffer = new StringBuffer();\n\n        buffer.append(ip & 0xFF).append(\".\");\n        buffer.append((ip >> 8) & 0xFF).append(\".\");\n        buffer.append((ip >> 16) & 0xFF).append(\".\");\n        buffer.append((ip >> 24) & 0xFF);\n\n        return buffer.toString();\n    }\n\n    /**\n     * 获得当前本地IP\n     */\n    public static String getLocalIP() {\n        try {\n            for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {\n                NetworkInterface ni = en.nextElement();\n                for (Enumeration<InetAddress> enumIpAddr = ni.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {\n                    InetAddress inetAddress = enumIpAddr.nextElement();\n                    if (!inetAddress.isLoopbackAddress()) {\n                        return inetAddress.getHostAddress().toString();\n                    }\n                }\n            }\n\n        } catch (Throwable ex) {\n            // ignore.\n        }\n        return null;\n    }\n\n    // ---------------- utils ------------------\n    private static boolean isEmpty(String str) {\n        return str == null || str.length() == 0;\n    }\n\n    /**\n     * 网络代理定义.\n     */\n    public static class NetworkProxy implements Cloneable {\n\n        public final String host;\n        public final int port;\n\n        NetworkProxy(String host, int port) {\n            this.host = host;\n            this.port = port;\n        }\n\n        final NetworkProxy copy() {\n            try {\n                return (NetworkProxy) clone();\n            } catch (CloneNotSupportedException e) {\n                // ignore.\n            }\n            return null;\n        }\n\n        @Override\n        public String toString() {\n            return host + \":\" + port;\n        }\n\n        @Override\n        public boolean equals(Object obj) {\n            if (this == obj)\n                return true;\n\n            if (obj != null && obj instanceof NetworkProxy) {\n                NetworkProxy proxy = (NetworkProxy) obj;\n                if (TextUtils.equals(this.host, proxy.host) && this.port == proxy.port)\n                    return true;\n            }\n\n            return false;\n        }\n    }\n\n    /**\n     * DNS定义.\n     */\n    public final static class DNS {\n        public String primary;\n        public String secondary;\n\n        DNS() {\n        }\n\n        @Override\n        public String toString() {\n            return primary + \",\" + secondary;\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/ProcessUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.app.ActivityManager;\nimport android.content.Context;\nimport java.util.Collection;\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * Created by wukewei on 16/11/12.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class ProcessUtils {\n\n    private final static int[] EMPTY_INT_ARRAY = new int[0];\n\n    private static volatile String sProcessName;\n    private final static Object sNameLock = new Object();\n\n    private static volatile Boolean sMainProcess;\n    private final static Object sMainLock = new Object();\n\n    private ProcessUtils() {\n        // static usage.\n    }\n\n    /**\n     * Returns the name of this process.\n     *\n     * @param context Application context.\n     * @return The name of this process.\n     */\n    public static String myProcessName(Context context) {\n        if (sProcessName != null) {\n            return sProcessName;\n        }\n        synchronized (sNameLock) {\n            if (sProcessName != null) {\n                return sProcessName;\n            }\n            return sProcessName = obtainProcessName(context);\n        }\n    }\n\n    /**\n     * Check whether this process is the main process (it's name equals to {@link Context#getPackageName()}).\n     *\n     * @param context Application context.\n     * @return Whether this process is the main process.\n     */\n    public static boolean isMainProcess(Context context) {\n        if (sMainProcess != null) {\n            return sMainProcess;\n        }\n        synchronized (sMainLock) {\n            if (sMainProcess != null) {\n                return sMainProcess;\n            }\n            final String processName = myProcessName(context);\n            if (processName == null) {\n                return false;\n            }\n            sMainProcess = processName.equals(context.getApplicationInfo().processName);\n            return sMainProcess;\n        }\n    }\n\n    /**\n     * Kill this process itself.\n     */\n    public void killSelf() {\n        android.os.Process.killProcess(android.os.Process.myPid());\n    }\n\n    /**\n     * Kill all processes related this package.\n     */\n    public static void killAll(Context context) {\n        killAll(context, EMPTY_INT_ARRAY);\n    }\n\n    /**\n     * Kill all process related this package.\n     *\n     * @param excludePid exclude pid of processes.\n     */\n    public static void killAll(Context context, int... excludePid) {\n        int myPid = android.os.Process.myPid();\n        Collection<ActivityManager.RunningAppProcessInfo> runningProcess = collectRunningProcessInfo(context);\n        Set<Integer> excludePidSet = collectUniqueSet(excludePid);\n        // kill running process exclude required exception and self.\n        if (runningProcess != null) {\n            for (ActivityManager.RunningAppProcessInfo process : runningProcess) {\n                if (excludePidSet != null && excludePidSet.contains(process.pid)) {\n                    // exclude process.\n                    continue;\n                }\n                if (myPid == process.pid) {\n                    // my pid, ignore here.\n                    continue;\n                }\n                android.os.Process.killProcess(process.pid);\n            }\n        }\n        if (excludePidSet != null && excludePidSet.contains(myPid)) {\n            // exclude self.\n            return;\n        }\n        // kill self at last.\n        android.os.Process.killProcess(myPid);\n    }\n\n    /**\n     * Kill all process related this package.\n     *\n     * @param excludeName exclude name of processes.\n     */\n    public static void killAll(Context context, String... excludeName) {\n        int myPid = android.os.Process.myPid();\n        String myProcessName = null;\n        Collection<ActivityManager.RunningAppProcessInfo> runningProcess = collectRunningProcessInfo(context);\n        Set<String> excludeNameSet = collectUniqueSet(excludeName);\n        // kill running process exclude required exception and self.\n        if (runningProcess != null) {\n            for (ActivityManager.RunningAppProcessInfo process : runningProcess) {\n                if (excludeNameSet != null && excludeNameSet.contains(process.processName)) {\n                    // exclude process.\n                    continue;\n                }\n                if (myPid == process.pid) {\n                    // my pid, ignore here.\n                    myProcessName = process.processName;\n                    continue;\n                }\n                android.os.Process.killProcess(process.pid);\n            }\n        }\n        if (myProcessName != null && excludeNameSet != null && excludeNameSet.contains(myProcessName)) {\n            // exclude self.\n            return;\n        }\n        // kill self at last.\n        android.os.Process.killProcess(myPid);\n    }\n\n    /**\n     * Whether this process is foreground.\n     *\n     * @return true if foreground.\n     */\n    public static boolean isForeground(Context context) {\n        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n        List<ActivityManager.RunningTaskInfo> runningTasks = am.getRunningTasks(1);\n        if (runningTasks == null || runningTasks.isEmpty()) {\n            return false;\n        }\n        ActivityManager.RunningTaskInfo topTask = runningTasks.get(0);\n        if (topTask == null) {\n            return false;\n        }\n        String myPackageName = context.getPackageName();\n        return (myPackageName.equals(topTask.baseActivity.getPackageName()))\n            || (myPackageName.equals(topTask.topActivity.getPackageName()));\n    }\n\n    private static Collection<ActivityManager.RunningAppProcessInfo> collectRunningProcessInfo(Context context) {\n        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n        Collection<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();\n        // filter processes according to uid.\n        if (runningProcesses != null) {\n            int uid = android.os.Process.myUid();\n            Iterator<ActivityManager.RunningAppProcessInfo> iterator = runningProcesses.iterator();\n            while (iterator.hasNext()) {\n                ActivityManager.RunningAppProcessInfo process = iterator.next();\n                if (process == null || process.uid != uid) {\n                    iterator.remove();\n                }\n            }\n        }\n        return runningProcesses;\n    }\n\n    private static <V> Set<V> collectUniqueSet(V... values) {\n        if (values == null || values.length == 0) {\n            return null;\n        }\n        Set<V> set = new HashSet<V>(values.length);\n        for (V value : values) {\n            set.add(value);\n        }\n        return set;\n    }\n\n    private static Set<Integer> collectUniqueSet(int... values) {\n        if (values == null || values.length == 0) {\n            return null;\n        }\n        Set<Integer> set = new HashSet<Integer>(values.length);\n        for (int value : values) {\n            set.add(value);\n        }\n        return set;\n    }\n\n    private static String obtainProcessName(Context context) {\n        final int pid = android.os.Process.myPid();\n        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);\n        List<ActivityManager.RunningAppProcessInfo> listTaskInfo = am.getRunningAppProcesses();\n        if (listTaskInfo != null && listTaskInfo.size() > 0) {\n            for (ActivityManager.RunningAppProcessInfo proc : listTaskInfo) {\n                if (proc != null && proc.pid == pid) {\n                    return proc.processName;\n                }\n            }\n        }\n        return null;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/PropertyUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.text.TextUtils;\nimport android.util.Log;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStreamReader;\nimport java.lang.reflect.Method;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic final class PropertyUtils {\n    public final static String PROPERTY_DNS_PRIMARY = \"net.dns1\";\n    public final static String PROPERTY_DNS_SECONDARY = \"net.dns2\";\n    private final static String TAG = \"PropertyUtils\";\n    private final static String CMD_GET_PROP = \"getprop\";\n\n    private static Class sClassSystemProperties;\n    private static Method sMethodGetString;\n\n    static {\n        try {\n            sClassSystemProperties = Class.forName(\"android.os.SystemProperties\");\n            sMethodGetString = sClassSystemProperties.getDeclaredMethod(\"get\", String.class, String.class);\n\n        } catch (Throwable e) {\n            Log.w(TAG, e);\n        }\n    }\n\n    private PropertyUtils() {\n        // static usage.\n    }\n\n    /**\n     * Get property of corresponding key.\n     *\n     * @param key      Property key.\n     * @param defValue Default value.\n     * @return Property of corresponding key.\n     */\n    public static String get(String key, String defValue) {\n        if (TextUtils.isEmpty(key)) {\n            return defValue;\n        }\n        String value = getWithReflect(key, null);\n        if (TextUtils.isEmpty(value)) {\n            value = getWithCmd(key, null);\n        }\n        if (TextUtils.isEmpty(value)) {\n            value = defValue;\n        }\n        return value;\n    }\n\n    /**\n     * Get property of corresponding key quickly (but provide less validity than {@link #get(String, String)}).\n     *\n     * @param key      Property key.\n     * @param defValue Default value.\n     * @return Property of corresponding key.\n     */\n    public static String getQuickly(String key, String defValue) {\n        if (TextUtils.isEmpty(key)) {\n            return defValue;\n        }\n        return getWithReflect(key, defValue);\n    }\n\n    private static String getWithReflect(String key, String defValue) {\n        if (sClassSystemProperties == null || sMethodGetString == null) {\n            return defValue;\n        }\n        String value = defValue;\n        try {\n            value = (String) sMethodGetString.invoke(sClassSystemProperties, key, defValue);\n\n        } catch (Throwable e) {\n            Log.w(TAG, e);\n        }\n        return value;\n    }\n\n    private static String getWithCmd(String key, String defValue) {\n        String value = defValue;\n        try {\n            Process process = Runtime.getRuntime().exec(CMD_GET_PROP + \" \" + key);\n            BufferedReader reader = null;\n            try {\n                reader = new BufferedReader(new InputStreamReader(process.getInputStream()));\n                StringBuilder builder = new StringBuilder();\n                String line;\n                while ((line = reader.readLine()) != null) {\n                    builder.append(line);\n                }\n                String readValue = builder.toString();\n                if (!TextUtils.isEmpty(readValue)) {\n                    // if read value is valid, use it.\n                    value = readValue;\n                }\n\n            } catch (IOException e) {\n                //\n            } finally {\n                if (reader != null) {\n                    reader.close();\n                }\n            }\n            // clean job.\n            process.destroy();\n\n        } catch (Throwable e) {\n            Log.w(TAG, e);\n        }\n        return value;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/Singleton.java",
    "content": "package com.wkw.common_lib.utils;\n\n/**\n * Created by wukewei on 16/7/24.\n */\npublic abstract class Singleton<T, P> {\n    private volatile  T mInstance;\n\n    protected abstract T create(P p);\n\n    public final T get(P p) {\n        if (mInstance == null) {\n            synchronized (this) {\n                if (mInstance == null) {\n                    mInstance = create(p);\n                }\n            }\n        }\n        return mInstance;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/StringUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.text.TextUtils;\nimport android.text.format.Time;\n\nimport java.io.ByteArrayOutputStream;\nimport java.io.InputStream;\nimport java.lang.reflect.Array;\nimport java.text.SimpleDateFormat;\nimport java.util.ArrayList;\nimport java.util.Collection;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.regex.Pattern;\n\n/**\n * Created by wukewei on 16/7/25.\n */\npublic class StringUtils {\n    /**\n     * 空字符串常量\n     */\n    public static final String EMPTY = \"\";\n    /**\n     * \"不可用\"字符串常量\n     */\n    public static final String NOT_AVAILABLE = \"N/A\";\n    private static final int CACHE_SIZE = 4096;\n\n    /**\n     * 创建指定格式的时间格式化对象\n     *\n     * @param pattern 时间格式，形如\"yyyy-MM-dd HH-mm-ss.SSS\"\n     * @return Format 时间格式化对象\n     */\n    public static SimpleDateFormat createDataFormat(String pattern) {\n        return new SimpleDateFormat(pattern);\n    }\n\n    /**\n     * 将s中字符用delimiter分割连接起来\n     *\n     * @param delimiter 分隔符\n     * @param segments  被连接的数据\n     * @return 返回连接号的字符串\n     * @see StringUtils#join(String, Object[])\n     */\n    public static String join(String delimiter, Collection<?> segments) {\n        StringBuilder stringBuilder = new StringBuilder();\n        if (segments != null) {\n            appendCollectionObjectToStringBuilder(stringBuilder, delimiter, segments);\n        }\n        String outString = stringBuilder.toString();\n        if (outString.endsWith(delimiter)) {\n            return outString.substring(0, outString.length() - delimiter.length());\n        }\n        return outString;\n    }\n\n    /**\n     * 将对象链接成一个字符串，使用delimiter传入的字符串分割，\n     * <p><b>注意:</b>如果前一个片段为字符串且以delimiter结束或者为空(null获取为\"\")，将不会重复添加此字符串</p>\n     * <p>字符串末尾不会自动添加delimiter字符串</p>\n     * <p>如果没有传入参数，返回一个<b>空字符串</b></p>\n     *\n     * @param delimiter 分割字符串\n     * @param segments  所有传入的部分\n     * @return 连接完毕后的字符串\n     */\n    public static String join(String delimiter, Object... segments) {\n        StringBuilder stringBuilder = new StringBuilder();\n        if (segments != null) {\n            int size = segments.length;\n            if (size > 0) {\n                for (Object segment : segments) {\n                    appendObjectToStringBuilder(stringBuilder, delimiter, segment);\n                }\n            }\n        }\n        String outString = stringBuilder.toString();\n        if (outString.endsWith(delimiter)) {\n            return outString.substring(0, outString.length() - delimiter.length());\n        }\n        return outString;\n    }\n\n\n    private static void appendArrayObjectToStringBuilder(StringBuilder stringBuilder, String delimiter, Object array) {\n        int length = Array.getLength(array);\n        for (int i = 0; i < length; i++) {\n            appendObjectToStringBuilder(stringBuilder, delimiter, Array.get(array, i));\n        }\n    }\n\n    private static void appendCollectionObjectToStringBuilder(StringBuilder stringBuilder, String delimiter, Collection<?> collection) {\n        Iterator iterator = collection.iterator();\n        while (iterator.hasNext()) {\n            appendObjectToStringBuilder(stringBuilder, delimiter, iterator.next());\n        }\n    }\n\n    private static void appendObjectToStringBuilder(StringBuilder stringBuilder, String delimiter, Object object) {\n        if (object == null) {\n            return;\n        }\n        if (object.getClass().isArray()) {\n            appendArrayObjectToStringBuilder(stringBuilder, delimiter, object);\n        } else if (object instanceof Collection) {\n            appendCollectionObjectToStringBuilder(stringBuilder, delimiter, (Collection) object);\n        } else {\n            String objectString = object.toString();\n            stringBuilder.append(objectString);\n            if (!isEmpty(objectString) && !objectString.endsWith(delimiter)) {\n                stringBuilder.append(delimiter);\n            }\n        }\n    }\n\n    /**\n     * 测试传入的字符串是否为空\n     *\n     * @param string 需要测试的字符串\n     * @return 如果字符串为空（包括不为空但其中为空白字符串的情况）返回true，否则返回false\n     */\n    public static boolean isEmpty(String string) {\n        return string == null || string.trim().length() == 0;\n    }\n\n    /**\n     * 测试传入的字符串是否为空\n     *\n     * @param string 需要测试的字符串\n     * @return 如果字符串为空（包括不为空但其中为空白字符串的情况）返回false，否则返回true\n     */\n    public static boolean isNotEmpty(String string) {\n        return string != null && string.trim().length() > 0;\n    }\n\n    /**\n     * 传入的字符串是否相等\n     *\n     * @param a a字符串\n     * @param b b字符串\n     * @return 如果字符串相等（值比较）返回true，否则返回false\n     */\n    public static boolean equal(String a, String b) {\n        return a == b || (a != null && b != null && a.length() == b.length() && a.equals(b));\n    }\n\n    /**\n     * 将字符串用分隔符分割为long数组\n     * <p><b>只支持10进制的数值转换</b></p>\n     * <p><b>如果格式错误，将抛出NumberFormatException</b></p>\n     *\n     * @param string    字符串\n     * @param delimiter 分隔符\n     * @return 分割后的long数组.\n     */\n    public static long[] splitToLongArray(String string, String delimiter) {\n        List<String> stringList = splitToStringList(string, delimiter);\n\n        long[] longArray = new long[stringList.size()];\n        int i = 0;\n        for (String str : stringList) {\n            longArray[i++] = Long.parseLong(str);\n        }\n        return longArray;\n    }\n\n    /**\n     * 将字符串用分隔符分割为Long列表\n     * <p><b>只支持10进制的数值转换</b></p>\n     * <p><b>如果格式错误，将抛出NumberFormatException</b></p>\n     *\n     * @param string    字符串\n     * @param delimiter 分隔符\n     * @return 分割后的Long列表.\n     */\n    public static List<Long> splitToLongList(String string, String delimiter) {\n        List<String> stringList = splitToStringList(string, delimiter);\n\n        List<Long> longList = new ArrayList<Long>(stringList.size());\n        for (String str : stringList) {\n            longList.add(Long.parseLong(str));\n        }\n        return longList;\n    }\n\n    /**\n     * 将字符串用分隔符分割为字符串数组\n     *\n     * @param string    字符串\n     * @param delimiter 分隔符\n     * @return 分割后的字符串数组.\n     */\n    public static String[] splitToStringArray(String string, String delimiter) {\n        List<String> stringList = splitToStringList(string, delimiter);\n        return stringList.toArray(new String[stringList.size()]);\n    }\n\n    /**\n     * 将字符串用分隔符分割为字符串列表\n     *\n     * @param string    字符串\n     * @param delimiter 分隔符\n     * @return 分割后的字符串数组.\n     */\n    public static List<String> splitToStringList(String string, String delimiter) {\n        List<String> stringList = new ArrayList<String>();\n        if (!isEmpty(string)) {\n            int length = string.length();\n            int pos = 0;\n\n            do {\n                int end = string.indexOf(delimiter, pos);\n                if (end == -1) {\n                    end = length;\n                }\n                stringList.add(string.substring(pos, end));\n                pos = end + 1; // skip the delimiter\n            } while (pos < length);\n        }\n        return stringList;\n    }\n\n    /**\n     * InputSteam 转换到 String，会把输入流关闭\n     *\n     * @param inputStream 输入流\n     * @return String 如果有异常则返回null\n     */\n    public static String stringFromInputStream(InputStream inputStream) {\n        try {\n            byte[] readBuffer = new byte[CACHE_SIZE];\n            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();\n            while (true) {\n                int readLen = inputStream.read(readBuffer, 0, CACHE_SIZE);\n                if (readLen <= 0) {\n                    break;\n                }\n\n                byteArrayOutputStream.write(readBuffer, 0, readLen);\n            }\n\n            return byteArrayOutputStream.toString(\"UTF-8\");\n        } catch (Exception e) {\n            e.printStackTrace();\n        } catch (OutOfMemoryError e) {\n            e.printStackTrace();\n        } finally {\n            try {\n                inputStream.close();\n            } catch (Exception e) {\n                e.printStackTrace();\n            }\n        }\n        return null;\n    }\n\n    /**\n     * 测试是否为有效的注册电子邮件格式\n     *\n     * @param string 内容\n     * @return true if yes\n     */\n    public static boolean isEmailFormat(String string) {\n        if (StringUtils.isEmpty(string)) {\n            return false;\n        }\n        String emailFormat = \"^([a-zA-Z0-9_\\\\.-]+)@([\\\\da-zA-Z\\\\.-]+)\\\\.([a-zA-Z\\\\.]{1,16})$\";\n        return Pattern.matches(emailFormat, string);\n    }\n\n    /**\n     * 测试是否为有效的登录电子邮件格式\n     *\n     * @param string 内容\n     * @return true if yes\n     */\n    public static boolean isLoginEmailFormat(String string) {\n        if (StringUtils.isEmpty(string)) {\n            return false;\n        }\n        String emailFormat = \"^\\\\s*\\\\w+(?:\\\\.?[\\\\w-]+\\\\.?)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\\\.[a-zA-Z]+\\\\s*$\";\n        return Pattern.matches(emailFormat, string);\n    }\n\n    /**\n     * 是否在长度范围之类\n     *\n     * @param string 内容\n     * @param begin  最小长度（inclusive）\n     * @param end    最大长度（inclusive）\n     * @return 字符串长度在begin和end之内返回true，否则返回false。<p><b>输入字符串为null时，返回false</b></p>\n     */\n    public static boolean lengthInRange(String string, int begin, int end) {\n        return string != null && string.length() >= begin && string.length() <= end;\n    }\n\n    /**\n     * 去除文件名中的无效字符\n     *\n     * @param srcStr srcStr\n     * @return 去除文件名后的字符\n     */\n    public static String validateFilePath(String srcStr) {\n        return StringUtils.isEmpty(srcStr) ? srcStr : srcStr.replaceAll(\"[\\\\\\\\/:\\\"*?<>|]+\", \"_\");\n    }\n\n    /**\n     * 获取字串字符长度，规则如下：\n     * 中文一个字长度为2，英文、字符长度为1\n     * 如：\"我c\"长度为3\n     *\n     * @param str str\n     * @return 字符串长度\n     */\n    public static int getCharsLength(String str) {\n        int length = 0;\n        try {\n            if (str == null) {\n                return 0;\n            }\n            str = str.replaceAll(\"[^\\\\x00-\\\\xff]\", \"**\");\n            length += str.length();\n        } catch (Exception e) {\n            e.printStackTrace();\n        }\n        return length;\n    }\n\n    /**\n     * 获取字串的文字个数，规则如下：\n     * 汉字为1，英文、字符算0.5个字\n     * 如：\"我\"字数为1，\"我k\"字数为2，\"我ko\"字数也为2\n     *\n     * @param str str\n     * @return 字符串长度\n     */\n    public static int getWordCount(String str) {\n        int length = getCharsLength(str);\n        return length % 2 + length / 2;\n    }\n\n    /**\n     * 得到毫秒数对应的时间串, 格式 \"2013-07-04 12:44:53.098\" <br>\n     * <br>\n     * 这个方法使用Android的Time类实现，用以替代java.util.Calender<br>\n     * 使用同余计算毫秒数，在某些ROM上，JDK被替换的算法不能计算毫秒数 (e.g. 华为荣耀)\n     *\n     * @param time 毫秒数\n     * @return 时间字符串\n     */\n    public static String getTimeStr(long time) {\n        long ms = time % 1000;\n\n        Time timeObj = new Time();\n\n        timeObj.set(time);\n\n        StringBuilder builder = new StringBuilder();\n\n        builder.append(timeObj.format(\"%Y-%m-%d %H:%M:%S\")).append('.');\n\n        if (ms < 10) {\n            builder.append(\"00\");\n        } else if (ms < 100) {\n            builder.append('0');\n        }\n\n        builder.append(ms);\n\n        return builder.toString();\n    }\n\n    /**\n     * 比较两个字符串，是否prefix字符串是source字符串的前缀，忽略大小写差别\n     *\n     * @param source 查找的字符串..\n     * @param prefix 前缀.\n     * @return {@code true} 如果指定字符串是这个字符串的前缀, 否则{@code false}\n     */\n    public static boolean startsWithIgnoreCase(String source, String prefix) {\n        if (source == prefix) {\n            return true;\n        }\n        if (source == null || prefix == null) {\n            return false;\n        }\n        return source.regionMatches(true, 0, prefix, 0, prefix.length());\n    }\n\n    /**\n     * 比较两个字符串，是否prefix字符串是source字符串的后缀，忽略大小写差别\n     *\n     * @param source 查找的字符串..\n     * @param suffix 后缀.\n     * @return {@code true} 如果指定字符串是这个字符串的后缀, 否则{@code false}\n     */\n    public static boolean endsWithIgnoreCase(String source, String suffix) {\n        if (source == suffix) {\n            return true;\n        }\n        if (source == null || suffix == null) {\n            return false;\n        }\n        int startIndex = source.length() - suffix.length();\n        if (startIndex < 0) {\n            return false;\n        }\n        return source.regionMatches(true, startIndex, suffix, 0, suffix.length());\n    }\n\n    /**\n     * 使用数组中的键值对替换字符串. 算法将每个在字符串中找的的key替换成对应value.\n     * 数组的构造类似 {key1, value1, key2, value2...}.\n     *\n     * @param source        source字符串.\n     * @param keyValueArray 包含键值对的数组.\n     * @return 被替换了的字符串，如果没有找到任意key则返回source.\n     */\n    public static String replaceWith(String source, Object... keyValueArray) {\n        if (TextUtils.isEmpty(source)) {\n            return source;\n        }\n        if (keyValueArray.length % 2 != 0) {\n            throw new IllegalArgumentException(\"key value array not valid\");\n        }\n        StringBuilder sb = null;\n        for (int i = 0; i < keyValueArray.length; i += 2) {\n            String key = String.valueOf(keyValueArray[i]);\n            String value = String.valueOf(keyValueArray[i + 1]);\n            int index = sb != null ? sb.indexOf(key) : source.indexOf(key);\n            while (index >= 0) {\n                if (sb == null) {\n                    sb = new StringBuilder(source);\n                }\n                sb.replace(index, index + key.length(), value);\n                index = sb.indexOf(key, index + value.length());\n            }\n        }\n        return sb != null ? sb.toString() : source;\n    }\n\n    /**\n     * 使用数组中的键值对替换StringBuilder. 算法将每个在字符串中找的的key替换成对应value.\n     * 数组的构造类似 {key1, value1, key2, value2...}.\n     *\n     * @param source        source StringBuilder.\n     * @param keyValueArray 包含键值对的数组.\n     * @return 被处理过的StringBuilder.\n     */\n    public static StringBuilder replaceWith(StringBuilder source, Object... keyValueArray) {\n        if (TextUtils.isEmpty(source)) {\n            return source;\n        }\n        if (keyValueArray.length % 2 != 0) {\n            throw new IllegalArgumentException(\"key value array not valid\");\n        }\n        for (int i = 0; i < keyValueArray.length; i += 2) {\n            String key = String.valueOf(keyValueArray[i]);\n            String value = String.valueOf(keyValueArray[i + 1]);\n            int index = source.indexOf(key);\n            while (index >= 0) {\n                source.replace(index, index + key.length(), value);\n                index = source.indexOf(key, index + value.length());\n            }\n        }\n        return source;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/ThreadUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.util.Printer;\n\nimport java.util.ArrayList;\nimport java.util.LinkedList;\nimport java.util.List;\nimport java.util.WeakHashMap;\nimport java.util.concurrent.atomic.AtomicBoolean;\n\n/**\n * Created by wukewei on 16/7/24.\n */\npublic class ThreadUtils {\n    /**\n     * Map to remember looper' printer wrappers. Use WeakHashMap to avoid\n     * hold looper instance permanently.\n     */\n    private final static WeakHashMap<Looper, PrinterWrapper> sLooperPrinters =\n            new WeakHashMap<Looper, PrinterWrapper>();\n    private static Thread sMainThread = Looper.getMainLooper().getThread();\n    private static Handler sMainHandler = new Handler(Looper.getMainLooper());\n\n    private ThreadUtils() {\n        // static usage.\n    }\n\n    /**\n     * <p>Causes the Runnable to be added to the <b>MAIN</b> message queue.\n     * The runnable will be run on the user interface thread.</p>\n     *\n     * @param r The Runnable that will be executed.\n     * @see #postDelayed\n     * @see #removeCallbacks\n     */\n    public static void post(Runnable r) {\n        sMainHandler.post(r);\n    }\n\n    /**\n     * <p>Causes the Runnable to be added to the <b>MAIN</b> message queue, to be run\n     * after the specified amount of time elapses.\n     * The runnable will be run on the user interface thread.</p>\n     *\n     * @param r           The Runnable that will be executed.\n     * @param delayMillis The delay (in milliseconds) until the Runnable\n     *                    will be executed.\n     * @see #post\n     * @see #removeCallbacks\n     */\n    public static void postDelayed(Runnable r, long delayMillis) {\n        sMainHandler.postDelayed(r, delayMillis);\n    }\n\n    /**\n     * <p>Removes the specified Runnable from the <b>MAIN</b> message queue.</p>\n     *\n     * @param r The Runnable to remove from the message handling queue\n     * @see #post\n     * @see #postDelayed\n     */\n    public static void removeCallbacks(Runnable r) {\n        sMainHandler.removeCallbacks(r);\n    }\n\n    /**\n     * Run this runnable in  <b>MAIN</b> ui thread.\n     *\n     * @param runnable Runnable to run.\n     */\n    public static void runOnUiThread(Runnable runnable) {\n        if (isMainThread()) {\n            runnable.run();\n        } else {\n            post(runnable);\n        }\n    }\n\n    /**\n     * Whether current thread is <b>MAIN</b> ui thread.\n     */\n    public static boolean isMainThread() {\n        return sMainThread == Thread.currentThread();\n    }\n\n    /**\n     * Get the <b>MAIN</b> handler.\n     *\n     * @return Main handler.\n     */\n    public static Handler getMainHandler() {\n        return sMainHandler;\n    }\n\n    /**\n     * Add a printer to current thread's looper.\n     *\n     * @param printer Looper printer.\n     */\n    public static void addLooperPrinter(Printer printer) {\n        addLooperPrinter(Looper.myLooper(), printer);\n    }\n\n    /**\n     * Add a printer to corresponding looper.\n     *\n     * @param looper  Looper.\n     * @param printer Looper printer.\n     */\n    public static void addLooperPrinter(Looper looper, Printer printer) {\n        if (looper == null) {\n            throw new RuntimeException(\"null looper\");\n        }\n        PrinterWrapper wrapper;\n        synchronized (sLooperPrinters) {\n            wrapper = sLooperPrinters.get(looper);\n            if (wrapper == null) {\n                wrapper = new PrinterWrapper();\n                sLooperPrinters.put(looper, wrapper);\n                // set looper' message logging.\n                looper.setMessageLogging(wrapper);\n            }\n        }\n        wrapper.add(printer);\n    }\n\n    /**\n     * Printer wrapper which allows multiple printers.\n     */\n    final static class PrinterWrapper implements Printer {\n\n        // wrapped printers, can ONLY be accessed within #println (thus corresponding looper thread).\n        private final List<Printer> mWrappedPrinters = new ArrayList<Printer>();\n        // pending printers, which is used to hold pending printers (waiting to be wrapped).\n        private final List<Printer> mPendingPrinters = new LinkedList<Printer>();\n        private final AtomicBoolean mHasPendingPrinter = new AtomicBoolean(false);\n\n        PrinterWrapper() {\n        }\n\n        @Override\n        public void println(String x) {\n            // deal with pending printer, try to avoid synchronize.\n            if (mHasPendingPrinter.getAndSet(false)) {\n                synchronized (mPendingPrinters) {\n                    mWrappedPrinters.addAll(mPendingPrinters);\n                    mPendingPrinters.clear();\n                }\n            }\n            // print.\n            for (Printer printer : mWrappedPrinters) {\n                printer.println(x);\n            }\n        }\n\n        public void add(Printer printer) {\n            synchronized (mPendingPrinters) {\n                mPendingPrinters.add(printer);\n            }\n            mHasPendingPrinter.set(true);\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/ToashUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.support.annotation.Nullable;\nimport android.view.Gravity;\nimport android.view.View;\nimport android.view.Window;\nimport android.widget.Toast;\n\n/**\n * Created by wukewei on 16/7/24.\n */\npublic final class ToashUtils {\n    private static final int LENGTH_SHORT = Toast.LENGTH_SHORT;\n    private static final int LENGTH_LONG = Toast.LENGTH_LONG;\n\n    private final static int DEFAULT_GRAVITY = Gravity.CENTER_HORIZONTAL | Gravity.BOTTOM;\n\n    private final static Singleton<Toast, Context> sToast = new Singleton<Toast, Context>() {\n        @Override\n        protected Toast create(Context context) {\n            if (context == null || context.getApplicationContext() == null) {\n                return null;\n            }\n            try {\n                return Toast.makeText(context.getApplicationContext(), null, LENGTH_SHORT);\n            } catch (Throwable e) {\n                return null;\n            }\n        }\n    };\n\n    private ToashUtils() {\n\n    }\n\n    /**\n     * Get the singleton instance of toast.\n     *\n     * @param context Application or activity context.\n     * @return Singleton instance of toast.\n     */\n    public static Toast get(Context context) {\n        return sToast.get(context);\n    }\n\n    /**\n     * Show application or activity level toast.\n     *\n     * @param context Application or activity context.\n     * @param resId   The resource text to show.  Can be formatted text.\n     */\n    public static void show(Context context, int resId) {\n        show(context, resId, LENGTH_SHORT);\n    }\n\n    /**\n     * Show application or activity level toast.\n     *\n     * @param context Application or activity context.\n     * @param msg     The text to show.  Can be formatted text.\n     */\n    public static void show(Context context, CharSequence msg) {\n        show(context, msg, LENGTH_SHORT);\n    }\n\n    /**\n     * Show application or activity level toast.\n     *\n     * @param context  Application or activity context.\n     * @param resId    The resource text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     */\n    public static void show(Context context, int resId, int duration) {\n        show(context, resId, duration, DEFAULT_GRAVITY);\n    }\n\n    /**\n     * Show application or activity level toast.\n     *\n     * @param context  Application or activity context.\n     * @param msg      The text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     */\n    public static void show(Context context, CharSequence msg, int duration) {\n        show(context, msg, duration, DEFAULT_GRAVITY);\n    }\n\n    /**\n     * Show application or activity level toast.\n     *\n     * @param context  Application or activity context.\n     * @param resId    The resource text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     * @param gravity  The gravity when display the message. See constant defined in {@link Gravity}.\n     */\n    public static void show(Context context, int resId, int duration, int gravity) {\n        show(context, resId == 0 ? null : getString(context, resId), duration, gravity);\n    }\n\n    /**\n     * Show application or activity level toast.\n     *\n     * @param context  Application or activity context.\n     * @param msg      The text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     * @param gravity  The gravity when display the message. See constant defined in {@link Gravity}.\n     */\n    public static void show(Context context, final CharSequence msg, final int duration, final int gravity) {\n        if (msg == null || msg.length() == 0) {\n            return;\n        }\n        if (!shouldShow(context)) {\n            return;\n        }\n        final Context appContext = context.getApplicationContext();\n        if (ThreadUtils.isMainThread()) {\n            showImmediately(appContext, msg, duration, gravity);\n        } else {\n            ThreadUtils.runOnUiThread(new Runnable() {\n                @Override\n                public void run() {\n                    showImmediately(appContext, msg, duration, gravity);\n                }\n            });\n        }\n    }\n\n    /**\n     * Show activity level toast.\n     *\n     * @param activity Activity.\n     * @param resId    The resource text to show.  Can be formatted text.\n     */\n    public static void show(Activity activity, int resId) {\n        show(activity, resId, LENGTH_SHORT);\n    }\n\n    /**\n     * Show activity level toast.\n     *\n     * @param activity Activity, can be null.\n     * @param msg      The text to show.  Can be formatted text.\n     */\n    public static void show(@Nullable Activity activity, CharSequence msg) {\n        show(activity, msg, LENGTH_SHORT);\n    }\n\n    /**\n     * Show activity level toast.\n     *\n     * @param activity Activity.\n     * @param resId    The resource text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     */\n    public static void show(@Nullable Activity activity, int resId, int duration) {\n        show(activity, resId == 0 ? null : getString(activity, resId), duration, DEFAULT_GRAVITY);\n    }\n\n    /**\n     * Show activity level toast.\n     *\n     * @param activity Activity.\n     * @param msg      The text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     */\n    public static void show(@Nullable Activity activity, CharSequence msg, int duration) {\n        show(activity, msg, duration, DEFAULT_GRAVITY);\n    }\n\n    /**\n     * Show activity level toast.\n     *\n     * @param activity Activity.\n     * @param resId    The resource text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     * @param gravity  The gravity when display the message. See constant defined in {@link Gravity}.\n     */\n    public static void show(@Nullable Activity activity, int resId, int duration, int gravity) {\n        show(activity, resId == 0 ? null : getString(activity, resId), duration, gravity);\n    }\n\n    /**\n     * Show activity level toast.\n     *\n     * @param activity Activity.\n     * @param msg      The text to show.  Can be formatted text.\n     * @param duration How long to display the message.  Either {@link Toast#LENGTH_SHORT} or\n     *                 {@link Toast#LENGTH_LONG}\n     * @param gravity  The gravity when display the message. See constant defined in {@link Gravity}.\n     */\n    public static void show(@Nullable Activity activity, final CharSequence msg,\n                            final int duration, final int gravity) {\n        if (msg == null || msg.length() == 0) {\n            return;\n        }\n        if (!shouldShow(activity)) {\n            return;\n        }\n        final Context appContext = activity.getApplicationContext();\n        if (ThreadUtils.isMainThread()) {\n            showImmediately(appContext, msg, duration, gravity);\n        } else {\n            ThreadUtils.runOnUiThread(new Runnable() {\n                @Override\n                public void run() {\n                    showImmediately(appContext, msg, duration, gravity);\n                }\n            });\n        }\n    }\n\n    private static void showImmediately(Context context, CharSequence msg, int duration, int gravity) {\n        Toast toast = sToast.get(context);\n        if (toast != null) {\n            try {\n                toast.setText(msg);\n                toast.setDuration(duration);\n                toast.setGravity(gravity, toast.getXOffset(), toast.getYOffset());\n                toast.show();\n            } catch (Throwable e) {\n                // internal INotificationManager may be null, just catch it and do nothing.\n            }\n        }\n    }\n\n    private static boolean shouldShow(Context context) {\n        if (context == null) {\n            // special situation.\n            return true;\n        }\n        if (context != context.getApplicationContext()) {\n            // fast way: application context.\n            return true;\n        }\n        if (context instanceof Activity) {\n            return shouldShow((Activity) context);\n        }\n        // default.\n        return true;\n    }\n\n    private static boolean shouldShow(Activity activity) {\n        if (activity == null) {\n            // null activity.\n            return false;\n        }\n        if (activity.isFinishing()) {\n            // activity finished.\n            return false;\n        }\n        Window window = activity.getWindow();\n        if (window == null) {\n            // contains no window.\n            return false;\n        }\n        View decorView = window.getDecorView();\n        if (decorView == null || decorView.getVisibility() != View.VISIBLE) {\n            // contains no decor view or decor view is not visible.\n            return false;\n        }\n        return true;\n    }\n\n    private static String getString(Context context, int resId) {\n        return context.getString(resId);\n    }\n\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/utils/ViewUtils.java",
    "content": "package com.wkw.common_lib.utils;\n\nimport android.app.Activity;\nimport android.content.Context;\nimport android.content.ContextWrapper;\nimport android.content.res.Resources;\nimport android.graphics.Bitmap;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build;\nimport android.util.DisplayMetrics;\nimport android.util.Log;\nimport android.util.SparseArray;\nimport android.util.TypedValue;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.view.ViewParent;\nimport android.view.WindowManager;\nimport android.view.animation.AlphaAnimation;\nimport android.widget.FrameLayout;\n\nimport com.wkw.common_lib.Ext;\n\nimport java.security.InvalidParameterException;\n\n/**\n * Created by wukewei on 16/7/24.\n */\npublic final class ViewUtils {\n    private final static boolean DEBUG = false;\n\n    private final static Object TAG_DECORATE = new Object();\n    static private float density = -1;\n    static private int screenWidth = -1;\n    static private int screenHeight = -1;\n\n    static {\n        DisplayMetrics metris = Ext.getContext().getResources().getDisplayMetrics();\n        density = metris.density;\n        if (metris.widthPixels < metris.heightPixels) {\n            screenWidth = metris.widthPixels;\n            screenHeight = metris.heightPixels;\n        } else {   // 部分机器使用application的context宽高反转\n            screenHeight = metris.widthPixels;\n            screenWidth = metris.heightPixels;\n            Log.d(\"ViewUtils\", \"screenHeight:\" + screenHeight + \",screenWidth:\" + screenWidth);\n        }\n    }\n\n    private ViewUtils() {\n        // static use.\n    }\n\n    public static <T extends View> T findById(View view, int id) {\n        return (T) view.findViewById(id);\n    }\n\n    /**\n     * 防止控件被连续误点击的实用方法，传入要保护的时间，在此时间内将不可被再次点击\n     */\n    public static void preventViewMultipleClick(final View v, int protectionMilliseconds) {\n        v.setClickable(false);\n        v.setEnabled(false);\n        v.postDelayed(new Runnable() {\n            @Override\n            public void run() {\n                v.setClickable(true);\n                v.setEnabled(true);\n            }\n        }, protectionMilliseconds);\n    }\n\n    /**\n     * Helper to set tag. Notice, do <em>NOT</em> use {@link android.view.View#setTag}\n     * or {@link android.view.View#getTag} after this. Use {@link #getTag(android.view.View)} instead.\n     */\n    public static void setTag(View view, final Object tag) {\n        setTagInternal(view, 0, tag, true);\n    }\n\n    /**\n     * Helper to get tag of view.\n     */\n    public static Object getTag(View view) {\n        return getTagInternal(view, 0);\n    }\n\n    /**\n     * Helper to set tag with key-value pair. Notice, do <em>NOT</em> use {@link android.view.View#setTag}\n     * or {@link android.view.View#getTag} after this. Use {@link #getTag(android.view.View, int)} instead.\n     */\n    public static void setTag(View view, int key, final Object tag) {\n        setTagInternal(view, key, tag, false);\n    }\n\n    /**\n     * Helper to get tag of specific key..\n     */\n    public static Object getTag(View view, int key) {\n        return getTagInternal(view, key);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static void setTagInternal(View view, int key, final Object tag, boolean ignoreKey) {\n        if (view == null) {\n            return;\n        }\n        if (!ignoreKey) {\n            // If the package id is 0x00 or 0x01, it's either an undefined package\n            // or a framework id\n            if ((key >>> 24) < 2) {\n                throw new IllegalArgumentException(\"The key must be an application-specific \"\n                        + \"resource id.\");\n            }\n        }\n\n        Object viewTag = view.getTag();\n        if (viewTag == null || !(viewTag instanceof SparseArray)) {\n            viewTag = new SparseArray<Object>();\n        }\n        SparseArray<Object> tagArray = (SparseArray<Object>) viewTag;\n        tagArray.put(key, tag);\n        view.setTag(tagArray);\n    }\n\n    @SuppressWarnings(\"unchecked\")\n    private static Object getTagInternal(View view, int key) {\n        if (view == null) {\n            return null;\n        }\n        Object viewTag = view.getTag();\n        if (viewTag == null || !(viewTag instanceof SparseArray)) {\n            return null;\n        }\n        SparseArray<Object> tagArray = (SparseArray<Object>) viewTag;\n        return tagArray.get(key);\n    }\n\n    /**\n     * Decorate a decor view on corresponding host view.\n     *\n     * @param hostView  host view to be decorated with.\n     * @param decorView decor view.\n     * @param gravity   gravity of decor view.\n     */\n    public static void decorate(View hostView, View decorView, int gravity) {\n        decorate(hostView, decorView, gravity, 0, 0, 0, 0);\n    }\n\n    /**\n     * Decorate a decor view on corresponding host view.\n     *\n     * @param hostView     host view to be decorated with.\n     * @param decorView    decor view.\n     * @param gravity      gravity of decor view.\n     * @param leftMargin   left margin of decor view.\n     * @param topMargin    top margin of decor view.\n     * @param rightMargin  right margin of decor view.\n     * @param bottomMargin bottom margin of decor view.\n     */\n    public static void decorate(View hostView, View decorView, int gravity, int leftMargin, int topMargin, int rightMargin, int bottomMargin) {\n        if (hostView == null || decorView == null) {\n            return;\n        }\n        ViewParent parent = hostView.getParent();\n        if (parent == null) {\n            if (DEBUG) {\n                throw new IllegalStateException(\"host \" + hostView + \" not attached to parent\");\n            }\n            return;\n        }\n        if (!(parent instanceof ViewGroup)) {\n            if (DEBUG) {\n                throw new InvalidParameterException(\"host \" + hostView + \" has invalid parent \" + parent);\n            }\n            return;\n        }\n\n        if (decorView.getParent() != null) {\n            if (DEBUG) {\n                throw new IllegalStateException(\"decorate \" + decorView + \" has already be added to a ViewParent \" + decorView.getParent());\n            }\n            return;\n        }\n\n        // generate layout params, before modify the host view's layout params.\n        FrameLayout.LayoutParams hostLp = generateHostLayoutParams(hostView);\n        FrameLayout.LayoutParams decorLp = generateDecorLayoutParams(gravity, leftMargin, topMargin, rightMargin, bottomMargin);\n\n        ViewGroup hostGroup = (ViewGroup) parent;\n        FrameLayout decorContainer;\n        if ((hostGroup instanceof FrameLayout) && getTag(hostView) == TAG_DECORATE) {\n            decorContainer = (FrameLayout) hostGroup;\n        } else {\n            decorContainer = new DecorateContainer(hostGroup.getContext(), hostView);\n            // decorate container should re-use the layout params and index as host view.\n            int index = computeChildIndex(hostGroup, hostView);\n            ViewGroup.LayoutParams lp = hostView.getLayoutParams();\n            // decorate container should wrap it's content (host and decorate view).\n            lp.width = ViewGroup.LayoutParams.WRAP_CONTENT;\n            lp.height = ViewGroup.LayoutParams.WRAP_CONTENT;\n            // remove host view & add decorate container.\n            hostGroup.removeView(hostView);\n            hostGroup.addView(decorContainer, index, lp);\n            // tag for recognise.\n            setTag(decorContainer, TAG_DECORATE);\n        }\n\n        // remove all existing decorates.\n        decorContainer.removeAllViews();\n\n        // add host & decorate view.\n        if (hostLp != null) {\n            decorContainer.addView(hostView, hostLp);\n        }\n        if (decorLp != null) {\n            decorContainer.addView(decorView, decorLp);\n        }\n    }\n\n    private static FrameLayout.LayoutParams generateHostLayoutParams(View hostView) {\n        if (hostView == null) {\n            return null;\n        }\n        FrameLayout.LayoutParams lp = newLayoutParams(hostView.getLayoutParams());\n        // host layout should contains no margin, it's container already preserves.\n        lp.leftMargin = lp.rightMargin = lp.topMargin = lp.bottomMargin = 0;\n        return lp;\n    }\n\n    private static FrameLayout.LayoutParams generateDecorLayoutParams(int gravity, int leftMargin, int topMargin, int rightMargin, int bottomMargin) {\n        FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);\n        lp.gravity = gravity;\n        lp.leftMargin = leftMargin;\n        lp.topMargin = topMargin;\n        lp.rightMargin = rightMargin;\n        lp.bottomMargin = bottomMargin;\n        return lp;\n    }\n\n    private static FrameLayout.LayoutParams newLayoutParams(ViewGroup.LayoutParams source) {\n        if (source == null) {\n            return null;\n        }\n        if (source instanceof ViewGroup.MarginLayoutParams) {\n            return new FrameLayout.LayoutParams((ViewGroup.MarginLayoutParams) source);\n        } else {\n            return new FrameLayout.LayoutParams(source);\n        }\n    }\n\n    private static int computeChildIndex(ViewGroup parent, View child) {\n        if (parent == null || child == null) {\n            return -1;\n        }\n        int index = 0;\n        int count = parent.getChildCount();\n        for (; index < count; index++) {\n            if (parent.getChildAt(index) == child) {\n                break;\n            }\n        }\n        return (index >= 0 && index < count) ? index : -1;\n    }\n\n    /**\n     * Capture corresponding view.\n     *\n     * @param view view to capture.\n     */\n    public static Bitmap capture(View view) {\n        view.buildDrawingCache();\n        Bitmap drawingCache = view.getDrawingCache();\n        if (drawingCache == null) {\n            return null;\n        }\n        Context context = view.getContext();\n        WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);\n        DisplayMetrics outMetrics = new DisplayMetrics();\n        wm.getDefaultDisplay().getMetrics(outMetrics);\n        Bitmap bitmap = Bitmap.createBitmap(drawingCache, 0, 0,\n                Math.min(outMetrics.widthPixels, drawingCache.getWidth()),\n                Math.min(outMetrics.heightPixels, drawingCache.getHeight()));\n        if (!view.isDrawingCacheEnabled()) {\n            view.destroyDrawingCache();\n        }\n        return bitmap;\n    }\n\n    // 支持系统设置的字体大中小变化\n    public static float getSpValue(float value) {\n        return TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, value,\n                Ext.getContext().getResources().getDisplayMetrics());\n\n    }\n\n    public static boolean isChildOf(View c, View p) {\n        if (c == p) {\n            return true;\n        } else if (p instanceof ViewGroup) {\n            int count = ((ViewGroup) p).getChildCount();\n            for (int i = 0; i < count; i++) {\n                View ci = ((ViewGroup) p).getChildAt(i);\n                if (isChildOf(c, ci)) {\n                    return true;\n                }\n            }\n        }\n        return false;\n    }\n\n    public static void getChildPos(View child, View parent, int[] posContainer) {\n        if (posContainer == null || posContainer.length < 2) {\n            return;\n        }\n        int x = 0;\n        int y = 0;\n        View vc = child;\n        while (vc.getParent() != null) {\n            x += vc.getLeft();\n            y += vc.getTop();\n            if (vc.getParent() == parent) {\n                posContainer[0] = x;\n                posContainer[1] = y;\n                if (posContainer.length >= 4) {\n                    posContainer[2] = vc.getMeasuredWidth();\n                    posContainer[3] = vc.getMeasuredHeight();\n                }\n                break;\n            }\n            try {\n                vc = (View) vc.getParent();\n                if (posContainer.length >= 4) {\n                    posContainer[2] = vc.getMeasuredWidth();\n                    posContainer[3] = vc.getMeasuredHeight();\n                }\n            } catch (ClassCastException e) {\n                break;\n            }\n        }\n        if (parent == null) {\n            posContainer[0] = x;\n            posContainer[1] = y;\n        }\n    }\n\n    public static String getActivityName(Context ctx) {\n        Context c = ctx;\n        if (!(ctx instanceof Activity) && (ctx instanceof ContextWrapper)) {\n            c = ((ContextWrapper) ctx).getBaseContext();\n        }\n        return c.getClass().getName();\n    }\n\n    public static int getStatusBarHeight(Context context) {\n        int result = 0;\n        Resources resources = context.getResources();\n        int resourceId = resources.getIdentifier(\"status_bar_height\", \"dimen\", \"android\");\n        if (resourceId > 0) {\n            result = resources.getDimensionPixelSize(resourceId);\n        }\n        return result;\n    }\n\n    public static float getDensity() {\n        return density;\n    }\n\n    public static int getScreenWidth() {\n        return screenWidth;\n    }\n\n    public static int getScreenHeight() {\n        return screenHeight;\n    }\n\n    /**\n     * Converts a dp value to a px value\n     *\n     * @param dp the dp value\n     */\n    public static int dpToPx(float dp) {\n        return Math.round(dp * getDensity());\n    }\n\n    public static int pxToDp(float px) {\n        return Math.round(px / getDensity());\n    }\n\n    public static int spToPx(float sp) {\n        final float fontScale = Ext.getContext().getResources().getDisplayMetrics().scaledDensity;\n        return (int) (sp * fontScale + 0.5f);\n    }\n\n    public static int pxTosp(float px) {\n        final float fontScale = Ext.getContext().getResources().getDisplayMetrics().scaledDensity;\n        return (int) (px / fontScale + 0.5f);\n    }\n\n    /**\n     * 在xml里设置android:alpha对api11以前的系统不起作用，所以在代码里获取并设置透明度\n     */\n    public static void setAlpha(View view, float alphaValue) {\n        if (view == null) {\n            return;\n        }\n        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {\n            view.setAlpha(alphaValue);\n        } else {\n            AlphaAnimation alpha = new AlphaAnimation(alphaValue, alphaValue);\n            alpha.setDuration(0);\n            alpha.setFillAfter(true);\n            view.startAnimation(alpha);\n        }\n    }\n\n    /**\n     * 兼容4.1前后的设置view background drawable的方法\n     */\n    public static void setViewBackground(View v, Drawable drawable) {\n        if (v == null) {\n            return;\n        }\n\n        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {\n            v.setBackgroundDrawable(drawable);\n        } else {\n            v.setBackground(drawable);\n        }\n    }\n\n    private static class DecorateContainer extends FrameLayout {\n\n        private final View mHostView;\n\n        public DecorateContainer(Context context, View hostView) {\n            super(context);\n            mHostView = hostView;\n        }\n\n        @Override\n        public int getVisibility() {\n            // decorate container share the visibility with host view.\n            return mHostView != null ? mHostView.getVisibility() : super.getVisibility();\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/ClearEditText.java",
    "content": "package com.wkw.common_lib.widget;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.graphics.drawable.Drawable;\nimport android.support.v7.widget.AppCompatEditText;\nimport android.text.Editable;\nimport android.text.TextWatcher;\nimport android.util.AttributeSet;\nimport android.view.MotionEvent;\nimport android.view.View;\nimport android.view.animation.Animation;\nimport android.view.animation.CycleInterpolator;\nimport android.view.animation.TranslateAnimation;\nimport com.wkw.common_lib.R;\n\n/**\n * Created by wukewei on 16/12/3.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class ClearEditText extends AppCompatEditText\n    implements View.OnFocusChangeListener, TextWatcher {\n\n    private Drawable mClearDrawable;\n\n    public ClearEditText(Context context) {\n        this(context, null);\n    }\n\n    public ClearEditText(Context context, AttributeSet attrs) {\n        this(context, attrs, R.attr.editTextStyle);\n    }\n\n    public ClearEditText(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(context, attrs);\n    }\n\n    private void init(Context context, AttributeSet attrs) {\n        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.ClearEditText);\n\n        mClearDrawable = a.getDrawable(R.styleable.ClearEditText_clearDrawable);\n\n        if (mClearDrawable == null) {\n            mClearDrawable = getResources().getDrawable(R.drawable.ic_delete);\n        }\n        mClearDrawable.setBounds(0, 0, mClearDrawable.getIntrinsicWidth(), mClearDrawable.getIntrinsicHeight());\n\n        setClearIconVisible(false);\n        setOnFocusChangeListener(this);\n        addTextChangedListener(this);\n    }\n\n    /**\n     * 因为我们不能直接给EditText设置点击事件，所以我们用记住我们按下的位置来模拟点击事件\n     * 当我们按下的位置 在  EditText的宽度 - 图标到控件右边的间距 - 图标的宽度  和\n     * EditText的宽度 - 图标到控件右边的间距之间我们就算点击了图标，竖直方向没有考虑\n     */\n    @Override\n    public boolean onTouchEvent(MotionEvent event) {\n        if (getCompoundDrawables()[2] != null) {\n            if (event.getAction() == MotionEvent.ACTION_UP) {\n                boolean touchable = event.getX() > (getWidth()\n                    - getPaddingRight() - mClearDrawable.getIntrinsicWidth())\n                    && (event.getX() < ((getWidth() - getPaddingRight())));\n                if (touchable) {\n                    this.setText(\"\");\n                }\n            }\n        }\n\n        return super.onTouchEvent(event);\n    }\n\n    /**\n     * 当ClearEditText焦点发生变化的时候，判断里面字符串长度设置清除图标的显示与隐藏\n     */\n    @Override\n    public void onFocusChange(View v, boolean hasFocus) {\n        if (hasFocus) {\n            setClearIconVisible(getText().length() > 0);\n        } else {\n            setClearIconVisible(false);\n        }\n    }\n\n    /**\n     * 设置清除图标的显示与隐藏，调用setCompoundDrawables为EditText绘制上去\n     *\n     * @param visible true if visible\n     */\n    private void setClearIconVisible(boolean visible) {\n        Drawable right = visible ? mClearDrawable : null;\n        setCompoundDrawables(getCompoundDrawables()[0],\n            getCompoundDrawables()[1], right, getCompoundDrawables()[3]);\n    }\n\n    /**\n     * 当输入框里面内容发生变化的时候回调的方法\n     */\n    @Override\n    public void onTextChanged(CharSequence s, int start, int count, int after) {\n        super.onTextChanged(s, start, count, after);\n        setClearIconVisible(hasFocus() && s.length() > 0);\n    }\n\n    @Override\n    public void beforeTextChanged(CharSequence s, int start, int count, int after) {\n\n    }\n\n    @Override\n    public void afterTextChanged(Editable s) {\n    }\n\n    /**\n     * 设置晃动动画\n     */\n    public void setShakeAnimation() {\n        setAnimation(shakeAnimation(5));\n    }\n\n    /**\n     * 晃动动画\n     *\n     * @param counts 1秒钟晃动多少下\n     * @return animation generated\n     */\n    public static Animation shakeAnimation(int counts) {\n        Animation translateAnimation = new TranslateAnimation(0, 10, 0, 0);\n        translateAnimation.setInterpolator(new CycleInterpolator(counts));\n        translateAnimation.setDuration(1000);\n        return translateAnimation;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/CustomTabHost.java",
    "content": "package com.wkw.test.tabhost;\n\nimport android.content.Context;\nimport android.content.res.TypedArray;\nimport android.os.Bundle;\nimport android.os.Parcel;\nimport android.os.Parcelable;\nimport android.support.v4.app.Fragment;\nimport android.support.v4.app.FragmentManager;\nimport android.support.v4.app.FragmentTransaction;\nimport android.util.AttributeSet;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.FrameLayout;\nimport android.widget.LinearLayout;\nimport android.widget.TabHost;\nimport android.widget.TabWidget;\nimport java.util.ArrayList;\n\n/**\n * Created by wukewei on 17/2/21.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class CustomTabHost extends TabHost implements TabHost.OnTabChangeListener {\n    private final ArrayList<TabInfo> mTabs = new ArrayList<TabInfo>();\n    private FrameLayout mRealTabContent;\n    private Context mContext;\n    private FragmentManager mFragmentManager;\n    private int mContainerId;\n    private OnTabChangeListener mOnTabChangeListener;\n    private TabInfo mLastTab;\n    private boolean mAttached;\n\n    static final class TabInfo {\n        private final String tag;\n        private final Class<?> clss;\n        private final Bundle args;\n        private Fragment fragment;\n\n        TabInfo(String _tag, Class<?> _class, Bundle _args) {\n            tag = _tag;\n            clss = _class;\n            args = _args;\n        }\n    }\n\n    static class DummyTabFactory implements TabContentFactory {\n        private final Context mContext;\n\n        public DummyTabFactory(Context context) {\n            mContext = context;\n        }\n\n        @Override\n        public View createTabContent(String tag) {\n            View v = new View(mContext);\n            v.setMinimumWidth(0);\n            v.setMinimumHeight(0);\n            return v;\n        }\n    }\n\n    static class SavedState extends BaseSavedState {\n        String curTab;\n\n        SavedState(Parcelable superState) {\n            super(superState);\n        }\n\n        private SavedState(Parcel in) {\n            super(in);\n            curTab = in.readString();\n        }\n\n        @Override\n        public void writeToParcel(Parcel out, int flags) {\n            super.writeToParcel(out, flags);\n            out.writeString(curTab);\n        }\n\n        @Override\n        public String toString() {\n            return \"FragmentTabHost.SavedState{\"\n                + Integer.toHexString(System.identityHashCode(this))\n                + \" curTab=\" + curTab + \"}\";\n        }\n\n        public static final Creator<SavedState> CREATOR\n            = new Creator<SavedState>() {\n            public SavedState createFromParcel(Parcel in) {\n                return new SavedState(in);\n            }\n\n            public SavedState[] newArray(int size) {\n                return new SavedState[size];\n            }\n        };\n    }\n\n    public CustomTabHost(Context context) {\n        // Note that we call through to the version that takes an AttributeSet,\n        // because the simple Context construct can result in a broken object!\n        super(context, null);\n        initFragmentTabHost(context, null);\n    }\n\n    public CustomTabHost(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        initFragmentTabHost(context, attrs);\n    }\n\n    private void initFragmentTabHost(Context context, AttributeSet attrs) {\n        TypedArray a = context.obtainStyledAttributes(attrs,\n            new int[]{android.R.attr.inflatedId}, 0, 0);\n        mContainerId = a.getResourceId(0, 0);\n        a.recycle();\n\n        super.setOnTabChangedListener(this);\n    }\n\n    private void ensureHierarchy(Context context) {\n        // If owner hasn't made its own view hierarchy, then as a convenience\n        // we will construct a standard one here.\n        if (findViewById(android.R.id.tabs) == null) {\n            LinearLayout ll = new LinearLayout(context);\n            ll.setOrientation(LinearLayout.VERTICAL);\n            addView(ll, new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));\n\n            TabWidget tw = new TabWidget(context);\n            tw.setId(android.R.id.tabs);\n            tw.setOrientation(TabWidget.HORIZONTAL);\n            ll.addView(tw, new LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT, 0));\n\n            FrameLayout fl = new FrameLayout(context);\n            fl.setId(android.R.id.tabcontent);\n            ll.addView(fl, new LinearLayout.LayoutParams(0, 0, 0));\n\n            mRealTabContent = fl = new FrameLayout(context);\n            mRealTabContent.setId(mContainerId);\n            ll.addView(fl, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, 0, 1));\n        }\n    }\n\n    /**\n     * @deprecated Don't call the original TabHost setup, you must instead\n     * call {@link #setup(Context, FragmentManager)} or\n     * {@link #setup(Context, FragmentManager, int)}.\n     */\n    @Override\n    @Deprecated\n    public void setup() {\n        throw new IllegalStateException(\n            \"Must call setup() that takes a Context and FragmentManager\");\n    }\n\n    public void setup(Context context, FragmentManager manager) {\n        ensureHierarchy(context);  // Ensure views required by super.setup()\n        super.setup();\n        mContext = context;\n        mFragmentManager = manager;\n        ensureContent();\n    }\n\n    public void setup(Context context, FragmentManager manager, int containerId) {\n        ensureHierarchy(context);  // Ensure views required by super.setup()\n        super.setup();\n        mContext = context;\n        mFragmentManager = manager;\n        mContainerId = containerId;\n        ensureContent();\n        mRealTabContent.setId(containerId);\n\n        // We must have an ID to be able to save/restore our state.  If\n        // the owner hasn't set one at this point, we will set it ourself.\n        if (getId() == View.NO_ID) {\n            setId(android.R.id.tabhost);\n        }\n    }\n\n    private void ensureContent() {\n        if (mRealTabContent == null) {\n            mRealTabContent = (FrameLayout) findViewById(mContainerId);\n            if (mRealTabContent == null) {\n                throw new IllegalStateException(\n                    \"No tab content FrameLayout found for id \" + mContainerId);\n            }\n        }\n    }\n\n    @Override\n    public void setOnTabChangedListener(OnTabChangeListener l) {\n        mOnTabChangeListener = l;\n    }\n\n    public void addTab(TabSpec tabSpec, Class<?> clss, Bundle args) {\n        tabSpec.setContent(new DummyTabFactory(mContext));\n        String tag = tabSpec.getTag();\n\n        TabInfo info = new TabInfo(tag, clss, args);\n\n        if (mAttached) {\n            // If we are already attached to the window, then check to make\n            // sure this tab's fragment is inactive if it exists.  This shouldn't\n            // normally happen.\n            info.fragment = mFragmentManager.findFragmentByTag(tag);\n            if (info.fragment != null && !info.fragment.isDetached()) {\n                FragmentTransaction ft = mFragmentManager.beginTransaction();\n                //                ft.detach(info.fragment);\n                ft.hide(info.fragment);\n                ft.commitAllowingStateLoss();\n            }\n        }\n\n        mTabs.add(info);\n        addTab(tabSpec);\n    }\n\n    @Override\n    protected void onAttachedToWindow() {\n        super.onAttachedToWindow();\n\n        String currentTab = getCurrentTabTag();\n\n        // Go through all tabs and make sure their fragments match\n        // the correct state.\n        FragmentTransaction ft = null;\n        for (int i = 0; i < mTabs.size(); i++) {\n            TabInfo tab = mTabs.get(i);\n            tab.fragment = mFragmentManager.findFragmentByTag(tab.tag);\n            //            if (tab.fragment != null && !tab.fragment.isDetached()) {\n            if (tab.fragment != null) {\n                if (tab.tag.equals(currentTab)) {\n                    // The fragment for this tab is already there and\n                    // active, and it is what we really want to have\n                    // as the current tab.  Nothing to do.\n                    mLastTab = tab;\n                } else {\n                    // This fragment was restored in the active state,\n                    // but is not the current tab.  Deactivate it.\n                    if (ft == null) {\n                        ft = mFragmentManager.beginTransaction();\n                    }\n                    //                    ft.detach(tab.fragment);\n                    ft.hide(tab.fragment);\n                }\n            }\n        }\n\n        // We are now ready to go.  Make sure we are switched to the\n        // correct tab.\n        mAttached = true;\n        ft = doTabChanged(currentTab, ft);\n        if (ft != null) {\n            ft.commitAllowingStateLoss();\n            mFragmentManager.executePendingTransactions();\n        }\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        super.onDetachedFromWindow();\n        mAttached = false;\n    }\n\n    @Override\n    protected Parcelable onSaveInstanceState() {\n        Parcelable superState = super.onSaveInstanceState();\n        SavedState ss = new SavedState(superState);\n        ss.curTab = getCurrentTabTag();\n        return ss;\n    }\n\n    @Override\n    protected void onRestoreInstanceState(Parcelable state) {\n        SavedState ss = (SavedState) state;\n        super.onRestoreInstanceState(ss.getSuperState());\n        setCurrentTabByTag(ss.curTab);\n    }\n\n    @Override\n    public void onTabChanged(String tabId) {\n        if (mAttached) {\n            FragmentTransaction ft = doTabChanged(tabId, null);\n            if (ft != null) {\n                ft.commitAllowingStateLoss();\n            }\n        }\n        if (mOnTabChangeListener != null) {\n            mOnTabChangeListener.onTabChanged(tabId);\n        }\n    }\n\n    private FragmentTransaction doTabChanged(String tabId, FragmentTransaction ft) {\n        TabInfo newTab = null;\n        for (int i = 0; i < mTabs.size(); i++) {\n            TabInfo tab = mTabs.get(i);\n            if (tab.tag.equals(tabId)) {\n                newTab = tab;\n            }\n        }\n        if (newTab == null) {\n            throw new IllegalStateException(\"No tab known for tag \" + tabId);\n        }\n        if (mLastTab != newTab) {\n            if (ft == null) {\n                ft = mFragmentManager.beginTransaction();\n            }\n            if (mLastTab != null) {\n                if (mLastTab.fragment != null) {\n                    ft.hide(mLastTab.fragment);  //detach改为hide\n                }\n            }\n            if (newTab.fragment == null) {\n                newTab.fragment = Fragment.instantiate(mContext,\n                    newTab.clss.getName(), newTab.args);\n                ft.add(mContainerId, newTab.fragment, newTab.tag);\n            } else {\n                ft.show(newTab.fragment); //attach改为show\n            }\n\n            mLastTab = newTab;\n        }\n        return ft;\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/ProgressLayout.java",
    "content": "package com.wkw.common_lib.widget;\n\nimport android.content.Context;\nimport android.util.AttributeSet;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Button;\nimport android.widget.RelativeLayout;\nimport android.widget.TextView;\n\nimport com.wkw.common_lib.R;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * Created by wukewei on 16/6/1.\n */\npublic class ProgressLayout extends RelativeLayout {\n\n    private static final String LOADING_TAG = \"loading_tag\";\n    private static final String ERROR_TAG = \"error_tag\";\n    private static final String NOTDATA_TAG = \"not_data_tag\";\n\n\n    private LayoutParams layoutParams;\n    private LayoutInflater layoutInflater;\n    private RelativeLayout loadingView, errorView, notDataView;\n\n    private Button btn_error, btn_notdata;\n\n    private List<View> contentViews = new ArrayList<>();\n    public ProgressLayout(Context context) {\n        super(context);\n    }\n\n    private enum State {\n        LOADING, CONTENT, ERROR, NOTDATA\n    }\n    private State currentState = State.LOADING;\n\n    public ProgressLayout(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        init(attrs);\n    }\n\n    public ProgressLayout(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n        init(attrs);\n    }\n\n    private void init(AttributeSet attrs) {\n        layoutInflater = (LayoutInflater) getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);\n    }\n\n    @Override\n    public void addView(View child, int index, ViewGroup.LayoutParams params) {\n        super.addView(child, index, params);\n        if (child.getTag() == null || (!child.getTag().equals(LOADING_TAG) && !child.getTag().equals(ERROR_TAG)\n                && !child.getTag().equals(NOTDATA_TAG))) {\n            contentViews.add(child);\n        }\n    }\n\n    @Override\n    protected void onDetachedFromWindow() {\n        super.onDetachedFromWindow();\n        if (btn_error != null) btn_error.setOnClickListener(null);\n        if (btn_notdata != null) btn_error.setOnClickListener(null);\n    }\n\n    public void showLoading() {\n        currentState = State.LOADING;\n        this.showLoadingView();\n        this.hideErrorView();\n        this.hideNotDataView();\n        this.setContentVisibility(false);\n    }\n\n    public void showContent() {\n        currentState = State.CONTENT;\n        this.hideLoadingView();\n        this.hideErrorView();\n        this.hideNotDataView();\n        this.setContentVisibility(true);\n    }\n\n    public void showError(String msg,OnClickListener click) {\n        if (this.isContent()) return;\n        currentState = State.ERROR;\n        this.hideNotDataView();\n        this.hideLoadingView();\n        this.showErrorView(msg);\n        this.btn_error.setOnClickListener(click);\n        this.setContentVisibility(false);\n    }\n\n\n\n    public void showNotData(OnClickListener click) {\n        currentState = State.NOTDATA;\n        this.hideLoadingView();\n        this.hideErrorView();\n        this.showNotDataView();\n        this.btn_notdata.setOnClickListener(click);\n        this.setContentVisibility(false);\n    }\n\n    public boolean isContent() {\n        return currentState == State.CONTENT;\n    }\n\n    private void showLoadingView() {\n        if (loadingView == null) {\n            loadingView = (RelativeLayout) layoutInflater.inflate(R.layout.layout_loading_view, null);\n            loadingView.setTag(LOADING_TAG);\n            layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);\n            layoutParams.addRule(CENTER_IN_PARENT);\n            this.addView(loadingView, layoutParams);\n        } else {\n            loadingView.setVisibility(VISIBLE);\n        }\n    }\n\n    private void showErrorView(String msg) {\n        if (errorView == null) {\n            errorView = (RelativeLayout) layoutInflater.inflate(R.layout.layout_error_view, null);\n            errorView.setTag(ERROR_TAG);\n            btn_error = (Button) errorView.findViewById(R.id.btn_try);\n            ((TextView)errorView.findViewById(R.id.tv_error)).setText(msg);\n            layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);\n            layoutParams.addRule(CENTER_IN_PARENT);\n            this.addView(errorView, layoutParams);\n        } else {\n            errorView.setVisibility(VISIBLE);\n        }\n    }\n\n\n    private void showNotDataView() {\n        if (notDataView == null) {\n            notDataView = (RelativeLayout) layoutInflater.inflate(R.layout.layout_no_data_view, null);\n            notDataView.setTag(ERROR_TAG);\n            btn_notdata = (Button) notDataView.findViewById(R.id.btn_try);\n            layoutParams = new LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT);\n            layoutParams.addRule(CENTER_IN_PARENT);\n            this.addView(notDataView, layoutParams);\n        } else {\n            notDataView.setVisibility(VISIBLE);\n        }\n    }\n\n\n    private void hideLoadingView() {\n        if (loadingView != null && loadingView.getVisibility() != GONE) {\n            loadingView.setVisibility(GONE);\n        }\n    }\n\n    private void hideErrorView() {\n        if (errorView != null && errorView.getVisibility() != GONE) {\n            errorView.setVisibility(GONE);\n        }\n    }\n\n\n    private void hideNotDataView() {\n        if (notDataView != null && notDataView.getVisibility() != GONE) {\n            notDataView.setVisibility(GONE);\n        }\n    }\n\n    private void setContentVisibility(boolean visible) {\n        for (View contentView : contentViews) {\n            contentView.setVisibility(visible ? View.VISIBLE : View.GONE);\n        }\n    }\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/TimerButton.java",
    "content": "package com.wkw.common_lib.widget;\n\nimport android.annotation.TargetApi;\nimport android.content.Context;\nimport android.graphics.drawable.Drawable;\nimport android.os.Build;\nimport android.os.Handler;\nimport android.os.Looper;\nimport android.util.AttributeSet;\nimport android.widget.Button;\n\n/**\n * Created by wukewei on 16/12/4.\n * Email zjwkw1992@163.com\n * GitHub https://github.com/zj-wukewei\n */\n\npublic class TimerButton extends Button {\n\n    private static final long UNIT = 1000;\n\n    private long mDuration;\n    private String mNormalText;\n    private String mTimerTextFormat;\n    private Drawable mEnableBackground;\n    private Drawable mDisableBackground;\n\n    private final Handler mHandler = new Handler(Looper.getMainLooper());\n    private final Runnable mTimerRunnable = new Runnable() {\n        @Override public void run() {\n            if (mDuration <= 0) {\n                setText(mNormalText);\n                setEnabled(true);\n                return;\n            }\n            setText(String.format(mTimerTextFormat, mDuration / UNIT));\n            mDuration -= UNIT;\n            mHandler.postDelayed(mTimerRunnable, UNIT);\n        }\n    };\n\n\n    public TimerButton(Context context) {\n        super(context);\n    }\n\n\n    public TimerButton(Context context, AttributeSet attrs, int defStyleAttr) {\n        super(context, attrs, defStyleAttr);\n    }\n\n\n    public TimerButton(Context context, AttributeSet attrs) {\n        super(context, attrs);\n    }\n\n\n    @TargetApi(Build.VERSION_CODES.LOLLIPOP)\n    public TimerButton(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {\n        super(context, attrs, defStyleAttr, defStyleRes);\n    }\n\n    public void startTimer(String timerTextFormat,String normalText, long duration) {\n        mTimerTextFormat = timerTextFormat;\n        mNormalText = normalText;\n        mDuration = duration;\n        setEnabled(false);\n        mHandler.post(mTimerRunnable);\n    }\n\n    public void setDisableBackground(Drawable disableBackground) {\n        mEnableBackground = getBackground();\n        mDisableBackground = disableBackground;\n    }\n\n    private void setEnableStatus(boolean enable) {\n        setEnabled(enable);\n        if (enable) {\n            setBackgroundDrawable(mEnableBackground);\n        } else {\n            setBackgroundDrawable(mDisableBackground);\n        }\n    }\n\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/DefaultEmptyItem.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\nimport android.text.TextUtils;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ImageView;\nimport android.widget.TextView;\nimport com.wkw.common_lib.R;\n\n/**\n * 默认的空数据视图\n *\n * @author cjj on 16/1/31.\n */\npublic class DefaultEmptyItem extends EmptyItem {\n\n    private TextView mEmptyTextView;\n    private ImageView mEmptyImageView;\n\n    @Override\n    public View onCreateView(ViewGroup parent) {\n        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.rv_with_footer_empty_layout, parent, false);\n        view.setLayoutParams(new ViewGroup.LayoutParams(parent.getMeasuredWidth(), parent.getMeasuredHeight()));\n        mEmptyTextView = (TextView) view.findViewById(R.id.rv_with_footer_empty_title);\n        mEmptyImageView = (ImageView) view.findViewById(R.id.rv_with_footer_empty_icon);\n        return view;\n    }\n\n    @Override\n    public void onBindData(View view) {\n        if (TextUtils.isEmpty(mEmptyText)) {\n            mEmptyTextView.setVisibility(View.GONE);\n        } else {\n            mEmptyTextView.setVisibility(View.VISIBLE);\n            mEmptyTextView.setText(mEmptyText);\n        }\n\n        if (mEmptyIconRes != -1) {\n            mEmptyImageView.setImageResource(mEmptyIconRes);\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/DefaultFootItem.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\nimport android.content.Context;\nimport android.text.TextUtils;\nimport android.view.LayoutInflater;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.ProgressBar;\nimport android.widget.TextView;\nimport com.wkw.common_lib.R;\n\n/**\n * @author cjj\n */\npublic class DefaultFootItem extends FootItem {\n\n    private static final String TAG = \"DefaultFootItem\";\n\n    private ProgressBar mProgressBar;\n    private TextView mLoadingText;\n    private TextView mPullToLoadText;\n    private TextView mEndTextView;\n\n    @Override\n    public View onCreateView(ViewGroup parent) {\n        LayoutInflater inflater = (LayoutInflater) parent.getContext().getSystemService(Context.LAYOUT_INFLATER_SERVICE);\n        View view = inflater.inflate(R.layout.rv_with_footer_loading, parent, false);\n        mProgressBar = (ProgressBar) view.findViewById(R.id.rv_with_footer_loading_progress);\n        mEndTextView = (TextView) view.findViewById(R.id.rv_with_footer_loading_end);\n        mLoadingText = (TextView) view.findViewById(R.id.rv_with_footer_loading_load);\n        mPullToLoadText = (TextView) view.findViewById(R.id.rv_with_footer_loading_pull_to_load);\n        return view;\n    }\n\n    @Override\n    public void onBindData(View view, int state) {\n        if (state == RecyclerViewWithFooter.STATE_LOADING) {\n            if (TextUtils.isEmpty(loadingText)) {\n                showProgressBar(view.getContext().getResources().getString(R.string.rv_with_footer_loading));\n            } else {\n                showProgressBar(loadingText);\n            }\n        } else if (state == RecyclerViewWithFooter.STATE_END) {\n            if (TextUtils.isEmpty(endText)) {\n                showPullToLoad(view.getContext().getResources().getString(R.string.rv_with_footer_empty));\n            } else {\n                showPullToLoad(endText);\n            }\n        } else if (state == RecyclerViewWithFooter.STATE_PULL_TO_LOAD) {\n            if (TextUtils.isEmpty(pullToLoadText)) {\n                showPullToLoad(view.getContext().getResources().getString(R.string.rv_with_footer_pull_load_more));\n            } else {\n                showPullToLoad(pullToLoadText);\n            }\n        }\n    }\n\n    public void showPullToLoad(CharSequence message) {\n        if (mPullToLoadText != null) {\n            mPullToLoadText.setVisibility(View.VISIBLE);\n            if (!TextUtils.isEmpty(message)) {\n                mPullToLoadText.setText(message);\n            }\n        }\n        if (mEndTextView != null) {\n            mEndTextView.setVisibility(View.GONE);\n        }\n        if (mProgressBar != null) {\n            mProgressBar.setVisibility(View.GONE);\n        }\n        if (mLoadingText != null) {\n            mLoadingText.setVisibility(View.GONE);\n        }\n    }\n\n    public void showProgressBar(CharSequence load) {\n        if (mEndTextView != null) {\n            mEndTextView.setVisibility(View.GONE);\n        }\n        if (mProgressBar != null) {\n            mProgressBar.setVisibility(View.VISIBLE);\n        }\n        if (mPullToLoadText != null) {\n            mPullToLoadText.setVisibility(View.GONE);\n        }\n        if (mLoadingText != null) {\n            if (!TextUtils.isEmpty(load)) {\n                mLoadingText.setVisibility(View.VISIBLE);\n                mLoadingText.setText(load);\n            } else {\n                mLoadingText.setVisibility(View.GONE);\n            }\n        }\n    }\n\n    public void showEnd(CharSequence end) {\n        if (mEndTextView != null) {\n            mEndTextView.setVisibility(View.VISIBLE);\n            if (!TextUtils.isEmpty(end)) {\n                mEndTextView.setText(end);\n            }\n        }\n        if (mPullToLoadText != null) {\n            mPullToLoadText.setVisibility(View.GONE);\n        }\n        if (mProgressBar != null) {\n            mProgressBar.setVisibility(View.GONE);\n        }\n        if (mLoadingText != null) {\n            mLoadingText.setVisibility(View.GONE);\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/EmptyFootItem.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\nimport android.view.View;\nimport android.view.ViewGroup;\nimport android.widget.Space;\n\n/**\n * @author markzhai on 16/7/11\n * @version 1.3.0\n */\npublic class EmptyFootItem extends FootItem {\n    @Override\n    public View onCreateView(ViewGroup parent) {\n        return new Space(parent.getContext());\n    }\n\n    @Override\n    public void onBindData(View view, int state) {\n\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/EmptyItem.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\nimport android.view.View;\nimport android.view.ViewGroup;\n\n/**\n * 没数据时候的默认View\n *\n * @author zzz40500 on 16/1/31.\n */\npublic abstract class EmptyItem {\n\n    CharSequence mEmptyText;\n    int mEmptyIconRes = -1;\n\n    abstract View onCreateView(ViewGroup parent);\n\n    abstract void onBindData(View view);\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/FootItem.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\nimport android.view.View;\nimport android.view.ViewGroup;\n\n/**\n * Footer item\n *\n * @author cjj on 2016/1/30.\n */\npublic abstract class FootItem {\n\n    public CharSequence loadingText;\n    public CharSequence endText;\n    public CharSequence pullToLoadText;\n\n    public abstract View onCreateView(ViewGroup parent);\n\n    public abstract void onBindData(View view, int state);\n\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/OnLoadMoreListener.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\n/**\n * Load more interface\n *\n * @author cjj\n */\npublic interface OnLoadMoreListener {\n    void onLoadMore();\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/RecyclerViewUtils.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\nimport android.support.v7.widget.GridLayoutManager;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.support.v7.widget.StaggeredGridLayoutManager;\nimport android.util.Log;\n\n/**\n * 设置rv manager 类型\n *\n * @author cjj\n */\nclass RecyclerViewUtils {\n\n    private static final String TAG = \"RecyclerViewUtils\";\n\n    public static void setVerticalLinearLayout(RecyclerView rv) {\n        LinearLayoutManager layoutManager = new LinearLayoutManager(rv.getContext(), LinearLayoutManager.VERTICAL, false) {\n            @Override\n            public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {\n                try {\n                    super.onLayoutChildren(recycler, state);\n                } catch (IndexOutOfBoundsException e) {\n                    Log.e(TAG, \"meet an IndexOutOfBoundsException in RecyclerView\");\n                }\n            }\n        };\n        rv.setLayoutManager(layoutManager);\n    }\n\n    public static void setGridLayout(final RecyclerView rv, int spanCount) {\n        final GridLayoutManager gridLayoutManager = new GridLayoutManager(rv.getContext(), spanCount, GridLayoutManager.VERTICAL, false) {\n            @Override\n            public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {\n                try {\n                    super.onLayoutChildren(recycler, state);\n                } catch (IndexOutOfBoundsException e) {\n                    Log.e(TAG, \"meet an IndexOutOfBoundsException in RecyclerView\");\n                }\n            }\n        };\n        gridLayoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() {\n            @Override\n            public int getSpanSize(int position) {\n                int viewType = rv.getAdapter().getItemViewType(position);\n                if (viewType < 0) {\n                    return gridLayoutManager.getSpanCount();\n                }\n                return 1;\n            }\n        });\n        rv.setLayoutManager(gridLayoutManager);\n    }\n\n    public static void setStaggeredGridLayoutManager(RecyclerView rv, int spanCount) {\n        StaggeredGridLayoutManager staggeredGridLayoutManager = new StaggeredGridLayoutManager(spanCount, StaggeredGridLayoutManager.VERTICAL) {\n            @Override\n            public void onLayoutChildren(RecyclerView.Recycler recycler, RecyclerView.State state) {\n                try {\n                    super.onLayoutChildren(recycler, state);\n                } catch (IndexOutOfBoundsException e) {\n                    Log.e(RecyclerViewUtils.TAG, \"meet an IndexOutOfBoundsException in RecyclerView\");\n                }\n            }\n        };\n        rv.setLayoutManager(staggeredGridLayoutManager);\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/java/com/wkw/common_lib/widget/loadmore/RecyclerViewWithFooter.java",
    "content": "/*\n * The GPL License (GPL)\n *\n * Copyright (c) 2016 Moduth (https://github.com/moduth)\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage com.wkw.common_lib.widget.loadmore;\n\nimport android.content.Context;\nimport android.support.annotation.DrawableRes;\nimport android.support.annotation.IntDef;\nimport android.support.v7.widget.LinearLayoutManager;\nimport android.support.v7.widget.RecyclerView;\nimport android.support.v7.widget.StaggeredGridLayoutManager;\nimport android.util.AttributeSet;\nimport android.util.Log;\nimport android.view.View;\nimport android.view.ViewGroup;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\n\n/**\n * A {@link RecyclerView} with footer which enables load more.\n * https://github.com/android-cjj/Android-RecyclerViewWithFooter\n * @author cjj\n */\npublic class RecyclerViewWithFooter extends RecyclerView {\n\n    private static final String TAG = \"RecyclerViewWithFooter\";\n\n    public static final int STATE_END = 0;\n    public static final int STATE_LOADING = 1;\n    public static final int STATE_EMPTY = 2;\n    public static final int STATE_NONE = 3;\n    public static final int STATE_PULL_TO_LOAD = 4;\n\n    private boolean mIsGettingData = false;\n\n    @State\n    private int mState = STATE_NONE;\n\n    /**\n     * 默认的 FootItem;\n     */\n    private FootItem mFootItem = new DefaultFootItem();\n    private EmptyItem mEmptyItem = new DefaultEmptyItem();\n\n    private AdapterDataObserver mAdapterDataObserver = new AdapterDataObserver() {\n\n        @Override\n        public void onChanged() {\n            super.onChanged();\n            reset();\n        }\n\n        private void reset() {\n            mIsGettingData = false;\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount) {\n            super.onItemRangeChanged(positionStart, itemCount);\n            reset();\n\n        }\n\n        @Override\n        public void onItemRangeChanged(int positionStart, int itemCount, Object payload) {\n            super.onItemRangeChanged(positionStart, itemCount, payload);\n            reset();\n\n        }\n\n        @Override\n        public void onItemRangeInserted(int positionStart, int itemCount) {\n            super.onItemRangeInserted(positionStart, itemCount);\n            reset();\n\n        }\n\n        @Override\n        public void onItemRangeRemoved(int positionStart, int itemCount) {\n            super.onItemRangeRemoved(positionStart, itemCount);\n            reset();\n        }\n\n        @Override\n        public void onItemRangeMoved(int fromPosition, int toPosition, int itemCount) {\n            super.onItemRangeMoved(fromPosition, toPosition, itemCount);\n            reset();\n        }\n    };\n\n    public RecyclerViewWithFooter(Context context) {\n        super(context);\n        init();\n    }\n\n    public RecyclerViewWithFooter(Context context, AttributeSet attrs) {\n        super(context, attrs);\n        init();\n    }\n\n    public RecyclerViewWithFooter(Context context, AttributeSet attrs, int defStyle) {\n        super(context, attrs, defStyle);\n        init();\n    }\n\n    private void init() {\n        setVerticalLinearLayout();\n    }\n\n    @Override\n    protected void onMeasure(int widthSpec, int heightSpec) {\n        super.onMeasure(widthSpec, heightSpec);\n//        int width = MeasureSpec.getSize(widthSpec);\n//        if(width != 0){\n//            int spans = width / mItemWidth;\n//            if(spans > 0){\n//                mLayoutManager.setSpanCount(spans);\n//            }\n//        }\n    }\n\n    public void setVerticalLinearLayout() {\n        RecyclerViewUtils.setVerticalLinearLayout(this);\n    }\n\n    public void setGridLayout(int span) {\n        RecyclerViewUtils.setGridLayout(this, span);\n    }\n\n    public void setStaggeredGridLayoutManager(int spanCount) {\n        RecyclerViewUtils.setStaggeredGridLayoutManager(this, spanCount);\n    }\n\n    public void setOnLoadMoreListener(OnLoadMoreListener onLoadMoreListener) {\n        setPullToLoad();\n\n        final OnLoadMoreListenerWrapper wrapper = new OnLoadMoreListenerWrapper(onLoadMoreListener);\n\n        addOnScrollListener(new RecyclerView.OnScrollListener() {\n            @Override\n            public void onScrollStateChanged(RecyclerView recyclerView, int newState) {\n                super.onScrollStateChanged(recyclerView, newState);\n                if (newState == RecyclerView.SCROLL_STATE_IDLE) {\n                    RecyclerView.LayoutManager layoutManager = recyclerView.getLayoutManager();\n                    if (layoutManager instanceof LinearLayoutManager) {\n                        int lastVisiblePosition = ((LinearLayoutManager) layoutManager).findLastVisibleItemPosition();\n                        if (lastVisiblePosition >= recyclerView.getAdapter().getItemCount() - 1) {\n                            wrapper.onLoadMore();\n                            if (mState == STATE_PULL_TO_LOAD) {\n                                setLoading();\n                            }\n                        }\n                    } else if (layoutManager instanceof StaggeredGridLayoutManager) {\n                        StaggeredGridLayoutManager staggeredGridLayoutManager = (StaggeredGridLayoutManager) layoutManager;\n                        int last[] = new int[staggeredGridLayoutManager.getSpanCount()];\n                        staggeredGridLayoutManager.findLastVisibleItemPositions(last);\n\n                        for (int aLast : last) {\n                            Log.i(TAG, aLast + \"    \" + recyclerView.getAdapter().getItemCount());\n                            if (aLast >= recyclerView.getAdapter().getItemCount() - 1) {\n                                wrapper.onLoadMore();\n                                if (mState == STATE_PULL_TO_LOAD) {\n                                    setLoading();\n                                }\n                            }\n                        }\n                    }\n                }\n            }\n        });\n    }\n\n    @Override\n    public void setAdapter(Adapter adapter) {\n        LoadMoreAdapter loadMoreAdapter;\n        if (adapter instanceof LoadMoreAdapter) {\n            loadMoreAdapter = (LoadMoreAdapter) adapter;\n            loadMoreAdapter.registerAdapterDataObserver(mAdapterDataObserver);\n            super.setAdapter(adapter);\n        } else {\n            loadMoreAdapter = new LoadMoreAdapter(adapter);\n            loadMoreAdapter.registerAdapterDataObserver(mAdapterDataObserver);\n            super.setAdapter(loadMoreAdapter);\n        }\n    }\n\n    /**\n     * 设置loading提示字符串\n     *\n     * @param loadText 提示字符串\n     * @return {@link RecyclerViewWithFooter}\n     */\n    public RecyclerViewWithFooter applyLoadingText(CharSequence loadText) {\n        mFootItem.loadingText = loadText;\n        return this;\n    }\n\n    public RecyclerViewWithFooter applyPullToLoadText(CharSequence pullToLoadText) {\n        mFootItem.pullToLoadText = pullToLoadText;\n        return this;\n    }\n\n    public RecyclerViewWithFooter applyEndText(CharSequence endText) {\n        mFootItem.endText = endText;\n        return this;\n    }\n\n    public RecyclerViewWithFooter applyEmptyText(CharSequence emptyText, @DrawableRes int drawableId) {\n        mEmptyItem.mEmptyIconRes = drawableId;\n        mEmptyItem.mEmptyText = emptyText;\n        return this;\n    }\n\n    public void setFootItem(FootItem footItem) {\n        if (mFootItem != null) {\n            if (footItem.endText == null) {\n                footItem.endText = mFootItem.endText;\n            }\n            if (footItem.loadingText == null) {\n                footItem.loadingText = mFootItem.loadingText;\n            }\n            if (footItem.pullToLoadText == null) {\n                footItem.pullToLoadText = mFootItem.pullToLoadText;\n            }\n        }\n        mFootItem = footItem;\n    }\n\n    public void setEmptyItem(EmptyItem emptyItem) {\n        if (mEmptyItem != null) {\n            if (emptyItem.mEmptyIconRes == -1) {\n                emptyItem.mEmptyIconRes = mEmptyItem.mEmptyIconRes;\n            }\n            if (emptyItem.mEmptyText == null) {\n                emptyItem.mEmptyText = mEmptyItem.mEmptyText;\n            }\n        }\n        mEmptyItem = emptyItem;\n    }\n\n    /**\n     * 切换为上拉加载更多状态\n     */\n    public void setPullToLoad() {\n        if (getAdapter() != null) {\n            mState = STATE_PULL_TO_LOAD;\n            mIsGettingData = false;\n            getAdapter().notifyItemChanged(getAdapter().getItemCount() - 1);\n            getAdapter().notifyDataSetChanged();\n        }\n    }\n\n    /**\n     * 切换为loading状态\n     */\n    public void setLoading() {\n        if (getAdapter() != null) {\n            mState = STATE_LOADING;\n            mIsGettingData = true;\n            getAdapter().notifyItemChanged(getAdapter().getItemCount() - 1);\n            getAdapter().notifyDataSetChanged();\n        }\n    }\n\n    /**\n     * 切换为没有更多数据状态\n     *\n     * @param end 提示字符串\n     */\n    public void setEnd(CharSequence end) {\n        if (getAdapter() != null) {\n            mIsGettingData = false;\n            mState = STATE_END;\n            mFootItem.endText = end;\n            getAdapter().notifyItemChanged(getAdapter().getItemCount() - 1);\n            getAdapter().notifyDataSetChanged();\n        }\n    }\n\n    /**\n     * 切换为没有更多数据状态\n     */\n    public void setEnd() {\n        if (getAdapter() != null) {\n            mIsGettingData = false;\n            mState = STATE_END;\n            getAdapter().notifyItemChanged(getAdapter().getItemCount() - 1);\n            getAdapter().notifyDataSetChanged();\n        }\n    }\n\n    /**\n     * 切换成无数据状态\n     *\n     * @param empty 无数据状态提示消息\n     * @param resId 无数据状态提示图标\n     */\n    public void setEmpty(CharSequence empty, @DrawableRes int resId) {\n        if (getAdapter() != null) {\n            mState = STATE_EMPTY;\n            mEmptyItem.mEmptyText = empty;\n            mEmptyItem.mEmptyIconRes = resId;\n            if (isEmpty()) {\n                getAdapter().notifyDataSetChanged();\n            }\n        }\n    }\n\n    /**\n     * 切换成无数据状态\n     */\n    public void setEmpty() {\n        if (getAdapter() != null) {\n            mState = STATE_EMPTY;\n            if (isEmpty()) {\n                getAdapter().notifyDataSetChanged();\n            }\n        }\n    }\n\n    /**\n     * 数据是否为空\n     */\n    private boolean isEmpty() {\n        return (mState == STATE_NONE && getAdapter().getItemCount() == 0) ||\n                (mState != STATE_NONE && getAdapter().getItemCount() == 1);\n    }\n\n    public boolean isLoadMoreEnable() {\n        return mState != STATE_LOADING;\n    }\n\n    @IntDef({STATE_END, STATE_LOADING, STATE_EMPTY, STATE_NONE, STATE_PULL_TO_LOAD})\n    @Retention(RetentionPolicy.SOURCE)\n    public @interface State {\n    }\n\n    private class OnLoadMoreListenerWrapper implements OnLoadMoreListener {\n\n        private OnLoadMoreListener mOnLoadMoreListener;\n\n        public OnLoadMoreListenerWrapper(OnLoadMoreListener onLoadMoreListener) {\n            mOnLoadMoreListener = onLoadMoreListener;\n        }\n\n        @Override\n        public void onLoadMore() {\n            if (!mIsGettingData && !isLoadMoreEnable() && mOnLoadMoreListener != null) {\n                mIsGettingData = true;\n                mOnLoadMoreListener.onLoadMore();\n            }\n        }\n    }\n\n    public class LoadMoreAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {\n\n        public static final int LOAD_MORE_VIEW_TYPE = -404;\n        public static final int EMPTY_VIEW_TYPE = -403;\n\n        public RecyclerView.Adapter mAdapter;\n\n        public LoadMoreAdapter(Adapter adapter) {\n            mAdapter = adapter;\n        }\n\n        @Override\n        public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {\n            if (viewType == LOAD_MORE_VIEW_TYPE) {\n                return new LoadMoreVH();\n            } else if (viewType == EMPTY_VIEW_TYPE) {\n                return new EmptyVH();\n            }\n            return mAdapter.onCreateViewHolder(parent, viewType);\n        }\n\n        @Override\n        public void registerAdapterDataObserver(AdapterDataObserver observer) {\n            super.registerAdapterDataObserver(observer);\n            mAdapter.registerAdapterDataObserver(observer);\n        }\n\n        @Override\n        public void unregisterAdapterDataObserver(AdapterDataObserver observer) {\n            super.unregisterAdapterDataObserver(observer);\n            mAdapter.unregisterAdapterDataObserver(observer);\n        }\n\n        @Override\n        public void onBindViewHolder(ViewHolder holder, int position) {\n            if (!isFootView(position)) {\n                mAdapter.onBindViewHolder(holder, position);\n            } else {\n                if (getLayoutManager() instanceof StaggeredGridLayoutManager) {\n                    ViewGroup.LayoutParams layoutParams = holder.itemView.getLayoutParams();\n                    if (layoutParams instanceof StaggeredGridLayoutManager.LayoutParams) {\n                        ((StaggeredGridLayoutManager.LayoutParams) layoutParams).setFullSpan(true);\n                    }\n                }\n                if (holder instanceof VH) {\n                    ((VH) holder).onBindViewHolder();\n                }\n            }\n        }\n\n        private boolean isFootView(int position) {\n            return position == getItemCount() - 1 && mState != STATE_NONE;\n        }\n\n        @Override\n        public int getItemViewType(int position) {\n            if (!isFootView(position)) {\n                return mAdapter.getItemViewType(position);\n            } else {\n                if (mState == STATE_EMPTY && getItemCount() == 1) {\n                    return EMPTY_VIEW_TYPE;\n                } else {\n                    return LOAD_MORE_VIEW_TYPE;\n                }\n            }\n        }\n\n        @Override\n        public int getItemCount() {\n            if (mState == STATE_NONE) {\n                return mAdapter.getItemCount();\n            } else {\n                return mAdapter.getItemCount() + 1;\n            }\n        }\n\n        /**\n         * 加载更多的ViewHolder\n         */\n        private class LoadMoreVH extends VH {\n\n            private View mItemView;\n\n            public LoadMoreVH() {\n                super(mFootItem.onCreateView(RecyclerViewWithFooter.this));\n                mItemView = itemView;\n            }\n\n            @Override\n            public void onBindViewHolder() {\n                super.onBindViewHolder();\n                if (mState == STATE_LOADING || mState == STATE_END || mState == STATE_PULL_TO_LOAD) {\n                    mFootItem.onBindData(mItemView, mState);\n                }\n            }\n        }\n\n        /**\n         * 数据为空时的ViewHolder\n         */\n        private class EmptyVH extends VH {\n\n            public EmptyVH() {\n                super(mEmptyItem.onCreateView(RecyclerViewWithFooter.this));\n            }\n\n            @Override\n            public void onBindViewHolder() {\n                super.onBindViewHolder();\n                mEmptyItem.onBindData(itemView);\n            }\n        }\n\n        class VH extends RecyclerView.ViewHolder {\n\n            public VH(View itemView) {\n                super(itemView);\n            }\n\n            public void onBindViewHolder() {\n\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "common_lib/src/main/res/layout/layout_error_view.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=\"match_parent\">\n\n    <TextView\n        android:textSize=\"16sp\"\n        android:text=\"出错了\"\n        android:id=\"@+id/tv_error\"\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <Button\n        android:layout_below=\"@id/tv_error\"\n        android:id=\"@+id/btn_try\"\n        android:layout_centerInParent=\"true\"\n        android:layout_marginTop=\"4dp\"\n        android:text=\"@string/try_again\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n</RelativeLayout>\n"
  },
  {
    "path": "common_lib/src/main/res/layout/layout_loading_footer_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<LinearLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:gravity=\"center\"\n    android:layout_height=\"wrap_content\">\n\n    <ProgressBar\n        android:id=\"@+id/progress_view\"\n        android:layout_width=\"25dp\"\n        android:layout_height=\"25dp\"\n        style=\"?progressBarStyle\"/>\n    <TextView\n        android:id=\"@+id/tv_content\"\n        android:layout_marginLeft=\"4dp\"\n        android:text=\"@string/loading\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n</LinearLayout>\n"
  },
  {
    "path": "common_lib/src/main/res/layout/layout_loading_view.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<RelativeLayout xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:id=\"@+id/rl_loading\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"match_parent\">\n\n    <ProgressBar\n        android:id=\"@+id/progress_bar\"\n        style=\"?progressBarStyle\"\n        android:layout_width=\"@dimen/progress_width\"\n        android:layout_height=\"@dimen/progress_width\"\n        android:layout_centerInParent=\"true\"\n        android:indeterminate=\"true\"\n        android:indeterminateBehavior=\"cycle\"/>\n\n    <TextView\n        android:textSize=\"16sp\"\n        android:layout_centerInParent=\"true\"\n        android:layout_below=\"@id/progress_bar\"\n        android:layout_marginTop=\"4dp\"\n        android:text=\"@string/loading\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n</RelativeLayout>\n"
  },
  {
    "path": "common_lib/src/main/res/layout/layout_no_data_view.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=\"match_parent\">\n\n    <TextView\n        android:textSize=\"16sp\"\n        android:text=\"@string/not_data\"\n        android:id=\"@+id/tv_error\"\n        android:layout_centerInParent=\"true\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n\n    <Button\n        android:layout_below=\"@id/tv_error\"\n        android:id=\"@+id/btn_try\"\n        android:layout_centerInParent=\"true\"\n        android:layout_marginTop=\"4dp\"\n        android:text=\"@string/try_again\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\" />\n</RelativeLayout>\n"
  },
  {
    "path": "common_lib/src/main/res/layout/rv_with_footer_empty_layout.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<RelativeLayout\n    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:orientation=\"vertical\">\n\n    <TextView\n        android:id=\"@+id/rv_with_footer_empty_title\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:layout_gravity=\"center\"\n        android:text=\"@string/rv_with_footer_empty\"/>\n\n    <ImageView\n        android:id=\"@+id/rv_with_footer_empty_icon\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_toLeftOf=\"@id/rv_with_footer_empty_title\"/>\n\n</RelativeLayout>\n"
  },
  {
    "path": "common_lib/src/main/res/layout/rv_with_footer_loading.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n\n<RelativeLayout\n    xmlns:android=\"http://schemas.android.com/apk/res/android\"\n    android:layout_width=\"match_parent\"\n    android:layout_height=\"wrap_content\"\n    android:layout_gravity=\"center\"\n    android:layout_margin=\"10dp\"\n    android:gravity=\"center\"\n    android:orientation=\"vertical\">\n\n    <LinearLayout\n        android:layout_width=\"match_parent\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:gravity=\"center\">\n\n        <ProgressBar\n            android:id=\"@+id/rv_with_footer_loading_progress\"\n            android:layout_width=\"24dp\"\n            android:layout_height=\"24dp\"\n            android:layout_gravity=\"center\"/>\n\n        <TextView\n            android:id=\"@+id/rv_with_footer_loading_load\"\n            android:layout_width=\"wrap_content\"\n            android:layout_height=\"wrap_content\"\n            android:text=\"@string/rv_with_footer_loading\"\n            android:textSize=\"12sp\"/>\n    </LinearLayout>\n\n    <TextView\n        android:id=\"@+id/rv_with_footer_loading_pull_to_load\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:layout_gravity=\"center\"\n        android:maxLines=\"1\"\n        android:text=\"@string/rv_with_footer_pull_load_more\"\n        android:singleLine=\"true\"\n        android:visibility=\"gone\"/>\n\n    <TextView\n        android:id=\"@+id/rv_with_footer_loading_end\"\n        android:layout_width=\"wrap_content\"\n        android:layout_height=\"wrap_content\"\n        android:layout_centerInParent=\"true\"\n        android:layout_gravity=\"center\"\n        android:maxLines=\"1\"\n        android:text=\"@string/rv_with_footer_empty\"\n        android:singleLine=\"true\"\n        android:visibility=\"gone\"/>\n\n</RelativeLayout>\n"
  },
  {
    "path": "common_lib/src/main/res/values/attrs.xml",
    "content": "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<resources>\n\n    <declare-styleable name=\"ClearEditText\">\n        <attr name=\"clearDrawable\" format=\"reference\"/>\n    </declare-styleable>\n\n</resources>"
  },
  {
    "path": "common_lib/src/main/res/values/dimens.xml",
    "content": "<resources>\n    <dimen name=\"progress_width\">60dp</dimen>\n    <dimen name=\"progress_height\">60dp</dimen>\n</resources>\n"
  },
  {
    "path": "common_lib/src/main/res/values/rv_with_footer_strings.xml",
    "content": "<resources>\n    <string name=\"rv_with_footer_pull_load_more\">上拉加载更多</string>\n    <string name=\"rv_with_footer_loading\">加载中…</string>\n    <!--<string name=\"rv_with_footer_empty\">没有数据啦</string>-->\n    <string name=\"rv_with_footer_empty\">\"  \"</string>\n</resources>\n"
  },
  {
    "path": "common_lib/src/main/res/values/strings.xml",
    "content": "<resources>\n    <string name=\"app_name\">common_lib</string>\n    <string name=\"not_network\">当前无网络连接,请检查网络...</string>\n    <string name=\"copy_done\">复制成功</string>\n    <string name=\"open_failure\">打开失败,没有找到打开该链接的其它应用</string>\n    <string name=\"loading\">正在加载...</string>\n    <string name=\"try_again\">重新加载</string>\n    <string name=\"not_data\">暂无数据</string>\n</resources>\n"
  },
  {
    "path": "common_lib/src/test/java/com/wkw/common_lib/ExampleUnitTest.java",
    "content": "package com.wkw.common_lib;\n\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * To work on unit tests, switch the Test Artifact in the Build Variants view.\n */\npublic class ExampleUnitTest {\n    @Test\n    public void addition_isCorrect() throws Exception {\n        assertEquals(4, 2 + 2);\n    }\n}"
  },
  {
    "path": "gradle/wrapper/gradle-wrapper.properties",
    "content": "#Mon Sep 12 10:05:44 CST 2016\ndistributionBase=GRADLE_USER_HOME\ndistributionPath=wrapper/dists\nzipStoreBase=GRADLE_USER_HOME\nzipStorePath=wrapper/dists\ndistributionUrl=https\\://services.gradle.org/distributions/gradle-2.14.1-all.zip\n"
  },
  {
    "path": "gradle.properties",
    "content": "## Project-wide Gradle settings.\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\n#Mon Aug 15 21:19:35 CST 2016\nandroid.useDeprecatedNdk=true\n"
  },
  {
    "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# 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\\\"`/\" >/dev/null\nAPP_HOME=\"`pwd -P`\"\ncd \"$SAVED\" >/dev/null\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    JAVACMD=`cygpath --unix \"$JAVACMD\"`\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\r\n@rem ##########################################################################\r\n@rem\r\n@rem  Gradle startup script for Windows\r\n@rem\r\n@rem ##########################################################################\r\n\r\n@rem Set local scope for the variables with windows NT shell\r\nif \"%OS%\"==\"Windows_NT\" setlocal\r\n\r\n@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.\r\nset DEFAULT_JVM_OPTS=\r\n\r\nset DIRNAME=%~dp0\r\nif \"%DIRNAME%\" == \"\" set DIRNAME=.\r\nset APP_BASE_NAME=%~n0\r\nset APP_HOME=%DIRNAME%\r\n\r\n@rem Find java.exe\r\nif defined JAVA_HOME goto findJavaFromJavaHome\r\n\r\nset JAVA_EXE=java.exe\r\n%JAVA_EXE% -version >NUL 2>&1\r\nif \"%ERRORLEVEL%\" == \"0\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:findJavaFromJavaHome\r\nset JAVA_HOME=%JAVA_HOME:\"=%\r\nset JAVA_EXE=%JAVA_HOME%/bin/java.exe\r\n\r\nif exist \"%JAVA_EXE%\" goto init\r\n\r\necho.\r\necho ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%\r\necho.\r\necho Please set the JAVA_HOME variable in your environment to match the\r\necho location of your Java installation.\r\n\r\ngoto fail\r\n\r\n:init\r\n@rem Get command-line arguments, handling Windowz variants\r\n\r\nif not \"%OS%\" == \"Windows_NT\" goto win9xME_args\r\nif \"%@eval[2+2]\" == \"4\" goto 4NT_args\r\n\r\n:win9xME_args\r\n@rem Slurp the command line arguments.\r\nset CMD_LINE_ARGS=\r\nset _SKIP=2\r\n\r\n:win9xME_args_slurp\r\nif \"x%~1\" == \"x\" goto execute\r\n\r\nset CMD_LINE_ARGS=%*\r\ngoto execute\r\n\r\n:4NT_args\r\n@rem Get arguments from the 4NT Shell from JP Software\r\nset CMD_LINE_ARGS=%$\r\n\r\n:execute\r\n@rem Setup the command line\r\n\r\nset CLASSPATH=%APP_HOME%\\gradle\\wrapper\\gradle-wrapper.jar\r\n\r\n@rem Execute Gradle\r\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%\r\n\r\n:end\r\n@rem End local scope for the variables with windows NT shell\r\nif \"%ERRORLEVEL%\"==\"0\" goto mainEnd\r\n\r\n:fail\r\nrem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of\r\nrem the _cmd.exe /c_ return code!\r\nif  not \"\" == \"%GRADLE_EXIT_CONSOLE%\" exit 1\r\nexit /b 1\r\n\r\n:mainEnd\r\nif \"%OS%\"==\"Windows_NT\" endlocal\r\n\r\n:omega\r\n"
  },
  {
    "path": "index.android.js",
    "content": "/**\n * Sample React Native App\n * https://github.com/facebook/react-native\n * @flow\n */\n\nimport {\n\tAppRegistry,\n} from 'react-native';\nimport rootApp from \"./js/rootApp.js\";\n\n\nAppRegistry.registerComponent('MyHot', () => rootApp);"
  },
  {
    "path": "js/actions/newsList.js",
    "content": "import * as types from \"../constants/ActionTypes.js\";\nimport * as Services from \"../utils/Services.js\";\nimport {\n\tNEW_LIST\n} from \"../constants/Urls.js\";\n\n\nexport function fetchNews(loading, isRefresh, isLoadMore, pn) {\n\treturn dispatch => {\n\t\tdispatch(fetchNewsList(loading, isRefresh, isLoadMore));\n\t\tServices.getNewList(NEW_LIST, pn)\n\t\t\t.then(result => {\n\t\t\t\tdispatch(receiveNewsList(result));\n\t\t\t});\n\t}\n}\n\nfunction fetchNewsList(loading, isRefresh, isLoadMore) {\n\treturn {\n\t\ttype: types.FE_NEWLIST,\n\t\tloading: loading,\n\t\tisRefresh: isRefresh,\n\t\tisLoadMore: isLoadMore\n\t};\n}\n\nfunction receiveNewsList(newsList) {\n\treturn {\n\t\ttype: types.RE_NEWLIST,\n\t\tnewsList: newsList\n\t}\n}"
  },
  {
    "path": "js/components/Header.js",
    "content": "import React, {\n\tPropTypes\n} from 'react';\nimport {\n\tStyleSheet,\n\tToolbarAndroid,\n\tPlatform,\n\tView,\n\tText\n} from 'react-native';\nimport {\n\tnaviGoBack\n} from '../utils/CommonUtil';\n\nconst iconLeft = require('../image/icon_left.png');\n\nconst propTypes = {\n\ttitle: PropTypes.string,\n\tactions: PropTypes.array,\n\tnavigator: PropTypes.object,\n\tonActionSelected: PropTypes.func,\n\tonIconClicked: PropTypes.func,\n\tnavIcon: PropTypes.number\n};\n\nconst Header = ({\n\ttitle,\n\tactions,\n\tnavigator,\n\tonActionSelected,\n\tonIconClicked,\n\tnavIcon\n}) => {\n\tconst handleIconClicked = () => {\n\t\tif (onIconClicked) {\n\t\t\tonIconClicked();\n\t\t} else if (navigator) {\n\t\t\tnaviGoBack(navigator);\n\t\t}\n\t};\n\n\tconst renderToolbarAndroid = () => (\n\t\t<ToolbarAndroid\n\t\t\tstyle={styles.toolbar}\n\t\t\tactions={actions}\n\t\t\tonActionSelected={onActionSelected}\n\t\t\tonIconClicked={handleIconClicked}\n\t\t\tnavIcon={navIcon === undefined ? iconLeft : navIcon}\n\t\t\ttitleColor=\"#fff\"\n\t\t\ttitle={title}\n\t\t\t/>\n\t);\n\n\n\n\tconst Toolbar = Platform.select({\n\t\tandroid: () => renderToolbarAndroid()\n\t});\n\n\treturn <Toolbar />;\n};\n\nconst styles = StyleSheet.create({\n\ttoolbar: {\n\t\tflexDirection: 'row',\n\t\tbackgroundColor: '#3F51B5',\n\t\talignItems: 'center',\n\t\theight: 58\n\t}\n});\n\nHeader.propTypes = propTypes;\n\nHeader.defaultProps = {\n\tonActionSelected() { },\n\ttitle: '',\n\tactions: []\n};\n\nexport default Header;"
  },
  {
    "path": "js/components/LoadingView.js",
    "content": "import React, {\n\tComponent\n} from 'react';\nimport {\n\tActivityIndicator,\n\tText,\n\tStyleSheet,\n\tView\n} from 'react-native';\nclass LoadingView extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<View style={styles.containers}>\n\t\t\t\t<ActivityIndicator size='large' color='#FF4081' />\n\t\t\t\t<Text style={ styles.text }>数据加载中...</Text>\n\t\t\t</View>\n\t\t)\n\n\n\t}\n}\n\nconst styles = StyleSheet.create({\n\tcontainers: {\n\t\tflex: 1,\n\t\talignItems: 'center',\n\t\tjustifyContent: 'center'\n\t},\n\ttext: {\n\t\tmarginTop: 10,\n\t\ttextAlign: 'center'\n\t}\n})\n\nexport default LoadingView;"
  },
  {
    "path": "js/constants/ActionTypes.js",
    "content": "export const FE_NEWLIST = 'FE_NEWLIST';\nexport const RE_NEWLIST = 'RE_NEWLIST';"
  },
  {
    "path": "js/constants/Urls.js",
    "content": "export const NEW_LIST = 'txapi/tiyu/tiyu';"
  },
  {
    "path": "js/containes/App.js",
    "content": "import React from 'react';\nimport {\n\tStyleSheet,\n\tNavigator,\n\tStatusBar,\n\tBackAndroid,\n\tView\n} from 'react-native';\nimport {\n\tnaviGoBack\n} from '../utils/CommonUtil.js';\n\nimport NewsContainer from \"./NewsContaines.js\"\n\nvar _navigator;\nclass App extends React.Component {\n\tconstructor(props) {\n\t\tsuper(props);\n\t\tthis.renderScene = this.renderScene.bind(this);\n\t\tthis.goBack = this.goBack.bind(this);\n\t\tthis.configureScene = this.configureScene.bind(this);\n\t\tBackAndroid.addEventListener('hardwareBackPress', this.goBack);\n\t}\n\n\tgoBack() {\n\t\treturn naviGoBack(_navigator);\n\t}\n\n\trenderScene(route, navigator) {\n\t\tlet Component = route.component;\n\t\t_navigator = navigator;\n\t\treturn (<Component navigator={navigator} route={route} />);\n\t}\n\n\tconfigureScene(route) {\n\t\tif (route.sceneConfig) {\n\t\t\treturn route.sceneConfig\n\t\t}\n\n\t\treturn Navigator.SceneConfigs.PushFromRight;\n\t}\n\n\trender() {\n\t\treturn (\n\t\t\t<Navigator\n\t\t\t\tstyle={styles.navigator}\n\t\t\t\tconfigureScene={this.configureScene}\n\t\t\t\trenderScene={this.renderScene}\n\t\t\t\tinitialRoute = {{\n\t\t\t\t\tcomponent: NewsContainer,\n\t\t\t\t\tname: 'NewsContainer'\n\t\t\t\t}}\n\t\t\t\t/>\n\t\t);\n\t}\n}\n\nconst styles = StyleSheet.create({\n\tnavigator: {\n\t\tflex: 1\n\t}\n});\n\nexport default App;"
  },
  {
    "path": "js/containes/NewsContaines.js",
    "content": "'use strict';\n\nimport React, {\n  Component\n} from 'react';\nimport {\n  connect\n} from 'react-redux';\nimport News from \"../pages/News.js\";\nimport {\n  bindActionCreators\n} from 'redux';\nimport * as newsAction from '../actions/newsList.js';\nclass NewsContainer extends Component {\n\n  render() {\n    return (\n      <News {...this.props} />\n    );\n  }\n}\n\nfunction mapStateToProps(state) {\n  const {\n    news\n  } = state;\n  return {\n    news\n  }\n}\n\nfunction mapDispatchToProp(dispatch) {\n  return {\n    actions: bindActionCreators(newsAction, dispatch)\n  };\n}\n\nexport default connect(mapStateToProps, mapDispatchToProp)(NewsContainer);"
  },
  {
    "path": "js/containes/WebViewContaines.js",
    "content": "import React, {\n  Component\n} from 'react';\nimport {\n  connect\n} from 'react-redux';\nimport WebViewPage from \"../pages/WebViewPage.js\";\nclass WebContainer extends Component {\n\n\trender() {\n     return (\n       <WebViewPage {...this.props} />\n    );\n  }\n\n}\n\nfunction mapStateToProps(state) {\n  const {news} = state;\n  return {\n    news\n  }\n}\n\nexport default connect(mapStateToProps)(WebContainer);"
  },
  {
    "path": "js/pages/News.js",
    "content": "import React, {\n  Component\n} from 'react';\nimport {\n  StyleSheet,\n  Text,\n  RefreshControl,\n  TouchableOpacity,\n  ListView,\n  InteractionManager,\n  Image,\n  ActivityIndicator,\n  View\n} from 'react-native';\nimport Header from '../components/Header.js';\nimport LoadingView from \"../components/LoadingView.js\";\nimport WebViewContaines from \"../containes/WebViewContaines.js\";\nimport {\n  toastShort\n} from \"../utils/ToastUtil.js\";\nvar page = 1;\nvar loadMoreTime = 0;\nclass News extends Component {\n\n  constructor(props) {\n    super(props);\n    this.renderContent = this.renderContent.bind(this);\n    this.renderItem = this.renderItem.bind(this);\n    this.renderFooter = this.renderFooter.bind(this);\n    this.onPress = this.onPress.bind(this);\n    this.state = {\n      dataSource: new ListView.DataSource({\n        rowHasChanged: (r1, r2) => r1 !== r2\n      })\n    };\n  }\n\n\n  componentDidMount() {\n    const {\n      actions\n    } = this.props;\n    actions.fetchNews(true, false, false, page);\n  }\n\n  onEndReached() {\n    let time = Date.parse(new Date()) / 1000;\n    if (time - loadMoreTime > 1) {\n      const {\n        actions\n      } = this.props;\n      page++;\n      actions.fetchNews(false, false, true, page);\n      loadMoreTime = Date.parse(new Date()) / 1000;\n    }\n\n  }\n\n  renderItem(news) {\n    return (\n      <TouchableOpacity onPress={() => this.onPress(news.title, news.url) }>\n        <View style={styles.containerItem}>\n          <Image style= {styles.image} source={{ uri: news.picUrl }}/>\n          <View style={{ flex: 1, flexDirection: 'column' }} >\n            <Text style={styles.title}>\n              {news.title}\n            </Text>\n            <Text >\n              来自: {news.description}\n            </Text>\n          </View>\n        </View>\n      </TouchableOpacity>\n    )\n  }\n\n  onPress(title, url) {\n    const { navigator } = this.props;\n    navigator.push({\n      component: WebViewContaines,\n      name: 'WebViewContaines',\n      url: url,\n      title: title\n    });\n  }\n\n  renderFooter() {\n    const {\n      news\n    } = this.props;\n    if (news.isLoadMore) {\n      return (\n        <View style={styles.footerContainer}>\n          <ActivityIndicator size=\"small\" color=\"#FF4081\" />\n          <Text style={styles.footerText}>\n            数据加载中……\n          </Text>\n        </View>\n      )\n    }\n  }\n  onRefresh() {\n    const {\n      actions\n    } = this.props;\n    actions.fetchNews(false, true, false, page);\n  }\n  renderContent() {\n    const {\n      news\n    } = this.props;\n    if (news.loading) {\n      return <LoadingView />\n    }\n\n    return (\n      <ListView initialListSize = {1}\n        dataSource = {this.state.dataSource.cloneWithRows(news.newsList) }\n        renderRow = {this.renderItem}\n        style = {styles.listView}\n        onEndReached = {this.onEndReached.bind(this) }\n        onEndReachedThreshold = {10}\n        renderFooter = {this.renderFooter}\n        refreshControl = {\n          <RefreshControl\n            style={{ backgroundColor: 'transparent' }}\n            refreshing={news.isRefresh}\n            onRefresh={this.onRefresh.bind(this) }\n            title=\"Loading...\"\n            colors={['#ff0000', '#00ff00', '#0000ff', '#3ad564']}\n            />\n        }\n        />)\n  }\n\n  render() {\n    const {\n      navigator,\n      news\n    } = this.props;\n    return (\n      <View style={styles.container}>\n        <Header title=\"体育\" navigator= {navigator}/>\n        {this.renderContent() }\n      </View>\n\n    )\n  }\n\n}\n\n\n\nconst styles = StyleSheet.create({\n  container: {\n    flex: 1,\n    backgroundColor: '#F5FCFF',\n  },\n  containerItem: {\n    flexDirection: 'row',\n    justifyContent: 'center',\n    alignItems: 'center',\n    backgroundColor: '#fcfcfc',\n    padding: 10,\n    borderBottomColor: '#ddd',\n  },\n  image: {\n    width: 88,\n    height: 66,\n    marginRight: 10\n  },\n  title: {\n    fontSize: 18,\n    textAlign: 'left',\n    color: 'black'\n  },\n  footerContainer: {\n    flex: 1,\n    flexDirection: 'row',\n    justifyContent: 'center',\n    alignItems: 'center',\n    padding: 5\n  },\n  footerText: {\n    textAlign: 'center',\n    fontSize: 16,\n    marginLeft: 10\n  }\n});\n\nexport default News;"
  },
  {
    "path": "js/pages/WebViewPage.js",
    "content": "'use strict'\nimport React, {\n    Component\n} from 'react';\nimport {\n    StyleSheet,\n    WebView,\n    View\n} from 'react-native';\nimport Header from '../components/Header.js';\nimport LoadingView from '../components/LoadingView.js';\nclass WebViewPage extends Component {\n    render() {\n        const {\n            navigator,\n            route\n        } = this.props;\n        console.log(route);\n        return (\n            <View style={styles.container}>\n                <Header title={route.title} navigator={navigator}></Header>\n                <WebView ref=\"webview\"\n                    automaticallyAdjustContentInsets={false}\n                    style={{ flex: 1 }}\n                    source={{ uri: route.url }}\n                    javaScriptEnabled={true}\n                    domStorageEnabled={true}\n                    startInLoadingState={true}\n                    scalesPageToFit={true}\n                    decelerationRate=\"normal\"\n                    renderLoading={this.renderLoading.bind(this) }>\n                </WebView>\n            </View>\n        );\n    }\n    renderLoading() {\n        return <LoadingView/>\n    }\n}\nconst styles = StyleSheet.create({\n    container: {\n        flex: 1,\n        backgroundColor: '#F5FCFF',\n    },\n});\nexport default WebViewPage;"
  },
  {
    "path": "js/reducers/index.js",
    "content": "'use strict'\nimport {\n\tcombineReducers\n} from 'redux';\nimport news from './newsList.js';\nconst rootReduer = combineReducers({\n\tnews,\n});\n\nexport default rootReduer;"
  },
  {
    "path": "js/reducers/newsList.js",
    "content": "import * as types from '../constants/ActionTypes';\n\nconst initialState = {\n\tloading: true,\n\tisRefresh: false,\n\tisLoadMore: false,\n\tnewsList: []\n}\n\nexport default function revicesNewsList(state = initialState, action) {\n\tswitch (action.type) {\n\t\tcase types.FE_NEWLIST:\n\t\t\treturn Object.assign({}, state, {\n\t\t\t\tloading: action.loading,\n\t\t\t\tisRefresh: action.isRefresh,\n\t\t\t\tisLoadMore: action.isLoadMore,\n\n\t\t\t});\n\t\tcase types.RE_NEWLIST:\n\t\t\treturn Object.assign({}, state, {\n\t\t\t\tloading: false,\n\t\t\t\tisRefresh: false,\n\t\t\t\tisLoadMore: false,\n\t\t\t\tnewsList: state.isLoadMore ? state.newsList.concat(action.newsList) : action.newsList,\n\t\t\t});\n\t\tdefault:\n\t\t\treturn state;\n\t}\n}"
  },
  {
    "path": "js/rootApp.js",
    "content": "import React, {\n\tComponent\n} from 'react';\nimport {\n\tProvider\n} from 'react-redux'\nimport configureStore from './store/store.js'\n\nimport App from './containes/App.js'\n\nconst store = configureStore();\n\nclass rootApp extends Component {\n\trender() {\n\t\treturn (\n\t\t\t<Provider store={store}>\n               <App/>\n            </Provider>\n\t\t)\n\t}\n}\nexport default rootApp;"
  },
  {
    "path": "js/store/store.js",
    "content": "'use strict';\n\nimport {\n\tcreateStore,\n\tapplyMiddleware\n} from 'redux';\nimport thunkMiddleware from 'redux-thunk';\nimport rootReducer from '../reducers/index';\nconst createStoreWithMiddleware = applyMiddleware(thunkMiddleware)(createStore);\nexport default function configureStore(initialState) {\n\tconst store = createStoreWithMiddleware(rootReducer, initialState);\n\treturn store;\n}"
  },
  {
    "path": "js/utils/CommonUtil.js",
    "content": "'use strict'\nimport {\n\tBackAndroid\n} from 'react-native';\nexport const naviGoBack = (navigator) => {\n\tif (navigator && navigator.getCurrentRoutes().length > 1) {\n\t\tnavigator.pop();\n\t\treturn true;\n\t} else {\n\t\tBackAndroid.exitApp();\n\t\treturn false;\n\t}\n\n};"
  },
  {
    "path": "js/utils/Services.js",
    "content": "const HOST = \"http://apis.baidu.com/\";\nimport FetchHttpClient, {\n\tquery,\n\theader\n} from 'fetch-http-client';\nimport {\n\ttoastShort\n} from \"./ToastUtil.js\";\n\nlet client = new FetchHttpClient(HOST);\n\nexport function getNewList(url, pnSize) {\n\n\treturn getClient().get(url, {\n\t\tquery: {\n\t\t\tnum: 10,\n\t\t\tpn: pnSize\n\t\t},\n\t}).then(filterJSON)\n\t\t.then(filterStatus)\n\t\t.catch((error) => {\n\t\t\ttoastShort('网络发生错误,请重试!')\n\t\t});\n}\n\nfunction getClient() {\n\tclient.addMiddleware(query());\n\tclient.addMiddleware(request => {\n\t\trequest.options.headers['apikey'] = 'ff27ef67506b2c0738a3252b01f8d564';\n\t});\n\treturn client;\n}\n\nfunction filterStatus(res) {\n\tif (res.code === 200) {\n\t\treturn res.newslist;\n\t} else {\n\t\ttoastShort(res.msg);\n\t}\n}\n\nfunction filterJSON(res) {\n\treturn res.json();\n}"
  },
  {
    "path": "js/utils/ToastUtil.js",
    "content": "import {\n\tToastAndroid\n} from 'react-native';\n\nexport const toastShort = (content) => {\n\tif (content != undefined) {\n\t\tToastAndroid.show(content, ToastAndroid.SHORT);\n\t}\n}\n\nexport const toastLong = (content) => {\n\tif (content != undefined) {\n\t\tToastAndroid.show(content, ToastAndroid.LONG);\n\t}\n}"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"rn-hot\",\n  \"version\": \"1.0.0\",\n  \"description\": \"react-native hot\",\n  \"main\": \"index.js\",\n  \"scripts\": {\n    \"start\": \"node node_modules/react-native/local-cli/cli.js start\",\n    \"test\": \"echo \\\"Error: no test specified\\\" && exit 1\",\n    \"bundle-android\": \"react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --sourcemap-output android/app/src/main/assets/index.android.map --assets-dest android/app/src/main/res/\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git+https://github.com/zj-wukewei/Hot.git\"\n  },\n  \"author\": \"wukewei\",\n  \"license\": \"ISC\",\n  \"bugs\": {\n    \"url\": \"https://github.com/zj-wukewei/Hot/issues\"\n  },\n  \"homepage\": \"https://github.com/zj-wukewei/Hot#readme\",\n  \"dependencies\": {\n    \"fetch-http-client\": \"0.0.7\",\n    \"react\": \"^15.2.1\",\n    \"react-native\": \"^0.31.0\",\n    \"react-redux\": \"^4.4.5\",\n    \"redux\": \"^3.5.2\",\n    \"redux-thunk\": \"^2.1.0\"\n  },\n  \"devDependencies\": {\n    \"redux-devtools\": \"^3.3.1\"\n  }\n}\n"
  },
  {
    "path": "settings.gradle",
    "content": "include ':app', ':common_lib'\n"
  },
  {
    "path": "tsconfig.json",
    "content": "{\"compilerOptions\":{\"allowJs\":true},\"exclude\":[\"node_modules\"]}"
  },
  {
    "path": "version.gradle",
    "content": "ext {\n    android = [\n            compileSdkVersion : 25,\n            buildToolsVersion : \"25.0.1\",\n            applicationId : \"com.wkw.hot\",\n            minSdkVersion : 16,\n            targetSdkVersion : 22,\n            versionCode : 1,\n            versionName : \"1.0\",\n            javaVersion : JavaVersion.VERSION_1_8\n    ]\n\n    dependencies = [\n            \"appcompat-v7\"        : \"com.android.support:appcompat-v7:25.0.1\",\n            \"design\"              : \"com.android.support:design:25.0.1\",\n            \"cardview\"            : \"com.android.support:cardview-v7:25.0.1\",\n            \"recyclerview-v7\"     : \"com.android.support:recyclerview-v7:25.0.1\",\n            \"retrofit\"            : \"com.squareup.retrofit2:retrofit:2.0.2\",\n            \"logging-interceptor\" : \"com.squareup.okhttp3:logging-interceptor:3.4.1\",\n            \"rxandroid\"           : \"io.reactivex:rxandroid:1.2.0\",\n            \"converter-gson\"      : \"com.squareup.retrofit2:converter-gson:2.0.2\",\n            \"adapter-rxjava\"      : \"com.squareup.retrofit2:adapter-rxjava:2.0.2\",\n            \"gson\"                : \"com.google.code.gson:gson:2.6.2\",\n            \"glide\"               : \"com.github.bumptech.glide:glide:3.7.0\",\n            \"butterknife\"         : \"com.jakewharton:butterknife:7.0.1\",\n            \"dagger\"              : \"com.google.dagger:dagger:2.0\",\n            \"dagger-compiler\"     : \"com.google.dagger:dagger-compiler:2.0\",\n            \"glassfish\"           : \"org.glassfish:javax.annotation:10.0-b28\",\n            \"react-native\"        : \"com.facebook.react:react-native:+\",\n            \"react-native-preloader\" : \"com.github.moduth:react-native-preloader:0.31.0\",\n            \"materialsearchview\"  : \"com.miguelcatalan:materialsearchview:1.4.0\"\n    ]\n}\n"
  }
]