From fbeb910c1ab843bd842e7c3f82fdbf6a7bcaa334 Mon Sep 17 00:00:00 2001 From: pengfeizhou Date: Wed, 4 Dec 2019 13:46:09 +0800 Subject: [PATCH 01/35] Add Readme --- README.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 00000000..c5fb175e --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# Doric Demos \ No newline at end of file From 8a6ae585bba5d34a166dae1f624b1a32b84e8286 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 4 Dec 2019 14:07:14 +0800 Subject: [PATCH 02/35] add project files from main project --- index.ts | 21 ++ package-lock.json | 268 ++++++++++++++++++++ package.json | 21 ++ rollup.config.js | 23 ++ src/AnimatorDemo.ts | 185 ++++++++++++++ src/ComplicatedAnimations.ts | 202 +++++++++++++++ src/ComplicatedDemo.ts | 49 ++++ src/Counter.ts | 121 +++++++++ src/EffectsDemo.ts | 367 ++++++++++++++++++++++++++++ src/FlowLayoutDemo.ts | 41 ++++ src/ImageDemo.ts | 109 +++++++++ src/LayoutDemo.ts | 460 +++++++++++++++++++++++++++++++++++ src/ListDemo.ts | 114 +++++++++ src/ModalDemo.ts | 150 ++++++++++++ src/NavbarDemo.ts | 84 +++++++ src/NavigatorDemo.ts | 52 ++++ src/NetworkDemo.ts | 34 +++ src/PopoverDemo.ts | 44 ++++ src/RefreshableDemo.ts | 95 ++++++++ src/ScrollerDemo.ts | 34 +++ src/SliderDemo.ts | 58 +++++ src/Snake.ts | 369 ++++++++++++++++++++++++++++ src/StorageDemo.ts | 93 +++++++ src/image_base64.ts | 2 + src/utils.ts | 72 ++++++ tsconfig.json | 61 +++++ 26 files changed, 3129 insertions(+) create mode 100644 index.ts create mode 100644 package-lock.json create mode 100644 package.json create mode 100644 rollup.config.js create mode 100644 src/AnimatorDemo.ts create mode 100644 src/ComplicatedAnimations.ts create mode 100644 src/ComplicatedDemo.ts create mode 100644 src/Counter.ts create mode 100644 src/EffectsDemo.ts create mode 100644 src/FlowLayoutDemo.ts create mode 100644 src/ImageDemo.ts create mode 100644 src/LayoutDemo.ts create mode 100644 src/ListDemo.ts create mode 100644 src/ModalDemo.ts create mode 100644 src/NavbarDemo.ts create mode 100644 src/NavigatorDemo.ts create mode 100644 src/NetworkDemo.ts create mode 100644 src/PopoverDemo.ts create mode 100644 src/RefreshableDemo.ts create mode 100644 src/ScrollerDemo.ts create mode 100644 src/SliderDemo.ts create mode 100644 src/Snake.ts create mode 100644 src/StorageDemo.ts create mode 100644 src/image_base64.ts create mode 100644 src/utils.ts create mode 100644 tsconfig.json diff --git a/index.ts b/index.ts new file mode 100644 index 00000000..bd7e494d --- /dev/null +++ b/index.ts @@ -0,0 +1,21 @@ +export default [ + 'src/Counter', + 'src/Snake', + 'src/ListDemo', + 'src/ScrollerDemo', + 'src/SliderDemo', + 'src/LayoutDemo', + 'src/EffectsDemo', + 'src/ImageDemo', + 'src/ModalDemo', + 'src/NetworkDemo', + 'src/StorageDemo', + 'src/NavigatorDemo', + 'src/NavbarDemo', + 'src/RefreshableDemo', + 'src/FlowLayoutDemo', + 'src/PopoverDemo', + 'src/AnimatorDemo', + 'src/ComplicatedAnimations', + 'src/ComplicatedDemo', +] \ No newline at end of file diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 00000000..ed538db2 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,268 @@ +{ + "name": "demo", + "version": "0.1.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "@types/node": { + "version": "12.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.7.tgz", + "integrity": "sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==" + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + }, + "doric": { + "version": "file:../js-framework", + "requires": { + "@types/ws": "^6.0.3", + "reflect-metadata": "^0.1.13", + "rollup": "^1.27.2", + "rollup-plugin-node-resolve": "^5.2.0", + "tslib": "^1.10.0", + "typescript": "^3.7.2", + "ws": "^7.2.0" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + }, + "@types/node": { + "version": "12.12.7", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.7.tgz", + "integrity": "sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==" + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/ws": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.3.tgz", + "integrity": "sha512-yBTM0P05Tx9iXGq00BbJPo37ox68R5vaGTXivs6RGh/BQ6QP5zqZDGWdAO6JbRE/iR1l80xeGAwCQS2nMV9S/w==", + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "1.26.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.26.5.tgz", + "integrity": "sha512-c6Pv0yWzjYNpy2DIhLFUnyP6e1UTGownr4IfpJcPY/k186RJjpaGGPRwKQ62KCauctG6dgtHt88pw1EGrPRkuA==", + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "typescript": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", + "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==" + }, + "ws": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", + "requires": { + "async-limiter": "^1.0.0" + } + } + } + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" + }, + "is-reference": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.1.4.tgz", + "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", + "requires": { + "@types/estree": "0.0.39" + } + }, + "magic-string": { + "version": "0.25.4", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.25.4.tgz", + "integrity": "sha512-oycWO9nEVAP2RVPbIoDoA4Y7LFIJ3xRYov93gAyJhZkET1tNuB0u7uWkZS2LpBWTJUWnmau/To8ECWRC+jKNfw==", + "requires": { + "sourcemap-codec": "^1.4.4" + } + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "resolve": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", + "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "1.27.2", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.2.tgz", + "integrity": "sha512-sD3iyd0zlvgK1S3MmICi6F/Y+R/QWY5XxzsTGN4pAd+nCasDUizmAhgq2hdh1t2eLux974NHU2TW41fhuGPv+Q==", + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-commonjs": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-commonjs/-/rollup-plugin-commonjs-10.1.0.tgz", + "integrity": "sha512-jlXbjZSQg8EIeAAvepNwhJj++qJWNJw1Cl0YnOqKtP5Djx+fFGkp3WRh+W0ASCaFG5w1jhmzDxgu3SJuVxPF4Q==", + "requires": { + "estree-walker": "^0.6.1", + "is-reference": "^1.1.2", + "magic-string": "^0.25.2", + "resolve": "^1.11.0", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, + "sourcemap-codec": { + "version": "1.4.6", + "resolved": "https://registry.npmjs.org/sourcemap-codec/-/sourcemap-codec-1.4.6.tgz", + "integrity": "sha512-1ZooVLYFxC448piVLBbtOxFcXwnymH9oUF8nRd3CuYDVvkRBxRl6pB4Mtas5a4drtL+E8LDgFkQNcgIw6tc8Hg==" + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "typescript": { + "version": "3.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", + "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==" + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 00000000..7c36fcc3 --- /dev/null +++ b/package.json @@ -0,0 +1,21 @@ +{ + "name": "demo", + "version": "0.1.0", + "main": "index.js", + "scripts": { + "test": "echo \"Error: no test specified\" && exit 1", + "build": "tsc -p .&& rollup -c", + "dev": "tsc -w -p . & rollup -c -w", + "clean": "rm -rf build && rm -rf bundle" + }, + "license": "Apache-2.0", + "dependencies": { + "doric": "file:../js-framework", + "reflect-metadata": "^0.1.13", + "rollup": "^1.27.2", + "rollup-plugin-commonjs": "^10.1.0", + "rollup-plugin-node-resolve": "^5.2.0", + "tslib": "^1.10.0", + "typescript": "^3.7.2" + } +} diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 00000000..3e5b5b75 --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,23 @@ +import resolve from 'rollup-plugin-node-resolve' +import commonjs from 'rollup-plugin-commonjs' +import bundles from './build/index' + +export default bundles.map(bundle => { + return { + input: `build/${bundle}.js`, + output: { + format: "cjs", + file: `bundle/${bundle}.js`, + sourcemap: true, + }, + plugins: [ + resolve({ mainFields: ["jsnext"] }), + commonjs() + ], + external: ['reflect-metadata', 'doric'], + onwarn: function (warning) { + if (warning.code === 'THIS_IS_UNDEFINED') { return; } + console.warn(warning.message); + } + } +}) \ No newline at end of file diff --git a/src/AnimatorDemo.ts b/src/AnimatorDemo.ts new file mode 100644 index 00000000..185acd51 --- /dev/null +++ b/src/AnimatorDemo.ts @@ -0,0 +1,185 @@ +import { animate, Group, Panel, gravity, Color, AnimationSet, vlayout, scroller, layoutConfig, IVLayout, modal, IText, network, View, stack, IHLayout, hlayout, IView, text, TranslationAnimation, ScaleAnimation, RotationAnimation, FillMode } from "doric"; +import { title, colors, box } from "./utils"; + +function thisLabel(str: string) { + return text({ + text: str, + width: 60, + height: 50, + backgroundColor: colors[0], + textSize: 15, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + }) +} + +@Entry +class AnimatorDemo extends Panel { + build(rootView: Group): void { + const view = box(2) + view.onClick = () => { + modal(context).toast('Clicked') + } + const view2 = box(3) + let idx = 0 + vlayout([ + title("Animator Demo"), + vlayout( + [ + hlayout([ + thisLabel('Reset').apply({ + onClick: () => { + animate(this)({ + animations: () => { + view.width = view.height = 20 + view.x = view.y = 0 + view.rotation = 0 + view.backgroundColor = colors[2] + view.corners = 0 + view.scaleX = 1 + view.scaleY = 1 + view.translationX = 0 + view.translationY = 0 + view.rotation = 0 + }, + duration: 1500, + }).then(() => { + modal(context).toast('Fininshed') + }).catch(e => { + modal(context).toast(`${e}`) + }) + } + }), + ]).apply({ space: 10 } as IHLayout), + hlayout([ + thisLabel('X').apply({ + onClick: () => { + animate(this)({ + animations: () => { + view.x = view.x || 0 + view.x += 100 + view2.x += 50 + }, + duration: 1000, + }) + } + }), + thisLabel('Y').apply({ + onClick: () => { + animate(this)({ + animations: () => { + view.y = view.y || 0 + view.y += 100 + view2.y += 50 + }, + duration: 1000, + }) + } + }), + thisLabel('Width').apply({ + onClick: () => { + animate(this)({ + animations: () => { + view.width += 100 + }, + duration: 1000, + }) + } + }), + thisLabel('Height').apply({ + onClick: () => { + animate(this)({ + animations: () => { + view.height += 100 + }, + duration: 1000, + }) + } + }), + ]).apply({ space: 10 } as IHLayout), + hlayout([ + thisLabel('BgColor').apply({ + onClick: () => { + animate(this)({ + animations: () => { + view.backgroundColor = colors[(idx++) % colors.length] + }, + duration: 1000, + }); + } + }), + thisLabel('Rotation').apply({ + onClick: () => { + animate(this)({ + animations: () => { + if (view.rotation) { + view.rotation += 0.5 + } else { + view.rotation = 0.5 + } + }, + duration: 1000, + }); + } + }), + thisLabel('Corner').apply({ + onClick: () => { + animate(this)({ + animations: () => { + if (typeof view.corners === 'number') { + view.corners += 10 + } else { + view.corners = 10 + } + }, + duration: 1000, + }); + } + }), + ]).apply({ space: 10 } as IHLayout), + + hlayout([ + thisLabel('scaleX').apply({ + onClick: () => { + animate(this)({ + animations: () => { + if (view.scaleX) { + view.scaleX += 0.1 + } else { + view.scaleX = 1.1 + } + }, + duration: 1000, + }); + } + }), + thisLabel('scaleY').apply({ + onClick: () => { + animate(this)({ + animations: () => { + if (view.scaleY) { + view.scaleY += 0.1 + } else { + view.scaleY = 1.1 + } + }, + duration: 1000, + }); + } + }), + ]).apply({ space: 10 } as IHLayout), + ] + ).apply({ space: 10 } as IVLayout), + stack([ + view, + ]).apply({ + layoutConfig: layoutConfig().atmost(), + backgroundColor: colors[1].alpha(0.3 * 255), + }), + ]).apply({ + layoutConfig: layoutConfig().atmost(), + gravity: gravity().center(), + space: 10, + } as IVLayout).in(rootView) + } +} \ No newline at end of file diff --git a/src/ComplicatedAnimations.ts b/src/ComplicatedAnimations.ts new file mode 100644 index 00000000..bc477830 --- /dev/null +++ b/src/ComplicatedAnimations.ts @@ -0,0 +1,202 @@ +import { animate, Group, Panel, gravity, Color, AnimationSet, vlayout, scroller, layoutConfig, IVLayout, modal, IText, network, View, stack, IHLayout, hlayout, IView, text, TranslationAnimation, ScaleAnimation, RotationAnimation, FillMode, TimingFunction } from "doric"; +import { title, colors, box } from "./utils"; + +function thisLabel(str: string) { + return text({ + text: str, + width: 80, + height: 30, + backgroundColor: colors[0], + textSize: 10, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + }) +} + +@Entry +class AnimationDemo extends Panel { + build(rootView: Group): void { + const view = box(2) + const view2 = box(3) + view.onClick = () => { + modal(context).toast('Clicked') + } + vlayout([ + title("Complicated Animation"), + vlayout( + [ + hlayout([ + thisLabel('reset').apply({ + onClick: () => { + const rotation = new RotationAnimation + rotation.duration = 1000 + rotation.fromRotation = view.rotation || 0 + rotation.toRotation = 0 + const translation = new TranslationAnimation + translation.duration = 1000 + translation.fromTranslationX = view.translationX || 0 + translation.toTranslationX = 0 + translation.fromTranslationY = view.translationY || 0 + translation.toTranslationY = 0 + const scale = new ScaleAnimation + scale.duration = 1000 + scale.fromScaleX = view.scaleX || 1 + scale.toScaleX = 1 + scale.fromScaleY = view.scaleY || 1 + scale.toScaleY = 1 + const animationSet = new AnimationSet + animationSet.addAnimation(rotation) + animationSet.addAnimation(translation) + animationSet.addAnimation(scale) + view.doAnimation(context, animationSet).then(() => { + modal(context).toast('Resetd') + }) + } + }), + ]).apply({ space: 10 } as IHLayout), + hlayout([ + thisLabel('TranslationX').apply({ + onClick: () => { + const animation = new TranslationAnimation + animation.duration = 1000 + animation.fromTranslationX = view.translationX || 0 + animation.toTranslationX = animation.fromTranslationX + 100 + animation.fromTranslationY = view.translationY || 0 + animation.toTranslationY = view.translationY || 0 + view.doAnimation(context, animation) + } + }), + thisLabel('TranslationY').apply({ + onClick: () => { + const animation = new TranslationAnimation + animation.duration = 1000 + animation.fromTranslationX = view.translationX || 0 + animation.toTranslationX = view.translationX || 0 + animation.fromTranslationY = view.translationY || 0 + animation.toTranslationY = animation.fromTranslationY + 100 + view.doAnimation(context, animation) + } + }), + thisLabel('ScaleX').apply({ + onClick: () => { + const animation = new ScaleAnimation + animation.duration = 1000 + animation.fromScaleX = view.scaleX || 1 + animation.toScaleX = animation.fromScaleX + 1 + view.doAnimation(context, animation) + } + }), + thisLabel('ScaleY').apply({ + onClick: () => { + const animation = new ScaleAnimation + animation.duration = 1000 + animation.fromScaleY = view.scaleY || 1 + animation.toScaleY = animation.fromScaleY + 1 + view.doAnimation(context, animation) + } + }), + thisLabel('rotation').apply({ + onClick: () => { + const animation = new RotationAnimation + animation.duration = 1000 + animation.fromRotation = view.rotation || 0 + animation.toRotation = animation.fromRotation + 0.25 + view.doAnimation(context, animation) + } + }), + ]).apply({ space: 10 } as IHLayout), + hlayout([ + thisLabel('group').apply({ + onClick: () => { + const rotation = new RotationAnimation + rotation.duration = 1000 + rotation.fromRotation = 0 + rotation.toRotation = 4 + const translation = new TranslationAnimation + translation.duration = 1000 + translation.fromTranslationX = view.translationX || 0 + translation.toTranslationX = 100 + const animationSet = new AnimationSet + animationSet.addAnimation(rotation) + animationSet.addAnimation(translation) + view.doAnimation(context, animationSet) + } + }), + ]).apply({ space: 10 } as IHLayout), + hlayout([ + thisLabel('Default').apply({ + onClick: () => { + const translation = new TranslationAnimation + translation.duration = 3000 + translation.fromTranslationX = 0 + translation.toTranslationX = 300 + translation.timingFunction = TimingFunction.Default + view.doAnimation(context, translation) + } + }), + thisLabel('Linear').apply({ + onClick: () => { + const translation = new TranslationAnimation + translation.duration = 3000 + translation.fromTranslationX = 0 + translation.toTranslationX = 300 + translation.timingFunction = TimingFunction.Linear + view.doAnimation(context, translation) + } + }), + thisLabel('EaseIn').apply({ + onClick: () => { + const translation = new TranslationAnimation + translation.duration = 3000 + translation.fromTranslationX = 0 + translation.toTranslationX = 300 + translation.timingFunction = TimingFunction.EaseIn + view.doAnimation(context, translation) + } + }), + thisLabel('EaseOut').apply({ + onClick: () => { + const translation = new TranslationAnimation + translation.duration = 3000 + translation.fromTranslationX = 0 + translation.toTranslationX = 300 + translation.timingFunction = TimingFunction.EaseOut + view.doAnimation(context, translation) + } + }), + thisLabel('EaseInEaseOut').apply({ + onClick: () => { + const translation = new TranslationAnimation + translation.duration = 3000 + translation.fromTranslationX = 0 + translation.toTranslationX = 300 + translation.timingFunction = TimingFunction.EaseInEaseOut + view.doAnimation(context, translation) + } + }), + ]).apply({ space: 10 } as IHLayout), + ] + ).apply({ space: 10 } as IVLayout), + stack([ + view.also(v => { + v.x = 20 + v.y = 0 + v.width = 30 + v.left = 15 + }), + view2.also(v => { + v.x = v.y = 20 + v.y = 40 + v.scaleX = 1.5 + }) + ]).apply({ + layoutConfig: layoutConfig().atmost(), + backgroundColor: colors[1].alpha(0.3 * 255), + }), + ]).apply({ + layoutConfig: layoutConfig().atmost(), + gravity: gravity().center(), + space: 10, + } as IVLayout).in(rootView) + } +} \ No newline at end of file diff --git a/src/ComplicatedDemo.ts b/src/ComplicatedDemo.ts new file mode 100644 index 00000000..c4c4db2f --- /dev/null +++ b/src/ComplicatedDemo.ts @@ -0,0 +1,49 @@ +import { Panel, Group, vlayout, image, layoutConfig, ScaleType, refreshable, Color, pullable, stack, Image, Refreshable, TranslationAnimation, loge, log } from "doric"; +import { title, icon_refresh } from "./utils"; + +@Entry +class MyDemo extends Panel { + build(root: Group) { + let refreshed: Refreshable + let headerImage: Image + stack([ + refreshed = refreshable({ + onRefresh: () => { + refreshed.setRefreshing(context, false) + }, + header: pullable(context, + stack([]).apply({ + backgroundColor: Color.RED, + layoutConfig: layoutConfig().exactly(), + width: 100, + height: 30, + }), + { + startAnimation: () => { + }, + stopAnimation: () => { + }, + setPullingDistance: (distance: number) => { + headerImage.scaleX = headerImage.scaleY = (headerImage.height + distance * 2) / headerImage.height + log(`Header Image scaleY:${headerImage.scaleY},height:${headerImage.height},distance:${distance}`) + }, + }), + content: vlayout([]).apply({ + backgroundColor: Color.YELLOW, + }), + }).apply({ + layoutConfig: layoutConfig().atmost(), + }).also(v => { + v.top = 200 + }), + + headerImage = image({ + imageUrl: "https://img.zcool.cn/community/01e75b5da933daa801209e1ffa4649.jpg@1280w_1l_2o_100sh.jpg", + layoutConfig: layoutConfig().exactly(), + width: root.width, + height: 200, + scaleType: ScaleType.ScaleAspectFill, + }), + ]).in(root) + } +} \ No newline at end of file diff --git a/src/Counter.ts b/src/Counter.ts new file mode 100644 index 00000000..3b152919 --- /dev/null +++ b/src/Counter.ts @@ -0,0 +1,121 @@ +import { text, vlayout, Image, ViewHolder, VMPanel, ViewModel, Gravity, NativeCall, Text, Color, log, logw, loge, Group, LayoutSpec, } from "doric" + +interface CountModel { + count: number +} + +class CounterView extends ViewHolder { + + number!: Text + counter!: Text + build(root: Group) { + root.addChild(vlayout([ + text({ + textSize: 40, + layoutConfig: { + alignment: Gravity.Center, + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + }, + }).also(it => { this.number = it }), + text({ + text: "点击计数", + textSize: 20, + border: { + width: 1, + color: Color.parse('#000000'), + }, + corners: 5, + layoutConfig: { + alignment: Gravity.Center, + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + }, + shadow: { + color: Color.parse("#00ff00"), + opacity: 0.5, + radius: 20, + offsetX: 10, + offsetY: 10, + } + }).also(it => { this.counter = it }), + ]).also(it => { + it.width = 200 + it.height = 200 + it.space = 20 + it.gravity = Gravity.Center + it.layoutConfig = { + alignment: Gravity.Center + } + it.border = { + width: 1, + color: Color.parse("#000000"), + } + it.shadow = { + color: Color.parse("#ffff00"), + opacity: 0.5, + radius: 20, + offsetX: 10, + offsetY: 10, + } + it.corners = 20 + it.backgroundColor = Color.parse('#ff00ff') + })) + + root.addChild((new Image).also(iv => { + iv.imageUrl = "https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png" + iv.layoutConfig = { + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + } + })) + } + + bind(state: CountModel) { + this.number.text = `${state.count}` + } + + setCounter(v: Function) { + this.counter.onClick = v + } +} + +class CounterVM extends ViewModel { + onAttached(s: CountModel, vh: CounterView): void { + vh.counter.onClick = () => { + this.updateState(state => { + state.count++ + }) + } + } +} + +@Entry +class MyPage extends VMPanel{ + + + getViewHolderClass() { + return CounterView + } + + getViewModelClass() { + return CounterVM + } + + getState(): CountModel { + return { + count: 0 + } + } + + + @NativeCall + log() { + log("Hello.HEGO") + logw("Hello.HEGO") + loge("Hello.HEGO") + context.modal.toast('This is a toast.').then((r) => { + loge(r) + }) + } +} \ No newline at end of file diff --git a/src/EffectsDemo.ts b/src/EffectsDemo.ts new file mode 100644 index 00000000..126d6728 --- /dev/null +++ b/src/EffectsDemo.ts @@ -0,0 +1,367 @@ + +import { Group, Panel, Text, text, gravity, Color, Stack, LayoutSpec, vlayout, hlayout, scroller, IVLayout, IHLayout, layoutConfig, Gravity } from "doric"; +import { colors } from "./utils"; + + +function box(idx = 0) { + return (new Stack).also(it => { + it.width = it.height = 20 + it.backgroundColor = colors[idx || 0] + }) +} + +function boxStr(str: string, idx = 0) { + return (new Text).also(it => { + it.width = it.height = 20 + it.text = str + it.textColor = Color.WHITE + it.backgroundColor = colors[idx || 0] + }) +} + +function label(str: string) { + return text({ + text: str, + textSize: 16, + }) +} + +@Entry +class EffectsDemo extends Panel { + build(rootView: Group) { + scroller( + vlayout([ + hlayout([ + vlayout([ + label("Origin view"), + box().apply({ + width: 100, + height: 100 + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Border"), + box().apply({ + width: 100, + height: 100, + border: { + width: 5, + color: colors[3] + }, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Corner"), + box().apply({ + width: 100, + height: 100, + corners: 10, + layoutConfig: layoutConfig().exactly().m({ + bottom: 10 + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Shadow"), + box().apply({ + width: 100, + height: 100, + shadow: { + opacity: 1, + color: colors[1], + offsetX: 3, + offsetY: 3, + radius: 5, + }, + layoutConfig: layoutConfig().exactly().m({ + bottom: 10 + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + ]).apply({ space: 20 } as IHLayout), + hlayout([ + vlayout([ + label("Border,Corner"), + box().apply({ + width: 100, + height: 100, + border: { + width: 5, + color: colors[3] + }, + corners: 10, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Border,Shadow"), + box().apply({ + width: 100, + height: 100, + border: { + width: 5, + color: colors[3] + }, + shadow: { + opacity: 1, + color: colors[1], + offsetX: 3, + offsetY: 3, + radius: 5, + }, + layoutConfig: layoutConfig().exactly().m({ + bottom: 10 + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Corner,Shadow"), + box().apply({ + width: 100, + height: 100, + corners: 10, + shadow: { + opacity: 1, + color: colors[1], + offsetX: 3, + offsetY: 3, + radius: 5, + }, + layoutConfig: layoutConfig().exactly().m({ + bottom: 10 + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Border,Corner,Shadow"), + box().apply({ + width: 100, + height: 100, + border: { + width: 5, + color: colors[3] + }, + corners: 10, + shadow: { + opacity: 1, + color: colors[1], + offsetX: 3, + offsetY: 3, + radius: 5, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + ]).apply({ space: 20 } as IHLayout), + hlayout([ + vlayout([ + label("Shadow"), + box().apply({ + width: 100, + height: 100, + corners: 50, + shadow: { + opacity: 1, + color: colors[1], + offsetX: 0, + offsetY: 0, + radius: 10, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 10, + right: 10, + bottom: 10, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Shadow,offset"), + box().apply({ + width: 100, + height: 100, + corners: 50, + shadow: { + opacity: 1, + color: colors[1], + offsetX: 5, + offsetY: 5, + radius: 5, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 10, + right: 10, + bottom: 10, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Shadow,opacity"), + box().apply({ + width: 100, + height: 100, + corners: 50, + shadow: { + opacity: 0.5, + color: colors[1], + offsetX: 5, + offsetY: 5, + radius: 5, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 10, + right: 10, + bottom: 10, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Shadow,color"), + box().apply({ + width: 100, + height: 100, + corners: 50, + shadow: { + opacity: 1, + color: colors[2], + offsetX: 5, + offsetY: 5, + radius: 5, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 10, + right: 10, + bottom: 10, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + ]).apply({ space: 20 } as IHLayout), + hlayout([ + vlayout([ + label("Corner round"), + box().apply({ + width: 100, + height: 100, + corners: 50, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Corner left top"), + box().apply({ + width: 100, + height: 100, + corners: { + leftTop: 50, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Corner right top"), + box().apply({ + width: 100, + height: 100, + corners: { + rightTop: 50, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Corner left bottom"), + box().apply({ + width: 100, + height: 100, + corners: { + leftBottom: 50, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + vlayout([ + label("Corner right bottom"), + box().apply({ + width: 100, + height: 100, + corners: { + rightBottom: 50, + }, + layoutConfig: layoutConfig().exactly().m({ + left: 5, + right: 5, + bottom: 5, + }) + }),]).apply({ + gravity: Gravity.Center, + space: 10, + } as IVLayout), + ]).apply({ space: 20 } as IHLayout), + ]).also(it => { + it.space = 20 + }), + ).also(it => { + it.layoutConfig = layoutConfig().atmost() + }).in(rootView) + } +} \ No newline at end of file diff --git a/src/FlowLayoutDemo.ts b/src/FlowLayoutDemo.ts new file mode 100644 index 00000000..f668cc08 --- /dev/null +++ b/src/FlowLayoutDemo.ts @@ -0,0 +1,41 @@ +import { Group, Panel, flowlayout, layoutConfig, FlowLayoutItem, text, Color, IFlowLayout, LayoutSpec, Gravity } from "doric"; +import { colors, label } from "./utils"; + +const imageUrls = [ + 'http://b.hiphotos.baidu.com/image/pic/item/908fa0ec08fa513db777cf78376d55fbb3fbd9b3.jpg', + 'http://f.hiphotos.baidu.com/image/pic/item/0e2442a7d933c8956c0e8eeadb1373f08202002a.jpg', + 'http://f.hiphotos.baidu.com/image/pic/item/b151f8198618367aa7f3cc7424738bd4b31ce525.jpg', + 'http://b.hiphotos.baidu.com/image/pic/item/0eb30f2442a7d9337119f7dba74bd11372f001e0.jpg', + 'http://a.hiphotos.baidu.com/image/h%3D300/sign=b38f3fc35b0fd9f9bf175369152cd42b/9a504fc2d5628535bdaac29e9aef76c6a6ef63c2.jpg', + 'http://h.hiphotos.baidu.com/image/pic/item/810a19d8bc3eb1354c94a704ac1ea8d3fd1f4439.jpg', + 'http://calonye.com/wp-content/uploads/2015/08/0-wx_fmtgiftpwebpwxfrom5wx_lazy1-9.gif', + 'http://hbimg.b0.upaiyun.com/ca29ea125b7f2d580f573e48eb594b1ef509757f34a08-m0hK45_fw658', + 'https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png', +] +@Entry +class FlowDemo extends Panel { + build(rootView: Group): void { + flowlayout({ + layoutConfig: layoutConfig().atmost(), + itemCount: 500, + columnCount: 3, + columnSpace: 10, + rowSpace: 10, + renderItem: (idx) => { + return new FlowLayoutItem().apply({ + backgroundColor: colors[idx % colors.length], + height: 50 + (idx % 3) * 20, + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + }).also(it => { + it.addChild(text({ + text: `${idx}`, + textColor: Color.WHITE, + textSize: 20, + layoutConfig: layoutConfig().wrap().a(Gravity.Center) + })) + }) + }, + }) + .in(rootView) + } +} \ No newline at end of file diff --git a/src/ImageDemo.ts b/src/ImageDemo.ts new file mode 100644 index 00000000..357a8e22 --- /dev/null +++ b/src/ImageDemo.ts @@ -0,0 +1,109 @@ +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, Image } from "doric"; +import { colors, label } from "./utils"; +import { img_base64 } from "./image_base64"; +const imageUrl = 'https://img.zcool.cn/community/01e75b5da933daa801209e1ffa4649.jpg@1280w_1l_2o_100sh.jpg' + +@Entry +class ImageDemo extends Panel { + build(rootView: Group): void { + let imageView: Image + scroller(vlayout([ + text({ + text: "Image Demo", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[5], + textAlignment: gravity().center(), + height: 50, + }), + label('Gif'), + image({ + imageUrl: "https://misc.aotu.io/ONE-SUNDAY/world-cup_2014_42.gif", + scaleType: ScaleType.ScaleToFill, + loadCallback: function (ret) { + log('this') + log('loadCallback', ret) + } + }), + label('APNG'), + image({ + imageUrl: "https://misc.aotu.io/ONE-SUNDAY/world_cup_2014_42.png", + loadCallback: (ret) => { + } + }), + label('Animated WebP'), + image({ + imageUrl: "https://p.upyun.com/demo/webp/webp/animated-gif-0.webp", + loadCallback: (ret) => { + } + }), + label('WebP'), + imageView = image({ + imageUrl: "https://p.upyun.com/demo/webp/webp/jpg-0.webp", + loadCallback: (ret) => { + if (ret) { + imageView.width = ret.width + imageView.height = ret.height + } + } + }), + label('ScaleToFill'), + image({ + imageUrl, + width: 300, + height: 300, + border: { + width: 2, + color: Color.GRAY, + }, + scaleType: ScaleType.ScaleToFill, + layoutConfig: layoutConfig().exactly(), + loadCallback: (ret) => { + } + }), + label('ScaleAspectFit'), + image({ + imageUrl, + width: 300, + height: 300, + border: { + width: 2, + color: Color.GRAY, + }, + scaleType: ScaleType.ScaleAspectFit, + layoutConfig: layoutConfig().exactly(), + }), + label('ScaleAspectFill'), + image({ + imageUrl, + width: 300, + height: 300, + border: { + width: 2, + color: Color.GRAY, + }, + scaleType: ScaleType.ScaleAspectFill, + layoutConfig: layoutConfig().exactly(), + }), + label('ImageBase64'), + image({ + imageBase64: img_base64, + width: 300, + height: 300, + border: { + width: 2, + color: Color.GRAY, + }, + scaleType: ScaleType.ScaleAspectFill, + layoutConfig: layoutConfig().exactly(), + }), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/src/LayoutDemo.ts b/src/LayoutDemo.ts new file mode 100644 index 00000000..b4762dbb --- /dev/null +++ b/src/LayoutDemo.ts @@ -0,0 +1,460 @@ + +import { Group, Panel, Text, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, slider, slideItem, scroller, IVLayout, IHLayout, layoutConfig } from "doric"; +import { O_TRUNC } from "constants"; + +const colors = [ + "#f0932b", + "#eb4d4b", + "#6ab04c", + "#e056fd", + "#686de0", + "#30336b", +] + +function box(idx = 0) { + return (new Stack).also(it => { + it.width = it.height = 20 + it.backgroundColor = Color.parse(colors[idx || 0]) + }) +} +function boxStr(str: string, idx = 0) { + return (new Text).also(it => { + it.width = it.height = 20 + it.text = str + it.textColor = Color.parse('#ffffff') + it.backgroundColor = Color.parse(colors[idx || 0]) + }) +} +function label(str: string) { + return text({ + text: str, + textSize: 16, + }) +} +@Entry +class LayoutDemo extends Panel { + build(rootView: Group) { + scroller( + hlayout([ + vlayout([ + label("Horizontal Layout(Align to Top)"), + hlayout([ + box().apply({ + height: 20 + }), + box().apply({ + height: 40 + }), + box().apply({ + height: 60 + }), + box().apply({ + height: 40 + }), + box().apply({ + height: 20 + }), + ]).also(it => { + it.space = 20 + }), + label("Horizontal Layout(Align to Bottom)"), + hlayout([ + box().apply({ + height: 20 + }), + box().apply({ + height: 40 + }), + box().apply({ + height: 60 + }), + box().apply({ + height: 40 + }), + box().apply({ + height: 20 + }), + ]).also(it => { + it.space = 20 + it.gravity = gravity().bottom() + }), + label("Horizontal Layout(Align to Center)"), + hlayout([ + box().apply({ + height: 20 + }), + box().apply({ + height: 40 + }), + box().apply({ + height: 60 + }), + box().apply({ + height: 40 + }), + box().apply({ + height: 20 + }), + ]).also(it => { + it.space = 20 + it.gravity = gravity().center() + }), + label("Horizontal Layout(Weight)"), + hlayout([ + boxStr('weight=1', 3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + box(2), + box(4), + ]).apply({ + width: 200, + height: 30, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IHLayout), + hlayout([ + box(3), + boxStr('weight=1', 2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + box(4), + ]).apply({ + width: 200, + height: 30, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IHLayout), + hlayout([ + box(3), + box(2), + boxStr('weight=1', 4).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + ]).apply({ + width: 200, + height: 30, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IHLayout), + hlayout([ + boxStr('weight=1', 3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + boxStr('weight=1', 2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + box(4), + ]).apply({ + width: 200, + height: 30, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IHLayout), + hlayout([ + boxStr('weight=1', 3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + boxStr('weight=1', 2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + boxStr('weight=1', 4).apply({ + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + ]).apply({ + width: 200, + height: 30, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IHLayout), + ]).also(it => { + it.space = 20 + it.gravity = gravity().center() + }), + vlayout([ + label("Vertical Layout(Algin to Left)"), + vlayout([ + box(1).apply({ + width: 20 + }), + box(1).apply({ + width: 40 + }), + box(1).apply({ + width: 60 + }), + box(1).apply({ + width: 40 + }), + box(1).apply({ + width: 20 + }), + ]).apply({ + space: 20 + } as IVLayout), + label("Vertical Layout(Algin to Right)"), + vlayout([ + box(1).apply({ + width: 20 + }), + box(1).apply({ + width: 40 + }), + box(1).apply({ + width: 60 + }), + box(1).apply({ + width: 40 + }), + box(1).apply({ + width: 20 + }), + ]).apply({ + space: 20, + gravity: gravity().right(), + } as IVLayout), + label("Vertical Layout(Algin to Center)"), + vlayout([ + box(1).apply({ + width: 20 + }), + box(1).apply({ + width: 40 + }), + box(1).apply({ + width: 60 + }), + box(1).apply({ + width: 40 + }), + box(1).apply({ + width: 20 + }), + ]).apply({ + space: 20, + gravity: gravity().center(), + } as IVLayout), + label("Vertical Layout(Weight)"), + hlayout([ + + vlayout([ + boxStr('weight=1', 3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + }, + }), + box(2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + } + }), + box(4).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + } + }), + ]).apply({ + width: 100, + height: 200, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IVLayout), + vlayout([ + box(3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + }, + }), + boxStr('weight=1', 2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + box(4).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + } + }), + ]).apply({ + width: 100, + height: 200, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IVLayout), + vlayout([ + box(3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + }, + }), + box(2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + }, + }), + boxStr('weight=1', 4).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + ]).apply({ + width: 100, + height: 200, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IVLayout), + vlayout([ + boxStr('weight=1', 3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + }, + }), + boxStr('weight=1', 2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + box(4).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + } + }), + ]).apply({ + width: 100, + height: 200, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IVLayout), + vlayout([ + boxStr('weight=1', 3).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + }, + }), + boxStr('weight=1', 2).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + boxStr('weight=1', 4).apply({ + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + weight: 1, + } + }), + ]).apply({ + width: 100, + height: 200, + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + backgroundColor: Color.parse('#eeeeee'), + gravity: gravity().center(), + } as IVLayout), + ]).also(it => { + it.space = 20 + }), + + ]).also(it => { + it.space = 20 + it.gravity = gravity().left() + }) + ]).also(it => { + it.space = 20 + }), + ).also(it => { + it.layoutConfig = layoutConfig().atmost() + }) + .in(rootView) + } +} \ No newline at end of file diff --git a/src/ListDemo.ts b/src/ListDemo.ts new file mode 100644 index 00000000..ebd5c186 --- /dev/null +++ b/src/ListDemo.ts @@ -0,0 +1,114 @@ +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, refreshable, Refreshable, ListItem } from "doric"; +import { rotatedArrow, colors } from "./utils"; +@Entry +class ListPanel extends Panel { + build(rootView: Group): void { + let refreshView: Refreshable + let offset = Math.ceil(Math.random() * colors.length) + vlayout([ + text({ + text: "ListDemo", + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + }, + textSize: 30, + textColor: Color.parse("#535c68"), + backgroundColor: Color.parse("#dff9fb"), + textAlignment: gravity().center(), + height: 50, + }), + refreshView = refreshable({ + onRefresh: () => { + refreshView.setRefreshing(context, false).then(() => { + (refreshView.content as List).also(it => { + it.reset() + offset = Math.ceil(Math.random() * colors.length) + it.itemCount = 40 + it.renderItem = (idx: number) => { + let counter!: Text + return listItem( + hlayout([ + text({ + layoutConfig: { + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.EXACTLY, + alignment: gravity().center(), + }, + text: `Cell At Line ${idx}`, + textAlignment: gravity().center(), + textColor: Color.parse("#ffffff"), + textSize: 20, + height: 50, + }), + text({ + textColor: Color.parse("#ffffff"), + textSize: 20, + text: "", + }).also(it => { + counter = it + it.layoutConfig = { + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + margin: { + left: 10, + } + } + }) + ]).also(it => { + it.layoutConfig = { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.WRAP_CONTENT, + margin: { + bottom: 2, + } + } + it.gravity = gravity().center() + it.backgroundColor = colors[(idx + offset) % colors.length] + let clicked = 0 + it.onClick = () => { + counter.text = `Item Clicked ${++clicked}` + } + }) + ).also(it => { + it.layoutConfig = { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.WRAP_CONTENT, + } + it.onClick = () => { + log(`Click item at ${idx}`) + it.height += 10 + it.nativeChannel(context, "getWidth")().then( + resolve => { + log(`resolve,${resolve}`) + }, + reject => { + log(`reject,${reject}`) + }) + } + }) + } + }) + }) + }, + header: rotatedArrow(context), + content: list({ + itemCount: 0, + renderItem: () => new ListItem, + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.AT_MOST, + }, + }), + }), + + ]).also(it => { + it.layoutConfig = { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.AT_MOST, + } + it.backgroundColor = Color.WHITE + }).in(rootView) + refreshView.backgroundColor = Color.YELLOW + } +} \ No newline at end of file diff --git a/src/ModalDemo.ts b/src/ModalDemo.ts new file mode 100644 index 00000000..2086e1b0 --- /dev/null +++ b/src/ModalDemo.ts @@ -0,0 +1,150 @@ +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, IText, modal } from "doric"; +import { colors, label } from "./utils"; + +@Entry +class ModalDemo extends Panel { + build(rootView: Group): void { + scroller(vlayout([ + text({ + text: "Modal", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[1], + textAlignment: Gravity.Center, + height: 50, + }), + label('toast on bottom'), + label('Click me').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + modal(context).toast('This is a toast.') + } + } as IText), + label('toast on top'), + label('Click me').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + modal(context).toast('This is a toast.', Gravity.Top) + } + } as IText), + + label('toast on center'), + label('Click me').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + modal(context).toast('This is a toast.', Gravity.Center) + } + } as IText), + text({ + text: "Alert", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[2], + textAlignment: Gravity.Center, + height: 50, + }), + label('Click me').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + modal(context).alert({ + msg: 'This is alert.', + title: 'Alert title', + okLabel: "OkLabel" + }).then(e => { + modal(context).toast('Clicked OK.') + }) + } + } as IText), + text({ + text: "Confirm", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[3], + textAlignment: Gravity.Center, + height: 50, + }), + label('Click me').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + modal(context).confirm({ + msg: 'This is Confirm.', + title: 'Confirm title', + okLabel: "OkLabel", + cancelLabel: 'CancelLabel', + }).then( + () => { + modal(context).toast('Clicked OK.') + }, + () => { + modal(context).toast('Clicked Cancel.') + }) + } + } as IText), + text({ + text: "Prompt", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[4], + textAlignment: Gravity.Center, + height: 50, + }), + label('Click me').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + modal(context).prompt({ + msg: 'This is Prompt.', + title: 'Prompt title', + okLabel: "OkLabel", + cancelLabel: 'CancelLabel', + }).then( + e => { + modal(context).toast(`Clicked OK.Input:${e}`) + }, + e => { + modal(context).toast(`Clicked Cancel.Input:${e}`) + }) + } + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: Gravity.Center, + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/src/NavbarDemo.ts b/src/NavbarDemo.ts new file mode 100644 index 00000000..43b743ca --- /dev/null +++ b/src/NavbarDemo.ts @@ -0,0 +1,84 @@ +import { Group, Panel, navbar, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, modal, IText, network, navigator } from "doric"; +import { title, label, colors } from "./utils"; + +@Entry +class NavbarDemo extends Panel { + build(rootView: Group): void { + scroller(vlayout([ + title("Navbar Demo"), + label('isHidden').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).isHidden().then(e => modal(context).alert(`Navbar isHidden:${e}`)).catch(e => { + modal(context).alert(e) + }) + } + } as IText), + label('setHidden').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).isHidden() + .then(e => navbar(context).setHidden(!e)) + .catch(e => { + modal(context).alert(e) + }) + } + } as IText), + label('setTitle').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).setTitle('Setted Title') + .catch(e => { + modal(context).alert(e) + }) + } + } as IText), + label('setBgColor').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navbar(context).setBgColor(Color.YELLOW) + .catch(e => { + modal(context).alert(e) + }) + } + } as IText), + label('Pop').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navigator(context).pop() + } + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/src/NavigatorDemo.ts b/src/NavigatorDemo.ts new file mode 100644 index 00000000..03796ef5 --- /dev/null +++ b/src/NavigatorDemo.ts @@ -0,0 +1,52 @@ +import { Panel, scroller, vlayout, text, layoutConfig, LayoutSpec, Color, gravity, IVLayout, Group, IText, navigator } from "doric"; +import { colors, label } from "./utils"; +@Entry +class NaivgatorDemo extends Panel { + build(root: Group) { + scroller(vlayout([ + text({ + text: "Navigator Demo", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[1], + textAlignment: gravity().center(), + height: 50, + }), + ...[ + 'NavbarDemo', + 'Counter', 'EffectsDemo', 'ImageDemo', 'LayoutDemo', + 'ListDemo', 'ModalDemo', 'NavigatorDemo', + 'NetworkDemo', 'ScrollerDemo', 'SliderDemo', 'Snake', 'StorageDemo'].map(e => + label(e).apply({ + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly().w(LayoutSpec.AT_MOST), + onClick: () => { + navigator(context).push(`assets://demo/${e}.js`, `${e}.js`) + }, + } as IText) + ), + label('POP').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + navigator(context).pop() + }, + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(root) + } + +} \ No newline at end of file diff --git a/src/NetworkDemo.ts b/src/NetworkDemo.ts new file mode 100644 index 00000000..851b5704 --- /dev/null +++ b/src/NetworkDemo.ts @@ -0,0 +1,34 @@ +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, modal, IText, network } from "doric"; +import { title, label, colors } from "./utils"; + +@Entry +class NetworkDemo extends Panel { + build(rootView: Group): void { + scroller(vlayout([ + title("Network Demo"), + label('Click me').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + network(context).get('https://m.baidu.com').then( + e => { + modal(context).alert(JSON.stringify(e)) + } + ).catch(e => { + modal(context).toast('Catched:' + JSON.stringify(e)) + }) + } + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/src/PopoverDemo.ts b/src/PopoverDemo.ts new file mode 100644 index 00000000..fd0e4f99 --- /dev/null +++ b/src/PopoverDemo.ts @@ -0,0 +1,44 @@ +import { Group, Panel, popover, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, modal, IText, network } from "doric"; +import { title, label, colors } from "./utils"; + +@Entry +class PopoverDemo extends Panel { + build(rootView: Group): void { + scroller(vlayout([ + title("Popover Demo"), + label('Popover').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + popover(context).show(text({ + width: 200, + height: 50, + backgroundColor: colors[0], + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly().a(Gravity.Center), + text: "This is PopOver Window", + }).also(v => { + let idx = 0 + v.onClick = () => { + v.backgroundColor = colors[(++idx) % colors.length] + } + modal(context).toast('Dismissed after 3 seconds') + setTimeout(() => { + popover(context).dismiss() + }, 3000) + })) + } + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(rootView) + } +} \ No newline at end of file diff --git a/src/RefreshableDemo.ts b/src/RefreshableDemo.ts new file mode 100644 index 00000000..b91c7e02 --- /dev/null +++ b/src/RefreshableDemo.ts @@ -0,0 +1,95 @@ +import { refreshable, Group, Panel, pullable, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, scroller, layoutConfig, image, IView, IVLayout, ScaleType, modal, IText, network, navigator, stack, Image } from "doric"; +import { title, label, colors, icon_refresh } from "./utils"; + +@Entry +class RefreshableDemo extends Panel { + build(rootView: Group): void { + let refreshImage: Image + let refreshView = refreshable({ + layoutConfig: layoutConfig().atmost(), + onRefresh: () => { + log('onRefresh') + setTimeout(() => { + refreshView.setRefreshing(context, false) + }, 5000) + }, + header: pullable(context, + stack([ + image({ + layoutConfig: layoutConfig().exactly().m({ top: 50, bottom: 10, }), + width: 30, + height: 30, + imageBase64: icon_refresh, + }).also(v => { + refreshImage = v + }), + ]), + { + startAnimation: () => { + log('startAnimation') + }, + stopAnimation: () => { + log('stopAnimation') + }, + setPullingDistance: (distance: number) => { + refreshImage.rotation = distance / 30 + }, + }), + content: (vlayout([ + title("Refreshable Demo"), + label('start Refresh').apply({ + width: 300, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + refreshView.setRefreshing(context, true) + } + } as IText), + label('stop Refresh').apply({ + width: 300, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + refreshView.setRefreshing(context, false) + } + } as IText), + + label('Enable Refresh').apply({ + width: 300, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + refreshView.setRefreshable(context, true) + } + } as IText), + + label('Disable Refresh').apply({ + width: 300, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + refreshView.setRefreshable(context, false) + } + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().centerX(), + space: 10, + } as IVLayout)) + }).apply({ + backgroundColor: Color.YELLOW + }).in(rootView) + } +} \ No newline at end of file diff --git a/src/ScrollerDemo.ts b/src/ScrollerDemo.ts new file mode 100644 index 00000000..9870d3d1 --- /dev/null +++ b/src/ScrollerDemo.ts @@ -0,0 +1,34 @@ +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, scroller, layoutConfig } from "doric"; +import { label } from "./utils"; + +@Entry +class ScrollerPanel extends Panel { + build(rootView: Group): void { + scroller( + vlayout([ + scroller( + vlayout(new Array(100).fill(1).map(e => label('Scroll Content'))) + ).apply({ + layoutConfig: layoutConfig().exactly(), + width: 300, + height: 500, + backgroundColor: Color.RED, + }), + scroller( + vlayout(new Array(100).fill(1).map(e => label('Scroll Content'))) + ).apply({ + layoutConfig: layoutConfig().exactly(), + width: 300, + height: 500, + backgroundColor: Color.BLUE, + }) + ]) + ) + .apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY), + height: 500, + backgroundColor: Color.YELLOW, + }) + .in(rootView) + } +} \ No newline at end of file diff --git a/src/SliderDemo.ts b/src/SliderDemo.ts new file mode 100644 index 00000000..6ab55c38 --- /dev/null +++ b/src/SliderDemo.ts @@ -0,0 +1,58 @@ +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, slider, slideItem, image, layoutConfig, ScaleType } from "doric"; +import { colors } from "./utils"; + +const imageUrls = [ + 'http://b.hiphotos.baidu.com/image/pic/item/908fa0ec08fa513db777cf78376d55fbb3fbd9b3.jpg', + 'http://f.hiphotos.baidu.com/image/pic/item/0e2442a7d933c8956c0e8eeadb1373f08202002a.jpg', + 'http://f.hiphotos.baidu.com/image/pic/item/b151f8198618367aa7f3cc7424738bd4b31ce525.jpg', + 'http://b.hiphotos.baidu.com/image/pic/item/0eb30f2442a7d9337119f7dba74bd11372f001e0.jpg', + 'http://a.hiphotos.baidu.com/image/h%3D300/sign=b38f3fc35b0fd9f9bf175369152cd42b/9a504fc2d5628535bdaac29e9aef76c6a6ef63c2.jpg', + 'http://h.hiphotos.baidu.com/image/pic/item/810a19d8bc3eb1354c94a704ac1ea8d3fd1f4439.jpg', + 'http://calonye.com/wp-content/uploads/2015/08/0-wx_fmtgiftpwebpwxfrom5wx_lazy1-9.gif', + 'http://hbimg.b0.upaiyun.com/ca29ea125b7f2d580f573e48eb594b1ef509757f34a08-m0hK45_fw658', + 'https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png', +] +@Entry +class SliderPanel extends Panel { + build(rootView: Group): void { + rootView.addChild(vlayout([ + text({ + text: "Gallery", + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.EXACTLY, + }, + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[1], + textAlignment: gravity().center(), + height: 50, + }), + slider({ + itemCount: 100, + renderPage: (idx) => { + return slideItem(image({ + imageUrl: imageUrls[idx % imageUrls.length], + scaleType: ScaleType.ScaleAspectFit, + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST).h(LayoutSpec.AT_MOST).a(gravity().center()), + })).also(it => { + let start = idx + it.onClick = () => { + it.backgroundColor = (colors[++start % colors.length]) + } + }) + }, + layoutConfig: { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.WRAP_CONTENT, + weight: 1, + }, + }), + ]).also(it => { + it.layoutConfig = { + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.AT_MOST, + } + })) + } +} \ No newline at end of file diff --git a/src/Snake.ts b/src/Snake.ts new file mode 100644 index 00000000..05bcba33 --- /dev/null +++ b/src/Snake.ts @@ -0,0 +1,369 @@ +import { text, loge, log, ViewHolder, Stack, ViewModel, Gravity, Text, Color, HLayout, VLayout, Group, VMPanel, LayoutSpec, vlayout, hlayout, takeNonNull, stack } from "doric"; + +type SnakeNode = { + x: number + y: number + prev?: SnakeNode + next?: SnakeNode +} + + +enum Direction { + left = 0, + right = 1, + up = 2, + down = 3, +} + +enum State { + idel, + run, + fail, +} + +class SnakeModel { + state = State.idel + direction = Direction.right + + width: number + height: number + + constructor(w: number, h: number) { + this.width = w + this.height = h + } + food = { x: -1, y: -1 } + + head: SnakeNode = { + x: 0, + y: 0, + } + + refreshFood() { + this.food.x = Math.floor(Math.random() * (this.width - 1)) + this.food.y = Math.floor(Math.random() * (this.height - 1)) + } + + get tail() { + let node = this.head + while (node.next !== undefined) { + node = node.next + } + return node + } + get score() { + let node = this.head + let n = 0 + while (node.next !== undefined) { + n++ + node = node.next + } + return n + } + + forward(node: SnakeNode) { + switch (this.direction) { + case Direction.left: + node.x -= 1 + break; + case Direction.right: + node.x += 1 + break; + case Direction.up: + node.y -= 1 + break; + case Direction.down: + node.y += 1 + break; + } + } + + + step() { + if (this.state !== State.run) { + return + } + let tail = this.tail + while (tail.prev != undefined) { + tail.x = tail.prev.x + tail.y = tail.prev.y + tail = tail.prev + } + this.forward(this.head) + if (this.head.x < 0 || this.head.x >= this.width + || this.head.y < 0 || this.head.y >= this.height) { + //If out of bound + loge('out of bound') + this.state = State.fail + } else if (this.head.x == this.food.x && this.head.y == this.food.y) { + //If eat food + + let head: SnakeNode = { x: this.food.x, y: this.food.y } + log('eat food', head) + this.forward(head) + this.head.prev = head + head.next = this.head + this.head = head + this.refreshFood() + } + if (this.crashAtSelf()) { + //If crash at self + loge('crash at self') + this.state = State.fail + } + } + + crashAtSelf() { + let cur = this.head.next + while (cur !== undefined) { + if (cur.x == this.head.x && cur.y == this.head.y) { + return true + } + cur = cur.next + } + return false + } + + reset() { + this.direction = Direction.right + this.state = State.run + this.head.x = 0 + this.head.y = 0 + this.head.next = undefined + this.refreshFood() + } +} + +class SnakeView extends ViewHolder { + + panel!: Stack + start?: Text + up?: Text + down?: Text + left?: Text + right?: Text + + build(root: Group): void { + root.backgroundColor = Color.parse('#000000') + vlayout([ + text({ + text: "Snake", + textSize: 20, + textColor: Color.parse("#ffffff"), + layoutConfig: { + alignment: new Gravity().centerX(), + margin: { + top: 20 + }, + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + }, + }), + (new Stack).also(panel => { + panel.backgroundColor = Color.parse('#00ff00') + this.panel = panel + }), + hlayout([ + text({ + text: "Start", + textSize: 30, + textColor: Color.parse("#ffffff"), + layoutConfig: { + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + }, + }).also(it => this.start = it), + ]).also(it => { + it.layoutConfig = { + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + } + }), + + vlayout([ + hlayout([ + text({ + width: 50, + height: 50, + text: "↑", + textSize: 30, + textAlignment: new Gravity().center(), + backgroundColor: Color.parse('#ffff00'), + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + }).also(it => this.up = it) + ]).also(it => { + it.layoutConfig = { + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + } + }), + hlayout([ + text({ + width: 50, + height: 50, + text: "←", + textSize: 30, + textAlignment: new Gravity().center(), + backgroundColor: Color.parse('#ffff00'), + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + }).also(it => this.left = it), + text({ + width: 50, + height: 50, + text: "↓", + textSize: 30, + textAlignment: new Gravity().center(), + backgroundColor: Color.parse('#ffff00'), + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + }).also(it => this.down = it), + text({ + width: 50, + height: 50, + text: "→", + textSize: 30, + textAlignment: new Gravity().center(), + backgroundColor: Color.parse('#ffff00'), + layoutConfig: { + widthSpec: LayoutSpec.EXACTLY, + heightSpec: LayoutSpec.EXACTLY, + }, + }).also(it => this.right = it), + ]).also(it => { + it.layoutConfig = { + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + } + it.space = 10 + }), + ]).also(controlArea => { + controlArea.gravity = new Gravity().centerX() + controlArea.space = 10 + controlArea.layoutConfig = { + alignment: new Gravity().centerX(), + widthSpec: LayoutSpec.WRAP_CONTENT, + heightSpec: LayoutSpec.WRAP_CONTENT, + } + }), + ]).also(it => { + it.space = 20 + it.layoutConfig = { + alignment: new Gravity().centerX().top(), + widthSpec: LayoutSpec.AT_MOST, + heightSpec: LayoutSpec.AT_MOST, + } + it.gravity = new Gravity().centerX() + }).in(root) + } + + bind(state: SnakeModel): void { + log('build', state) + this.panel.width = state.width * 10 + this.panel.height = state.height * 10 + let node: SnakeNode | undefined = state.head + let nodes: SnakeNode[] = [] + while (node != undefined) { + nodes.push(node) + node = node.next + } + nodes.push(state.food) + nodes.forEach((e, index) => { + + let item = this.panel.children[index] + if (item === undefined) { + item = new Stack + item.width = item.height = 10 + item.corners = 5 + item.shadow = { + color: Color.GRAY, + opacity: 1, + radius: 3, + offsetX: 3, + offsetY: 3, + } + this.panel.addChild(item) + } + if (index === nodes.length - 1) { + item.backgroundColor = Color.parse('#ffff00') + } else { + item.backgroundColor = Color.parse('#ff0000') + } + item.x = e.x * 10 + item.y = e.y * 10 + }) + + if (nodes.length < this.panel.children.length) { + this.panel.children.length = nodes.length + } + } +} + +class SnakeVM extends ViewModel{ + timerId?: any + + start = () => { + if (this.timerId !== undefined) { + clearInterval(this.timerId) + } + this.updateState(it => it.reset()) + this.timerId = setInterval(() => { + this.updateState(it => it.step()) + if (this.getState().state === State.fail) { + loge('Game Over') + this.stop() + } + }, 500) + } + + stop = () => { + if (this.timerId !== undefined) { + clearInterval(this.timerId) + this.timerId = undefined + } + } + + left = () => { + this.updateState(it => it.direction = Direction.left) + } + + right = () => { + this.updateState(it => it.direction = Direction.right) + } + + up = () => { + this.updateState(it => it.direction = Direction.up) + } + + down = () => { + this.updateState(it => it.direction = Direction.down) + } + + onAttached(state: SnakeModel, v: SnakeView): void { + takeNonNull(v.start)(it => it.onClick = this.start) + takeNonNull(v.left)(it => it.onClick = this.left) + takeNonNull(v.right)(it => it.onClick = this.right) + takeNonNull(v.up)(it => it.onClick = this.up) + takeNonNull(v.down)(it => it.onClick = this.down) + } + +} +@Entry +class SnakePanel extends VMPanel{ + getViewModelClass() { + return SnakeVM + } + getState(): SnakeModel { + return new SnakeModel(35, 35) + } + getViewHolderClass() { + return SnakeView + } +} \ No newline at end of file diff --git a/src/StorageDemo.ts b/src/StorageDemo.ts new file mode 100644 index 00000000..f13db93b --- /dev/null +++ b/src/StorageDemo.ts @@ -0,0 +1,93 @@ +import { storage, Panel, scroller, vlayout, text, layoutConfig, LayoutSpec, Color, gravity, IVLayout, Group, IText, modal, Text, log, loge } from "doric"; +import { colors, label } from "./utils"; +const storedKey = 'StoredKey' +const zone = 'StorageDemo' +@Entry +class StorageDemo extends Panel { + stored!: Text + + update() { + storage(context).getItem(storedKey, zone).then(e => { + this.stored.text = e || "" + log('Called in then') + }) + } + + build(root: Group) { + scroller(vlayout([ + text({ + text: "Storage Demo", + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[1], + textAlignment: gravity().center(), + height: 50, + }), + label('Stored'), + text({ + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 20, + textColor: Color.WHITE, + backgroundColor: colors[3], + textAlignment: gravity().center(), + height: 50, + }).also(it => this.stored = it), + label('store a value').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + storage(context).getItem(storedKey, zone).then(e => { + modal(context).prompt({ + text: e, + title: "Please input text to store", + defaultText: "Default Value", + }).then(text => { + storage(context).setItem(storedKey, text, zone).then(() => { + this.update() + }) + }) + }) + }, + } as IText), + label('remove value').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + storage(context).remove(storedKey, zone).then(e => { + this.update() + }) + }, + } as IText), + label('clear values').apply({ + width: 200, + height: 50, + backgroundColor: colors[0], + textSize: 30, + textColor: Color.WHITE, + layoutConfig: layoutConfig().exactly(), + onClick: () => { + storage(context).clear(zone).then(e => { + this.update() + }) + }, + } as IText), + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + gravity: gravity().center(), + space: 10, + } as IVLayout)).apply({ + layoutConfig: layoutConfig().atmost(), + }).in(root) + this.update() + } + +} \ No newline at end of file diff --git a/src/image_base64.ts b/src/image_base64.ts new file mode 100644 index 00000000..9eb105a6 --- /dev/null +++ b/src/image_base64.ts @@ -0,0 +1,2 @@ +export const img_base64 = + 'data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEASABIAAD/4Qm8aHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49Iu+7vyIgaWQ9Ilc1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCI/PiA8eDp4bXBtZXRhIHhtbG5zOng9ImFkb2JlOm5zOm1ldGEvIiB4OnhtcHRrPSJYTVAgQ29yZSA0LjQuMC1FeGl2MiI+IDxyZGY6UkRGIHhtbG5zOnJkZj0iaHR0cDovL3d3dy53My5vcmcvMTk5OS8wMi8yMi1yZGYtc3ludGF4LW5zIyI+IDxyZGY6RGVzY3JpcHRpb24gcmRmOmFib3V0PSIiIHhtbG5zOmRjPSJodHRwOi8vcHVybC5vcmcvZGMvZWxlbWVudHMvMS4xLyI+IDxkYzpjcmVhdG9yPiA8cmRmOlNlcT4gPHJkZjpsaT5WZWN0b3JTdG9jay5jb20vNzMxNTkwPC9yZGY6bGk+IDwvcmRmOlNlcT4gPC9kYzpjcmVhdG9yPiA8L3JkZjpEZXNjcmlwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICA8P3hwYWNrZXQgZW5kPSJ3Ij8+/9sAQwADAgIDAgIDAwMDBAMDBAUIBQUEBAUKBwcGCAwKDAwLCgsLDQ4SEA0OEQ4LCxAWEBETFBUVFQwPFxgWFBgSFBUU/9sAQwEDBAQFBAUJBQUJFA0LDRQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgDDAPoAwERAAIRAQMRAf/EAB0AAQABBAMBAAAAAAAAAAAAAAAHBAUGCAECAwn/xAB8EAAABQICAwQPDQ8NDAkDAgcAAQIDBAUGBxEIEiETFDFRFRgZIkFTYXGBkZKVwdHSCRYXMlJWV1hncpbC0yMzQlVidoKToaKmsbK15Dc4c3R1lJejpKWztNQkJSYnNDZDZoO2w/A1REVGVGRlhIUoOUhjxkd3huHE4/H/xAAYAQEBAQEBAAAAAAAAAAAAAAAAAQIDBP/EACoRAQADAAICAwADAAIABwAAAAABESECEhRhAzFBEyJRMnEzQkOBocHw/9oADAMBAAIRAxEAPwD6pgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOMy4wHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODMi6ICz3NedBsqnnPuCtU+hQS4ZNTlNx2y+yWZEA1sv3zTXASypO8oV0SLzqhmaUwbWhOTFLPiS5zrZ9hZglsKLTF0g8WdVOFOjlUKdDd+d1m+5W82jI+BW5Zt5/YrULRa3SbK0x6hUo0yqY8WBadxLI1Q7SjwW1sPF9ElRraNasuMiX1yChcU6QWlvhAaUX7gbTMQ6c0XP1OxZxpdUXqtxPXUZ9TUSBa+2n5qVg7Pnopd5NXHhlWeBcS6KS42SVcWu3rZF1VEkQbKWHjBY+KMRMi0btotytGnWPkXPbfUkvqkpMzT2SIFZeSiPo7QHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgzIuEwFtr1zUi1aeufWqnDpEFHppM+QhhpPXUsyIBrjiH5pRgDh88qKV6puiokrUTCtmOuepZ8RLSRN5/ZgI/5d3GzFUiRhFo4V1cRxXzKtXq+UCPl0D1OdIy6zhi0lsfuyz9Jq4YhS8W9Im0sE6K6ZmcC20obey9Sl5w0Kz964oKRjtraIWCFXqDVSfpOKGkXWlHnySqJvtQXFfth447Rp6zi+yAnyh2jPwko6JFHtHCrAGi7UnPqbqZksvfbnuDet1319kFUJV2j3oZbteuJmMK1KNC4tmw10qlK6m+GEsNmn30lQCsiYVrKmPIh6OVhN0xeZuxK9WGXanK4lKcTGeQSi+qeM/qi4QoUKYtDslJf3DivguTSdY1wHF1qjpP3qTmMIR10N9gBdY79WxVpiocSvYVY+UpKDN2DVGEw5iS4lam+GyV12W+wFiFL60PMFqhK37XsGb5wiqqSNZVmynFTorR+qLeintUuqplHYBHhZmGGK9Hc3PAvS3h3k2ynJNt3sSJTySL6BWtruo+1oAZmWk3pT4Rc5iPo/s3lAaTk5VrCmm4eRfRbh80V2DJALbJbL81FwRr01NNuObWcO6wWxcK6qW4waFdEjWjXSXXVqiFtlbKxOtHEeEUy1bmpFyRjSSt1pU5uQRF1dRR5dkFZMSiPo7QHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4MyItoCiq9bp9AguTanNjU6G0Wa5Et5LTaS6qlGREA14xI80WwBw1W4xJv6HXZ6FapQrdbXUFqPiJTZG2R9dZAlozVp54p4pZt4OaOdz1eM4rJqtXWsqdFy9VlwKLrOkLRazXPbelddcE52JmN9lYEUBw81R6GlG7JLiJ50yyP3rxgMQoOiTgpctQbqVXm4paSlaNe2WrfG8FK/bCzaZy/wBuoET7bGHkjCilb8tvDXDHA6ktnkurV+SiXMQXGomSbTn15KgVTrumlXetSZGJV/4rvkvVXAw7pyoFOV1N8x0pIi9/LMBebUw/rFIl77s7B60LGla+ZVu7Z3JKqH1VJYJxSj99KIKRmi8MLsuPM7qxQr0ls1axwbZZaosfrEtG6SMv9sQUWuFvYEWBbE8qhEtWnv1Uj1uSlTSqfNM+PfEg3HPvhRnh5qIiUZqIuDM88hQBAudPNJmk+MjyMBid4YTWZiA4Ttx2tSaxJL0kuTEQchHVS8RE4k+qSiEpWPJwYm0DNVn4g3ZbREWSIkmaVYhl1NzmE4tJdRDiQoY9eNk3nXGtS7rIw8xcitJ1UOuMqpU9JcaSeS+3rdZ1vsCUWxLdaHY6TNMvFfBbck5EmUldao6T98rfjCEdZTfYBV0dh1XFqkLbUvCbSDoqEc+h1KYcsi4jy303rdhrsAILvXQ8wRVNVUKlhpiLgdWEFr8mLWU5MhtH6olxVSEoLrob7ACps3DvHGjpUrBHSrouJkJlOyhXgSJLySL6FSyNxxJ9DaSOwFDLOW10k8JNZGKGjs/X4TRfNKxYUzfKci4Vbjm4fbUkKGXWL5p7gRdkveFWr0+xasWRLg3VT3IqkK6JG4nWbLsqIQtspad+21fsAp1tV+mXBCMiPfFLmNyUbeqgzBV+JRH0QHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODMi4QFNUKlFpUR2VNksxIrRay333CbQkuM1GZEQCAMSvNA8BMLjeaqWIlMqU1vZvOha1QcNXqc2SUkj98ogEUL80HvrE7XawY0e7wuppZ5NVevkVNh++z55Jl/tEglrXcNI0vr3gOT75xSsTAO3V7VppiUOyEJ4t2cMyI+qTpClsFpmilg5eFQKfc934oaS9ZSvnlQd8OwDVxE/zrSS/9xkCJ7s/Cb0L6cqZZ+DmHeD9PYy1q1dcxEqYhPqlEwRln15QWtOZF5U66nnWZeLl4YjyUKyVS8LaUcaGf1JyY6VqSXvpZALjbmHs6JOVOtTBS3bbm6xKTX7/qhVCpl1TS1vhwz6ipCQoZ25hze1y63nnxRqiGVGRnAtKEzSWetuqt2kdknEi0lqmjYAYf0aoFUfOxFqtWI9YqpXluVSXnxk9JU4ouwZAJBy5wkfQJ2EnoF1i6AqGZEA6SZLUOM5JkOIjxmy1lvPKJCElxmo9hAI4m6RdgtzHIVLrS7sqKNhwrUiPVd0j4lHHStCPslJEV4nfuItx7Lfw25DsqTmmbedWai5dXe0Yn3D6yjQfWAPOhivNUmW/iRRafLTkaYFPtZLkHqks3XzeX10rb6wAVyYr23kVUs6h3hHI9sm16qcOQZce9phEjPqFIMByWkXadMUhu6Wq1YT6j1crqpT0RjPqSSJcc+w6AkGh1+mXRAROo1Sh1iEv0smnyESGj+yQZl90BXEZHwHmKjlOaDzSZpPjSeQDDbtwase+pO+65alKnz+FNQ3sTUtB8aX29VxJ9ZQirIWENZt/WVaOJN00NOzVhVV5FbiZcWUojeIuol4goti952LdVeUpd44bWBimlGRInwTOlVJBcaEyCcSSveyECKxlVTotk6xt3JingypGSUMXHHXWKQk/2Z0pTSU+9fb7AC5VOgVLFyjuLn0XCfSCoiUkk5EZSYcvsa2+W9brON9gBAt36H2B8Oe5UnLSxN0fq0jnuStEN6RCaVx7tHVJbSnrqb7AIvNoWNpFUNhcjBvSZtnGGlNZGVLulKH3iIvoVOoNxZH11o7AKyQ9M3H3CfWTixo41SXDaP5pWrFk79ZIuircufyL3zhBRbOLA80ywDvmQUOTdjtn1PMkqg3RDXCUg+JTnPNl3YhbZK27vod409M+g1iBW4KvSyabKRIbP7JBmQKuxGR9EByAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4MyIB5SZjMOO4++6hlltOstxxRJSkuMzPYQCCcStO7AnCndm61iRR3pbZbYdJcOoPZ+pNLBK1T98ZAiHHPNGrhxHUtjBjAW9b6JRZN1SpNFT4OfqtfJZGXXUkWi1vrLGmXiFAdnXNedhYBW6pPzRcYkypLaeq4s1oI+qTiQotH0fRcwoviecm98UMS9JKsIUWvGoZSJEElcW6N6zSC676SBE62NgjDw4hql2NgPY+GkZhJKOuXtObkS0J9UaWSdPupKQVVzb6hXFJdiVDGmvXpKRw0bCajarRfUKfZS+4jrqkI7ACqomHjiqgc+28DqbCnnkpFwYm1kps9J+qJCTlPZ9Q3G+wCM/XYN/3IRlceJ0mBHUkiOBZtMapzZdTd3jfe7KTQfWCi3tTtHqwIc5E+Zbzdx1RORlUbmkO1eQR8ZLkqc1T96RC0JEbbS0yhlCSQygiJLaSySkuIiLYQqOdhAOHHEtMqdWZIaQRmpxR5JSXGZnsIQR1U9IfD6BOVT4txNXDVE5kdOtph2rSSPiNEZLmqfvjIFU3oj35cWRW3hjKgsrLnZ15VNmmo6+4M7u8fWUlB9YAKyMSrjyOvYisUBhRc9Ds2kNtLLqb6lm8s+ulCD6wDvF0crEXJbl1ulyLyno2lLu2c9VlEfGSH1KbR9iggoSPChR6bDbiRGGokRstVEeOgm20lxElJERdoB7EREKgAAGXOmn6E+FPQPrl0QEe1zR/w9rtQOorteHTaqZ63JOiGumTM+Pdoym1mfXMxKVQlhfeVv6p2xihVVNJPMoN2wmawz1t1LcZBdc3VAOE3bilbhpKs2HTbojl6aVaNXJt4y496zCb7SXlAOzWkbZcN1ti45FRsWWs8tyu6mvU1GfET607gr7FwwEi0qqwq9Abm0yZHqUJws0SYbyXmlF1FpMyPtgKkjI+DaKjlJmjPVM058OqeQDBrnwPsK8Jxz6nalMXVM9YqnFa3pNSfGUhk0OF3QirYnCm5LezVaeJ1x05GtmUK4CbrcbLiNTxJkZdZ8KLYhd9g3BXJByLywnsjEZ4lFlV7eknS6okuNCZBZpP3sohKW1g88NHsxWTN94k4QOEokoh3xCVU6Wnqb4fS8gk+8lJAVtwWXNxapCpNcsnCzHujHzqajSHkw5ii407pu6M+tIQCUgK5tETBCiVB2pQ4mKOjjWkqz5IQzfXBQr9sMm+0Sf9sjsAMntS0tKG24ZzMKNIKz8cKG0ZGmFcSULeMvUm82a1Z++dSAvpacmMuFeaMX9HC4I0VtWTtas14qhGy6KtTniSXXdCltIeHXmkeAOIjqYyb4atqomrUVCuVhcBaD4jWstzz+zEGxtDuOlXPAbnUepRKrBc9JJgvofaV1lIMyMFXAjI+AwHIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA4zyAdHH22W1OLWSEJI1KWo8iIuMzAQpiVpr4IYTbqi4sSKG3KbI9aHAf37II+I22CWoj6+QCEX/NKpF/uqjYNYKXxiQ6ZZInuxd4wc+ge6ZL2e+1QS1FUJWmpibDcmVOqWHgJb5ozW8pSZstpPGpSjcQR9XNApaOFaM2G9+VBR4i434iaQ1Wb+eUq1yflQyV6n5gTrbZdd1BdYETbh9o+0WwWN8WDo72rZjbKNdNdv+oNOyUkX0Wo1vhZceSnW+wCrvUL+j1eUun1bHCXXJSU5cgMJKJuikH6hTraZTqeLPdG+wA7UvD5ufPTPomBxTJxpzTX8V62UiQlXq0tqOW8XWyb7ACQ02RiNcDSUV3EdFCiamqdPsqkNRCSXqd8STfX2UJR2ApLekTR2sMpbc2rUdy7aijgm3ZMeq7hHxpKQpSEfYJSQtCRY0ZqFFbjR20R4zZaqGWUkhtJcRJLYXaFR6bCAM+cNX0Kdpq6Bdc+gCo9rekBh9Q6gdOVdESp1Uj1eRlDSupy8+LcYyXFEfXIhEUJYn3ncGqVs4X1VDSsyKdd01mjs9fci3aQfWNpJgrhNo4o3HqnWb9ptrsHnrRLQpCVvEXFvqYbnbSykB2a0crKlutyLjjVC+ZaDz3a7qk9Uk58ZMLVuCfsWyASLS6VCocBuFTYkenQmyyRGhtJZaSXUQkiIu0AqiIi4CyFQ4AHVxxLLK3nFE2ygjNTizySki6JqPYQKjuo6Q1gRJy4EK4EXJVE5kdOtiO7V5BHxGmMler9kZCWPFN/YgXGnWt3DKRToykmZVC86o1TmyLj3Bgn3uwokH1hLKR7UsXX4NaaiVXSHwxoNaIzTyGj09t6IhXqH3XJZOZn0D1mvemAzyn3liXBhMS5Vm0W96Y4WsmpWTW0kpxPqijy9RPYS+oLKejekVZsFxtm5XanYslZ6pN3bTHqe3nxFIUk2FfYuGLYkOk1eDX4Dc6lzY1ShOFmiTCeS+0ouotBmX3RRVEZGXDmCOQHVbaXWlNLIltKIyU2os0qLiMj2GCo6qmjxh9UJ6qhGtxq36orMzqNtvO0mSZ8ZrjKb1j99mIKYsOL7t3VO28Tpc1lBc7BvKms1JHW3dncHy66lLPrgOCvfEu3MiruHUevsJLnplm1dDqz6u9ZZMqLrJcX2QHpG0jbERJbiVupyLMnr2FFu6C9SVGfES3kpaX9iswEjwZsepw25cN9qXEcLWRIjrJxtRcZKSZkfbAexGR9UVAthGRGZEfCRHsMBgNfwGsC46gdRkWtBiVYz1uSlJJVOm58e7xzbc7ZiUqhbwyu+3MjtXFGttNJVmUG6YzVZj9bdD3KRl13jCi2FXTh9VqnMKZeGDdqXnL19Y67ZlQ5G1QuqlL+5LSfvZJiUqzt3ZS7RdQiNihfeFj6l5Ip+JNNVNp6epvmQk8y97LAe11YbPYrUspl0YXYZ42Ut08kVe3JSIkxZcaSeJSc+tKILKQFW9EzBW1qguo0Or4paNNa19kle+EwEq6shJuMmX/uCBGZ21b2lnaEBM/DnGeyMebfbPNDNZShL6k8W7NGeZ++eBV4Tp84mYXareMmjrdVDjoPJ2s2uoqjEy9V6lJf7QwotJ2G3miOAOJqmmIeIEGiz1nqnCuFCqetKuLWdIkGfWUYithaVWYNchNTKdMjz4bpZokRXUutqLqKSZkYCsIyPgPMByAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA6qcSlJmZ5EW0z6ACH8SdL/BnCTdE3RiNQYMlvPWhsSilSSMuhuLOusuyQCB5XmnFOvSQqHg9hLfOKMraSZMeCcSFn0DNwyWoi98lIJaik17TYxVjqkb1sbAqhmkzXJnOlOmtJ4zM90QRl1SQLRaNpejlZd91A2cUtIq+scqqj55QLNJ6TGI+ik24xPJQXXNvsAiYcONGy17Jbbew+0bKJRDbRrIruI1QaN5OX0W5p306XWM2+wCslqV/pflFS63jiwclKdU7cwoohSJDZ+oNRFLdTxZkTXYAeUGwodamNTaZglULjm5c7XMW63rmR+rSy6qU6nrE032AEixrNxLrEdliqX7AtWAlGoVOsmittmhPqd8Szd7aWkdgKS3dnR0siQ+1Jr8GZe0xvaUi7qg9VCI+NLTqjZR9i2RCiRKfT4tJhNw4MZmDDbLVRHitpabSXESUkRF2gHuREXAKjks1Z6pGoi4cizyBWBXJjxh/as86fNuunu1Uj1eRdOWqfNM+Le8clufeiC2eixdFfyK1sMK9JbUeSZ1zvNUSNlx6izXIy/wBiQDgrbxXuTI6peVEtCOZ7Y1r0o5kgi4t8zDNOfVJggHJaOlpVJaHbpcrN+vpPWzuqqvTGc+pGI0xy7DQCQaHQabbFPRBo1OiUiCj0sanx0R2i+xQRF9wBXERFwFkKjnMBwZ5IUv6BO01dAuufQAR9WNIDD+j1A6cm5otXqxHqnTKAhyqS8+I2YyXFEfXIhFUzeIt73Jq+djC+ptsqzIp93TmaSyXV3JG7SOwptIllI6unFRdMnJg3fjnbdtzjUaFW/h9TCqFTI/U6zm+HDPoZpjo6gKsqaRS7meZfg4OXhiNJSeaativVziQz4lJjyVrUnrJipEGcwKJixOgtQjum2MOaU3sRTrJoe+XW0+pJ+Vk2XXKOA83NHe1awpLl2ya7iC8R63+FlXelsZ9SKk0Ry6xNAPGo3pbNh1B214FqQI9uRVNsVA4cdlmOwayI8twSjVcJJKSa88siVszyMFVcvRzsFM12bR6M7Z1TWZmqdaE56jumfGZR1JQv7JCiBHqi18ULabNFAxORX4ZJNJU6+qM1MSZcW+YpsOdlSV9kFYNULZKBPOdcOAqY84iM1XBhJXCYkqV6tTRKiPnx5fNOyCPWk4qUqmz2qfScdZdvVAi2UDF2ibkvM+BCXXUxXlcWZOOdkUShGvTEqjxmn6rYEG6YCka5VGyK027rp9VveWTR9hLq+pmFpTuxpF2Ow+1Gr1QlWVNc2FGu6A9Ssz4kuPJJpf2KzIWxIsCfGqsJuZCkMzYbhayJEZwnW1FxkpJmR9sB7EeYo5MiMEeciO1LjOR320Px3C1VsupJaFFxGk9hgI4m6OlguzHJtLoirTqS9pzrUlvUh0z41b3UhK/skqEV5HYOIlubbfxK5LspTzsK86S1Lz6m+YxsOF11Es+uAeiBiFbp5XDhouqspTz02zKq1NI+rveSTDpdZOufXAe0HSKsB+aiDUq751qkvYUC6ortIeM+IikpQlR+9UYCR2H25UdEhlaXo6y1kPNqJSFFxkothkKjtsMgAyI0KQe1CiyUg/Sn1y6ICPato/Yf1WoHUW7aj0aqmZmdTt9xylSzPjN2KptRn77MRVM3h3fNtavnYxRqLzCM8oF3wGaqyfU3ZvcH+ypxZ9cKLYHcGHst+emddWCVBr04jNa7gw7qpQKkZ8eq5vZ0j6iX19kSlUEa9afa77UeHjDdeHslZ7KVirSDfi+9KRIS2tXXTKUA6XnhA3idARMvLBbD7FqC/maa3aM1uNMWn1SUvkn7kowsQLP0VcHrMqG/bTvrE/RprKlnqlUt8MwNbiN5WbSi60gyBGe0GmaYdiQGp9l4k2Hj7bqNrZVBKGJC08ROtmlJn1TdMKVckeaG3nhmaGsZ9H28rQbTscq1ESVRhe+1udIi6y1AWlrDXT9wFxTNlqlYjUuDMc2bzralU90lep+bElKj96oxFT7CqEapRW5MSQ1KjOFrIeZWS0KLjJRbDAVBGR8ADkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAddcuv1gEWYkaU+EmEZOJuzEKgUh9GZKiHMS7JLL/APRb1l/egNfqh5qDbFzzFQMJsOL3xXn6xpSumU1UeKZ9VxRKWkuqaCBLULl56a+LbRuU62LLwSox5qOXWpG/praeMyLXSRl9U2kURtVNH2hXvUd6YvaUF34sVTM91tixicea1uik2IyXtXspR2ARKWGui7Y9oEw5h/ozxG3E7UVzEme2hRH6rcj3y6XWNtvsAtM0qt+Ow326RX8bKLQ3k5t+dnDCiplzW/qc1FJc7KWW+wApI1kU64pDEmHg3cV8SknztXxZrJtsZ9BSY76nlp6yYyAEi0+0MTZ8NiLJvCh2PTGy1U06yqKla0J9SUiVrI7KY6QpLeidHWz6gtt25k1S+5CD1te7Km9Paz4yjmZMJ+xaIWhIVHo8C3oDcGlQY1LhNlkiNBZSw0nrIQRF9wBVkRFwbBUcpI1mZJI1GXDqlmAwi68bbDsqYcKsXZS49SzyKmsv75mKPiKO0S3TP7ERVmPGCu17MrTw0uWqIM8kzq6TdDimXH/dB7uZdZkwHB0TFu5TPf8Ac1uWTGM/nFv05dTlEXFviUaGyP8A2BgCtHi3KwZLu2pXDfrmtrGi46s65GM/2q1ucfsbmYDPbctajWdAKFQKRAocMuCPTIrcZvuUERALmREQqOQAs1EZpI1EXCZFwAMCuDHiwLaqB06VdUCVVSPV5F0s1VCaZ8W4Rycc7aRFUCMTruuPIrVwurj7RqyKdc8hqix+vqK3SRl/sSEspgd4YnT6HL3pemNNn2PL19U6HZ8HklVT6iVPm4tR+9ikCscVBot2KQ5EwuxAxXdJesipYk1I6dTVFxlHkqSRF7yIIM3pVFxVcp6IEOrWZhZR0nmin2fRjnvtlxE8/ubJH1SjmAwrEqwaNTX6XT6+5dGLlw1Vat7U64q46UI8ss1qisbkwRZnwbmfAeZkRGYDBpbR2xIqlOq1MiWa1DkIdg0igspjRUKShBpWylCCS4olGXPmasjUeeRFmA2hsidPqtoUedVHWXqhKiofecjtmhCjWWsWSTyyPIyz2EWeeWzIFYbf2ItZpFzuUijphMlGjtPvPzWVPGs3NbVSlKVJyIiTtPMzzPIssgF3w/xF89cpdKqMZuBWW0bqSGVmpmS3mRGtoz2lkZkSkHtTmR5mR5gIclf3+arzque5Iy5yjPjJTi0J+9JPaBEveiNHomHVu1Z9tc2fUYbBR4baiSt902iNW09iUlkZqUfAXGZkRlYxTcWbiRW6fyRZpi4EqU1FXHiNOJca3RZISpLilHr5GosyNJZlnlkAmLVz2ZFnwANRrjr8+qP151yWdQutbyob8RpnXZkJbXqE2lhSDStoibMyJRZ5meaiNR5kZPbOHlvx71TQplpysK7jmtKfjT7DrD9OYk5ZmebTStyM+dV6ZCi2GRkWzMJMXbuKtBjuM0rESn3bAUjUOnX1Q0OGpPqd8wzaPsqaX2QVgkq3Y1HmOTKzgTUbemmXPV3CCuESjPorUy0qK8rjyNpzsgiuomKkJqemBQMeGY9QJJJTb2K9FKLKUr1CVmUR4z6vzTsiiTE3ziLQGkrruG5VuJqErkhZVXamJUXqtwkkwvsIUvshaU9IekRYSpbcKq1pdp1FeWUK64j1IdM+JJyEoQv7BSiFsSLHkNTIyJLDiH47hEpDzSiWhRcZKLYYqPQjzADIj4QHhPgRqrCchzY7U2I4WquPJbJ1tRcRpURkfaARzI0crFakOSqFTpVlTl7Tk2jPepRmfGbbKiaV9kgxFeZ2ViZbmsdDxDi3Cwki1Yd5UdC1n1N9RDZUXXU2vsgOfRJvm3syuTDGbKZQXPTrOqLNUb6+4O7g+XWShZ9cBVUnSFw+qc9NPeuRihVVRkRU242nKTKM+Im5KWzUfvcwEipWS2kuJMlNqLNK07UqLjI+AxUc7DAdHWkPsLYdSlxhZGlTSy1kKLiNJ7DEEdz9HiwJM1c+BQU2zU15mdQteS7SHzPjNUZSCV9kRhSvIrDxCtxOrbuJr1TjJSZFT70pTU9BlxbuwbDvZVrn1xKLR9WMPVM1Df8AcOB0F6eRGpdwYXVkok1R+qNBnEe7BLc7ILbwhX5EoElqFTsbKzaUpRbKJi3RecUfQQl55Md1fXJ9zsgKG+8C6fiLETKvvAKy8RI76TVydsae2xLWn1RJe3FXYTIWAgt3RfwssWeT9iYtYk6OFXcM9SHcG+I0I1cWu6SG3C6z6iASJSU6Z2HMFqdb91WFj7bpJ+ZuPasSU4nqOINCDPqmtYUWrmvNH6zh0tEfGfAm9rANJZLqUFjkhBz49fJGzrGoQtM2GmnRgXivuKKFiRRkS3C2Q6o6cB/P1JIfJGsfvcwVOkeUzKYQ8y4h1ladZLiFEpKi4yMthgPQjzAcgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADgBxrF1+sAjjEfSQwvwjQ55778oNCdRwxpM5ByD6zKTNZ9hIDXaseakWHWJy6ZhfZl54sVQlaqE0OlLbYM+qtZa5F1dzBLW9WJWmli+kzt7D208HKSs8ym3NL35MbTx6hZ5H1FNELQjmvYEovConCxp0sLivmoqUe62nYRKMjPoo3vGS6fU2tJBEg4a6KOHFqGy5YejS9U3yVztbxKmIYTn6vcnDfdL7QgFpIVXvWVbym6PcGMFp2OaD3Pzs4eUlMyekvUp3Tdln10xkhYoG7QpV0OtvMYVXniW+lfO1PFCqnEgn9UUaQozSXvYhAJDpNo4mOwGoLdftfDmktnzlOs6jb5dbTxE/J1Wi7EcKLe56PFsVYyXdcuu367raxpuequyI5n+1UGiOX2oWkZ9QLcpVqQEwaHTIVFhJ4I1OjIjtl9igiIEXAiIugKOU5qPJJGo+JJZgMOu/GGyLCf3vX7rpNMm/QwXJSVylnxJYRrOKPqEkxFY+eNFRrpGVo4dXVX0nlqTajHRRYZ9XXlml0y960oAVTsXrl1t81i1rFjKy+ZUqI7WZZFxbs/uLRH/sVEAL0faPWyM7vuC576NR5qZrNWW1EM/wBqxiZZMuopCgGb2tZVvWNDOLbdCplvxj4WqXDbjJPr6hFn2QF6y2mfRPoioACSNeeqRqy4dUswGD3RjdYdnTTg1S66Y3U89UqZGe31NUfEUdkluH3IirWnFe47hzTaWGNyVJGeRTa/udEjZceTxnIy6zAWUwu9sSK3bbqmb2xbsXDVzWLKk0JjkpU1EfQQqQfPH72KYlqxN5FBvHno1iYm4xqNWs3NvaYqk0lXV3CQphs0+9iqAZpRKNii1A3hRzsPCKjmeZQrYpSqnJR1nFkwwR9XclkIPWRgLTbizVelz3XfprPNces1hbEJR/tSITLOXUUlQDM7Tse3bCib2tmgUu3WOiilQm42fXNCSNXZzBV6y258J8YDkBHGMtspnwKfXotVj0Wt0dw3IcmU+hlDmeRm3rL2EZmRGWeZcJGWqo8g5wvxJpeKUNg5TMXk7TTN3c9UlEk/SKeZM8zTwmlREeaTPIzMjSZhl91XJGtKgSqrJQ4+hgkkllnLXdWpRJQhOezM1GRZnsLh6ACCb4u52uS2au/SCpM5hvcFutyyfjPs5mZIdPVSbSkmZmlzI0lrGSsknmQUbFaVFKFXoGsUqmPlKQhRaqucPJ1pRdDNGugy6pdQwHjaUhuXQKdIaVrNvJ3VKuMlLNRH90BR2tWFVukQZb69WLTYvI2NrHklCG1Gbq+prL4T4m0gK+37iRydj1Eqc5UigrJ2NENwmWydy5119ZkZkZEeaWkpNW0lL1edIBOVh3yi840xLkM6dPhLSiRH3QnE5KLNC0LyLNJkR8JEZGkyMgHpe1z0axYKrgqDTZy0NnGjmlKSfdz542krPgTs1lGZ6pERqPgAR9hKheId0LvmrVSDJlttG3ApsN9K96tHmWupJHmkslKy1izPWNSss0pSEzZABkR8ICkrFHgXFT1wKtBi1aCsslRZ7CJDRl1ULIy+4AjwtHSzqW4t61iq+H8lR5m5Z9Vfp7ZnxnHI1R1dY2jAe0mhYsUqI9Fi3tQb8pridVdOvihpbWtPqTkQ9VJ9dUdQIwR6h0635L0qpYI3HZEtXpqzhHWd2Z6q1MR1sOK6yoy+yKLtbuKaJM9UC1sdqRUZ6ckpt7EykFCqBn6nWSUV7Pqm052QsSOq/wC/rbSZ3JhjKnR0kRnPs2ps1Js+ruL24PdhKVn1wtKe9N0hMP5s9NPl3C3b1UVkRU65WHaRJM+IkSkt6x+9MxbEhocS6yl1BktpZEaXEnmlRcZHwGA7Z5ijgyI+EgRS1ekQbggOQapCjVOE4WS401lL7Si6qFkZfcAR25o5WZCdcftpqp2JKWee6WlU3qe3n1WEmbCvsmzEV1VamKdtmo6PfVKupgj52LdtIJl4y4t9QzQXZNhQDn0Urwt/WK6ML6uTSTyVOtOWzWWOvufzKQRdZpQCvoOP2H1wVAqc1dMKBVTPV5F1kl02ZnxbhJS2s+wRgJBPYklGRkk+BXQPrGKgZEfVAeUuIzPiORZTLcmK4Wqth9BLbUXEaTzI+0IqOZWjrYiZTkyjUl6z56+GXaU16krM+NSWFJbX9mhQDq5ZWJFCZW3RcRWbhhmjU5H3tR2pJKL1O+Ipsq7KkL7IlFo7qWH7FMnLnVjA5ymTiTmqvYTVvcHlK9WptCojyutqudkFKff7NMlJp1Ixxepco05ed/Fuibk4s/UE4tMR5XFnrO9kBZMQ9Hig34yp/EDRztq7Euo11V3D6oNNyFEf0Wo5vZw+PInHOyAhVvRpw9sOeRYbY74g6P1Wc+d0e6yfixDV0E5Pk0hwus4vsgiSINQ01sL4iJUKXYmPNAJJGh9lSYMx1PGlSdzQZ92Cq1jzS7zhvJi4yYM3zho8RESppRDmwc+iZOZIMy96ShC044a6aGCeLO5ItzEihPynCLVhzJG85BmfQJp4kKM+sRgqaEPIcQlaVEpCiIyUR5kZcZGA7ZgOQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHU1EXR7QDBMRMesOsJmXHLwvahW6pBZ7jPntoeV71vPXV2CMBrfcXmpeGL9QcpeHdBu3FWrkrVQzblIcJpR9VbhErLqkgwS1rVjFpk4waybRwlt3CmluHzs+8JpyJSE8e5FkZH1DaMUtH10YK1i55yoeOOl1VKvMcV80tKwi3NSj9RuEclLVxbWBUZfhzoj4V20tD1laONXuqWS8+TeI8lMRo1erNp81udXZGIQSjV7rqFktppFdxQsPC1pBklNuWVTUzahq8SCdzzP3sUFWw7Zo93KJbeHuIWLDhLJSJ2INQVTqYrq72kKbTl72IYIz+iWhiS3TygU+ZZmFtII80wLUpJznkFxE66TTJH/ALBQUtqxzR+odbzVd1ZuS+1KVrKar1WcKKZ/tSPuTGXUNsxaRnNs2jQ7Kg7zt6i06gxOkUuI3GQfXJBFn2QF1yIhUclzx5ERqPiLaYDFbxxUs7D4yTcl0UiiPKLNMeZMQl9fUS1ma1H1CSYisY9HB2uJytCw7sulJlmiY7BKkwj6u7TTaMy6qEKADYxgubPdJVp2FGUXpYzT1cmF9mvcGUn9gsuuALwEh10j8+F23XehKLno02qHChn1N7QyZQZdRet2QGYWjh7a9gMGzbNuUq321FkrkZCbYUv3ykkRq65mYDIcszMz2mfRMVAATms8kkaj4klmAw27sZLHsWTvWu3XSqfP4EwDkk5LWfElhvWcUfUJIirIWL9YuDWTaOG11VxOzVmVRhFEiGR9HOUaXjL3rKgspid8Yh3LbOsm9cTMPcKELyUiDEzqlSWXEhUhTaTV72OsSxhj8m3b0So2LcxWxr18lIkV95dGoyj6rbpxWVJ96y52QVl9u0XEqFCVDtyk4eYOUlzLOPRIC6rLLq6xFGYJXXS4XXEFXJwObuQlKvW9bvvfX+eRZlVOBBV1DiwiZQZdRZqBUUXHYMrDq/ZzeH9rnb8/cEt0R+3qYiMy4g0Et1DriU/NFEeZqU4Z7CTllltCY7CvuuVO66va90QIUeuQI7cw5FMeU4w80syItiueSraWw+gfbCQQAAAAHB8ADXyqlHvTFac1X6nyMiRn5bLbi1oQppqPqZMtGsjJC16xuqURaxpLIuhkFHW6bFo1t0O/LLqk5uKuSpKeSbSVuMrNK05nsIzSo0G2pCjMj1kmRlkAzWFTmaZh+49f13zatHrzLC0svJLOO6ad0Io25pNZqLnT4MiNGeREAj9yczEN3VqUes09syJc5ptTLrJKPJJyY6yJTZGZ5boRG2ZntNOeQCw01o7avQ6X/wBl1Zo3YyD/ANE63kS2y6hoMjLqJy6ADiwZhQrCbUrgp++WT/2S1+AiBFkh7u7Zto2/FXuUiqtE9IcIszbYL5o6rrmaiT2QGbNuMwGTiRDixI8Y0odlzXTRHYUraSVGRGpxxXptzQRrPPM8iPMFSHZlNotYt+oUW3bxnRK/JW3Km1NiKbElSUnqkTbbqS1WiLnS1czLPaeajMww+2qDWMQbqqEO6K+7Kj0Bh5l6U00hLhoS8pGRGZGRKWbSlKXqmrVQhPDmZha7gXQqdBoly2lWJRreZkyGkTlpOXDUyk1a55FrE2oyNCkLzI9csgRsxAkKlwY0hbZsreZQ4po/oDUkjNPYzy7AKqAAAAAGG4o307YdCiyIkFFQqM6Y3AiMvO7k1uq88jcX0Ell/wD84QEG33Rb0uu5W4F6UUq5UETCVTIqYBT6S0yZIQ6vc3EmSkESjJWvz3FlwgiVW9He2KItS7QnV/D53WzIrUrD0aNnxnFcNyOZdTcwHeoUXFiHAdhKuW1cSaS56enXpRN6OuJ9Sb8XWaPrnHAYKdLpFsOuvzsIL0w0kKVmuq4V1U5kFPGo48ZaTMuouIYov1q4ov1WccKz8cLZumbrElNAv2mlT6mfUNTW4OEfVVHUFiQXMR72trW89GF1VUykyI59pTWauwfV3JW4yOwTShbSlXRcf8P61UCpxXPEpdWM9XkXXUrpczPi3GSltZ9gjASBnziVfQq2kroH1j6Io5BHBkRgKCvW9S7qgKg1umQ6zCV6aNUYyJDZ/YrIyEVH3K62rS1KctWRW7CeNWt/gvVXYrGf7VUa459lsA87uLFt7abd9BvGOSsyj3NS1QZJlxb5iHqZ9U44DksWrloOy6sMbghtkeSp1tuNVyNlx6rRokEX+xAXW2sdbAu2cUCn3ZTU1TPV5GTnDhTSPiOO+SHPvQGdqI05axGnPgzLLMUcGRHw5AinqVNiVmC5CqEVifDcLJcaW0l1pRcRoURkfaBUdu6OllRXnZFvRJ1jy3NpvWjUXqYkz4zZbVuKvsmzEodJdnYmUmK9Hp19Uy7qetOodOvaioUpafUnIiG2XZUysSi0dTbDhUOW9MqOClWtWYZc9WsJK3kkz6K1MNKjOq6xsudkFe9Mv7VkqpVDxwhSJBpJBW3irRCjSnD9RrZRHT4szQ52QGLYkaM9pXoh53EHRqpNUUtOsuu4cT2t1Vn9FuZ71dPrETnZCxEULR0tKxKgUfCnSQvfBSqKy3O3b0J2PHM+gkmpJMksutunZBEksXJpsYUMJfdplj450QiI0yqc8UCa6njL52gzMuJKwW1bD807pFnSkwsX8Kr5wsl5klT8unqlQ8+iZOESFGXWQYFp7w20uMHMW9zTa2ItBqMhzLVhuSyjSTz/AP0XdVf3BFS4S0mWeezjAdgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAddYgGHX9jLYuFkVT933fRLbQlOtlU57bK1F9ShR6yusRGA1surzUvCGLPcpdkxLlxPrHA3FtikuLSpXFrOEk8uqlKgRZFY9aXmL5qRYuCVIw3prpFqVK+JxrfSXqtxLUUR9Tc1ClsEu/CC9K/LVGx10vXojzxkS7UsTKO4v6gm2iJxfZZMEX3D7RAwfoL2+LT0f7nxBn6xKOtYgvbyjrP1ZolKJZl0dkYwVL1UrtTw5iFS6vfeG2DEQstzolswkzZyk8SN13NJn72KoBal0Wi3kSjRaeJ2MJqMlolXbLVSKSrqmw8cds0+9jr7IDO7ds/ESDAVBokaw8JaSrI96W5TFVKQn7NRR2SP/ZrLrhRa5O4C0+vax3hc903ua8tdip1VUaGr/wBrEJloy6ikqFpLZlaliW3YcY49tUCl2+wr0yKXDbj63XNBEZ9czMBe8izzPhPoio54TyLafEXCAxy78SLUw/aJdzXJSaASizSmozW2Vr96hR6yj6hEYisRTjwxXSLzn2bdl4kos0So9MOnwj6u+JpspMuqgldkA18YLm9K3aVhRlFwuKfrkwuwW92Un2Vl1wA8DOTqf8ML4u27EqLJcTkhyLhH1NwhE1mXUWpQDKrOwvtDD4j87VsUmhLUWS3oMNtt1fVU4Ra6j6pmYoyc9p5ntPjPhBAALnjySRqPiIszAYneGLFmYfrJq47ppNHkn6WLKloKQvqJZIzcUfUJJiKx5ONEyv5ps/D67bmI05olyYRUeGfV3SYba1F1UNqCxjd637d9uM7reN84dYQRHE6yG3n1VScouJJvKYb1us052RLGCuVe272QrcouLWN5OJ2Le16LRjV9lvNhSPsXNnGCsptiiYh0qMqPadqYc4N091OSyhRl1eafVMmkx2dbrqc7IguMjBeTcuar1xBvG7yUWS4iaiVIhKLiNiCTRqLqLWrsgMjs3CyzsPMzti1qPQXVemfgwkIfX1VO5a6j6pqMFZSrNajUozUo+io8zAcAOFrJtClKPJKSMzPiIuEBEN36QdHeoCm7OnN1WtyVqYbbNpxJsGRenU2pOsozzIkJyPWPbwJMBasCq9AotSfpVWgzYt2VRzdJVQnKUpUl3JSibMlJStGwlGkjLJWSuezLIgnQByAAAC1XFdFLtSGiVVZiIjS17m2RpUtbiuHVShJGpR5bdhAMRn2LaOK5cmokl5e7mTbz1Pc1N1UjYROtrSZa6eDM0koiy25ZAMIvybCrcWk4dWW2l9ht/Jb7ajcbJxOtnz+3W1FLN1xeZlmSU5mpWRBnGI9kqlW/SHadKjR3KCg0NlPdJll1k20tqSpw9iFZJSZKPZmWR7DzIIdffiVh1Ed5RxJ6SUllZLQ4e0slE24k1IcSZZkpJGZKLMlEAwqoVCRHoUd2WRFULYrDKXDSZ5KYUZJJRZ7cjbcLh9SCKukq3CwLvTn87lVEi7JmfhAUFFqqaYup1daN0TRqLDgsN+qdWglmkuqajQQDLKQwm34cNdUeOTWDQpRIQWupBqPNzc09DNXplnlmfCZERERUrYTW1Im1crkkyIiWo7LkaNFjSm5LhG5q66nVNmaUnkgiJBGfCZmfAQC18kDwkxVqy6iyo6BXdd7d0oNZISazcNWRem3NbjpLSW3UWhREZEoBklPwgsmnFyabcW7SCIpaW3JaVQSQnnkqMyLn0JyzIlqUksi4gGV27f1Au2S6xSqkiVIbTuhtKQttakZ+nSS0kak7S54sy2lxgMgAAAAARpjfcNAYt86DV4DtWenp124sdZIW1krVS7rmR6p655JIkqNR5kSTLMBh+GGMjtpwXaJf0ldP3s2a40yalxLhoTwNuJUklKPL0isjzyUnMzIjMJqt64IF00eLVKY+cmDJSamnTbUgzIjMj51REZbSPhIBcQHGRZ5gLTdFoUK+IJw7jotNuCIezcarDblJLrE4k8uwAwdjR/olvnrWbXLnw/Uk9ZLNvVhzehH+1JG6sZdQkECOKtRsVU09UCdUbKxWo5nmuBdtIVT33C4jdZ3Vkz6psJAYQiJQ7SUpyXhniHhI6a9Zyo4dVBVSpiOrveMpacvfxCAZNZuJlSr8retlYzWZfsnXyKiXXD5G1QuopTBoUk/fRRRnS8ULrtzMrrwvr0ZslapzrZearUfr6iNzkZf7ExbSlwt3HawLnnlT4d1U9mqmrV5F1JSoE0j4t7yCbc+9AZ4eaSI1Eac+DMssxUAHGRHl1AFquW0qJecHeVwUan16H0iqRG5KO0sjy7AisETo82/RuetKrXHYayPWJu3qs4UUj/aj+6sZdQmyACo+LltZbyuK2r3jJP5zXYDlKlGXFviMbjZn/sCAcljFWqERFduGtz0hBHz06iobrkQi484x7sRe+ZIBe7TxqsS+JRQ6LdlKl1DPI6cuQTExJ8So7uq6R9dIDNVZoMiURpM+goshUcGRHwlmAo61RKdckBcGrwItWgr2KjT2EPtK66FkZfcEVHx6O1o05a3bYOr2G+o9bO1Ko9CZz6sbNUdXZaMKLeVRtDE2HCehtXXb9+0xzYunXpRSaW4n1Jvxckdk45iUto7kWVTbbfekSsH7osGSpXPVbCisG9GL6o47Cmlq6yoqgFZSr7eqbzlHoGNNv3K6rJvzsYmUZMOcv6k9Qo7nZUwvsgMHxL0WrCu7d3L/ANGdlDqtq65htObdMz9VuSTjPH1tyc7ICMqRgBSrKqO88HdKW68MKkRluVrX0S228+gkmJKWc+whfZBEkIvnTWwjbJdWs+zcaqOnJRS6DJ3jNcTxkk9QjM/qW1BSq2meah2jbk1NOxXw+vbCeomokqVVqYt+MR9RxJEsy6pNiFthcN9KDCfFxKCtLECgVl9ZkSYjc1Lcnssr1XC7kFSfrF1uuA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAODURdEBi974p2dhrCOXdl0Ue245J1iXVZzcfMuoS1EZ9gBrVeXmo+CtFnKptryK5iPWD2IhWrSnHtZXES3NQjLqp1gS2OHpKaVmLxmjDvAOLZFPdTkiq37ONKyI/otw+ZqLraqxS2F3lhXihWndyx10uY9qpeIiVbNkasV5ZeoSSNRxf2tYIrLD0PMF6XJOXbuCd64r1Q8lHWb3cVBiuH6oylqaNRdVLC+yAmmXNquFtOTBm3JhbgRTFII2qdSI6Zk1RcSdfcEGrrMOdkFWlUOiXslWVLxWxmJxOsTlVdXRaOZ+8WcRlaes252QGa2tZl+0qIqLbVCw+whprqS1mqRBXVJfXM0lGaJXX3QuuFFrwvA1uv5qvC87tvDXLJcZ+pnT4auoceETKVF1Fmvq5i0lsrtDDe1MP21Itm26TQNYslrp0Jtla/fLItZR9UzMBkZ7VZntPjPhFQz2kXRPgIBY7rvq27DilJuWv0u32D9KuqTG4+t1iWZGfWLMRWFIx/plcIitC2rpvjWzJL9KpK48M/wD3Us2WjLqpUoAKdi/c2ruFMtSxIys+fqEl6tTC/wBk1uLKT/2iy64B6Cc2ukR3fiFddxpMslwoctNGhn1Nzhkhwy6i3VBQyOz8I7KsB3drdtWk0mUfppjERJyV9VTys3FH1TUYDLlc8eajNR8ZnmYqAAW08i2nxFwgMavDEy0sP0EdzXNSaCpRZobqExtpxfUS2Z66j6hEYisWRjhyfyTZ9kXbd2unNEpum8jYauru802SUXVQlfZCxY7vvi+KHDKVdVzYd4PU1xBmlyqzVVSWfULXVGaJXWJwuuJa0j9VyW1eqOcqGLON+unVUilsro1GM/fpKGwpHXW52QGR2nQb6oqDRZuH+HWEEZxOquQtKqtUFlxqTHSy3re+eX2RBeHsIqvcvPXniZd9ypMslQ4EtNEhGXqdzhkhxRdRbqgVerPwfsfD9437dtKj0mWraqazESqUs+NT69ZxR9U1GAzBajcVrLUa1cajzMAAAAAAAHBgIbqm96JpFJkTlJhJqlL3KDMURERSDQTWZn6rnTT11oL6IgHjauF95O3LQ5l2VGPJZoSUIRMJ7dHpJNrUtOseWe1aiM1LPMiLVItpmAmouAsuDIByAAACzV+zqFdT8Jyt0yPUSiKUbW+CM0oJRES8yzyMjIi4c+Aj6ADXC2qXOrTMenUxybMVUWCddgJlmxHcbbM0pfkL4ciQaE7c9bYWqo+AL7U7Sr2H9QhVLc2KNIeJMSPU6RIN1kj2qQw82pKSNB5HkWRpM+A0qyAZVdLVTxSsy263Dp+/d6uPb+ozaiMzeT8zNTZK2LNCkr1UntMl5lzxAI1qtHp9RdXEUwqlVUyzJqRGVGdMy288hRJNZFxltLhIyPaAjurT35r1VhzEmibLhPUuURnnnJZLdY68+jroMyz6Jl2ARUU6qlIw8u9ST2yFE4jb09CfDmAt0arsQ4qVOlukfkg9VX0lt1245JZYR9k6RZdYBIFKpbLDbUuvGh+qS8nN7KSbh63ETZEZrUXBwGSeAstpmVKWGVs1CnXGu4n6e7QKQxCdS8qS1uDkxORGXzLhJKNU1EpZEeZ5EWRmAxlx+uYu1yO4UffjiSKfGhPyDZiU1ozMmlrMiM1OqLPbkZmesRaqSAeFYtKp2zIZptRQqnQKg+Sjbp0s3YE1aDJZtrQaS1F5p1jLVI1Ek9p7SASXhBaVDO2LeuJuAydcXDWT08zPdVuLUZO623Iz1iMszLMiLLg2AJIAAAAARjiNYtdqN00y6LZdiuVGESGzYlKIkkps3NVRZ7D2OrI0mZH6UyPMsjDCrqpExLuGtq1ScVeuxmab0x1at1NDC3Sc1VKMszIiRmWZFsaM+DIEbBqVrqNWZnmee0FAAAAAABxlkZGWwy4DAWO7rEtu/wCLve57epVxMlwJqsJuSafemsjNPYMgGHR8B4NuaqrKuu7bDNB5oj0qrrkwkn+1JhPNEXUSSQSnjXKPie/AKBW2rBxfo6TzOHclMXS5K/s0lIYM/wDZoLrAMNZ879nERybJxQwZUlRqcmWfKXVqQnq7jHVIaJPvoyRRltkYjV65XEs2RixYWJyyMzVS6y1yMqaC4lqjmeqfvopAMyVixcNv6pXbhlc1LRnkqbQibrcXLjyYMnyLrsELaUutrY22HecwoNJuulvVPPI6a+9vaYk+I47xIdLspAZuojQZEojSZ+qLIVAAy259EuiAsd12Nbl9xSjXJQKZcDBcDdUhtyCT1tcjMuxkCsKb0f6XQySdoXJdFjmnalik1Zb8Mv8A2sonmiLqJSkQCg4v21q73qlq33GTn8zqMZ6iyzL9lZ3Zkz/2SC6wAWNc6hJIrvw8uu3UkRmubBiprMMurukM1uEXVW0kBkVn4vWTf7u4W9dVJqssvTQ2ZSSko6imVGTiT6hpIBl586eSiNJ8RlkKjgyI+gAt1xWzSLugHBrtKg1uEfDGqUZElvuVkZCKwJOj1bdIPXtOfX7Dc1tYkW1VnWYxH+1Hd0j9jcwoU9XtHExNPcgv1q1MSqQtXP0+8KNvR1wuI3o+u0fZjkJRaPVWnSrVcW69hhfGGDyl5qqWGdUObAT1TjR1bS99EBVwpF5zLo3Sj0DFyzsQNdWods3/AEpMKoKL1Ktz3JRH76KYCOMSdE7DS6VOu31o1y6LINXPVvDaWiSjW9WTTRsunx/5OoBglvYGO2lUChYJ6WdetCehXzK0r9IzyPoI3vJJtRcWxlQIkROKOmhg+SfPLhta2L9KQeZzbWmHEluJ49zPLM+oloFXGieak4fUye3TMTLSvLCeqmrVWivUla2CPqLQWuZdXcyELbGYc6ROGWLbbZ2ffVBr7q+CNEnI3cuu0ZksuykFSHrF1uuA7AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADjMi6IDH7vxCtjD+Ac257hpVuwyIz3eqzW4yNnVWZZgNar481AwLteYdPotZqV+1Y8yRBtWnOSTWroES1aiD+xMwRinLW6TOLeqnDLR4XbUF0vmdYv6ZuBZHwK3DNs+0ahaLYleWG2NdYJJ44aV1Jw6iPJyOgWaSIryiP6BKs23FcXAvsgPKyNDvBFiYmfSsLcQca6ustc6xdinIcR0/VGuUqOlZe9bc7ICciaqmEtJQyqVhPo/UdaPmbMdCZktRcRZ72bNX2LnZCxatai3una5ivjQTqdu5kuiUdR9ct5srR2XeyCMvtCyb2ojJt2nZ2HmEUR1GqtceOqqzldVRNJjt63Xcc7IUtr+rBWTX8lXhf123RrJyXEanFSYZ9TcoSWlKLqLcULSWyOz8KrOw/Ua7btek0V9RZLkxIaEvr6qncjWo+qajAZUfPHmZmZ8Z7TFHGZF0QRarmu6h2XC35cNZp1BidPqktuMjsGsyz7AgwRGkNQKzzto0i478WZ6pOW/SHDin/AO7f3JjLqk4YKFV8Xbl1d5W9bNjxlH8+rk9yrSiLj3CMTbRH/t1AOSwcrFdIju3Em6Kygz5+DRnG6HEPqZRiJ4y988YC+WlgvYtjSil0S06VDqHCdQVHJ6Wo+NUhzWcM+uoBmijNRkajNRl0VHmKgCmeZkRbTPoEAsF23/bNhR0v3LcNKt9pRc6dTmNxzV70lGRq6xEYgxBrHeHXtUrPtS671NZHqSIFKVEhq60mYbLZl1UGrshZS1XPemIFMgJnXDUbAwhpKyP+67gqSqlJL7HOMyR/ZuF1xLKRyd421eJEkrpxSxqUeaVxrTiLpVJP/bMpjNGn30hfZBV8tG37woiiXZOFuH+FRKzJVRqzp1WpLI+itEZKCNXvpKhBf3sLLkubI7xxTuusoP00GhuN0GJt4S/uYt3MvfPmAuVp4J2FY8zftFtGkxKie1VRdjlImKPjVId13TP7IFZutSnDzWpSz41HmA4AcgAAAAAAAAADgzyIBAuJs2ZibdpW1BglKYp8lxDTbeohx5xtJE+tbqyMm2S1iRqkWaz49hEGM3UqvtwWaBXalJTSm1IdTHcfRKQ43uqWlKRJTtcS3rKzQ5maVapnwECNhrQtCHY1GKkQH5b8Np5xbW/Ht1U2SlZ6hHkXOl0CBV7AcGeQDykTI8RRJffaYUfATriUGfWIzAUteZdl2/Um4+e6vRHkNKT0VG2ok5dkyAa+2RAduC2bnplPSSp8634KozOsSTebbWrdWiPoZ6xJP35ZgOqr1n1q2aLZqKaa3KetlKmWEuKmSTZP5kjcVJLcdpJNZrVkWrsPI8wRIc2wK3DwlYo0R3Xqu779nR475tFJ13FLdYS5mWRc8REeZErUyMyJRgqG6vCo5xHob0iTQX0HzzT26NLZWXAZtr2ZkfRLbxKARrdVaS1LakT3mn5aG0tSJUMyU3KQg82pCDLgWWakqQe0tYjLMgR1otuV9VnVREOEqZGdWSmHmlEW7ISajSptJnmZbcy4+AswFvt2oRIs2IweU9URSFG0k9VL76CzQ3rKyJKEqUalKP1JdEwEoUIoBNOyKnXUVSoST1nyiOKJrqISSNqklwER58eWZgqa8JLRns0+tHMYk02hVFgmGKdIUrXPMlEt/c1Ge5ayVERJ2GeWZkWwBhdGuGrYLVt9moQWnnFx2oy0yXFMNSSaNW5PsuklSTIyUZKbMtYuuW0PKFSZlJwzUqe2th6sXHHlQmXEKQozLNbzpJVzySURLyz2mkiM/TAJVwUbX5wWFkRm29MmOtERf6M5C8jLqbDPsgMzTOjKe3FMlhT3BuZOpNfazzAe/AZkewy6BgACmqUMqjT5UQ3no5PtLaN6OvUcRrEZayVdBRZ5kfGA1yXSZmHV7VSiWdUZzRLUzE3FJNuvSFqYS6rnlkSEqRzyjcUXOpUoj6GQcxEVfCe5GrilQidVNZWta3JaJyJjRZLeNt8ueQ9qkStuZLJJFwFsDZFh5Ehlt1pWu04kloUX0STLMj7RkA9AAAAAAAAAAAAC51RKIzJRcBlsMBjd44bWniG2SLotmkXDl6VdShNvOI964Za6euRkAxePgj529VVlXxeFlanzuLHqh1KCnqFGmk8ki6iDSCKK46NiTPhph3LQ8O8ZKU2R5MViEukzD6uaiksGrrE2XWAYkzNtyykJN+hYr4Jbnman6M4us0ZJ9RDZy2Ep67TfYFGaWPiDdFypT5ysSMPMWmkEalxH1HS6iguJao6nUkr3zCOwAyo8YatQNVN34cXXQC260ymx0VqIRF0daIanSLqqZSLaUvlo4w2Rfkje1Buqk1GcXpoCJSUSkHxKYXquJPqGkgGYqzSeSiNJ8SiyFQACLI8y2HxlwgMdu/Dm1cQGkt3NbdJuBKSySdShNvLR71ai1kn1SMhFYgnAaPQiLzn3hdlmkkucixamc+GXU3tMJ5JF1EavYACbxgtnLVetK/YyC4HUP0OYf2Sd8MqP7FBdYAPHNVCLK77Gu21CSWa5ZU/krCLq7vCN3IuqtCQGU2dijZ+IJGVtXPSK64ks1MwZiHHkdRTeeuk+oaSBGUHsPI9h8R7DFHGRZkfRIBaLos2gXvD3pcVDptfilwM1SI3JSXWJZHl2BFYQ3gBRqJqqtGu3NYqknrJZolWWuIR/tSTuzBF1CQQUKKu2fiQ/A3hVHrJxVpGZmqDdNKVAfWXVdbJ5kz/2CRKW2Apt2j2hzzliYjYSL1jUubYk5VTpaervdhTqMvfRUgLnSLnqF9sqpFExKw/xYZUZpXb1409MKeSeJZNcB++ikFiKsRdEXCe5HFPXlo61yzphrM+TWHUhMxlKvVk3HNLnV2xQGLWrgxcFtTkw8DNLuoQpTSvmdpX4W6rT9RuL5EtPFsYBGfpxp0xcHjSm8sH6BinTGvTVCzJxsSVp9VuR5mZ9QmiClXa2/NS8LEz26XiBRrrwrrBnquMXJSHNzSfUU2SlZdU0EIW2Rw9x0w9xYYQ7Z96UO49Ys9yp89tx1Pvm89ZPZIgVnJKI+iA5AAAAAAAAAAAAAAAAAAAAAAAAAAHVxRoQZkk1GRbEl0T4gGhtG07sacfH6lHwRwLJ+LAmOU+TWrqqrbbDD6ctZC20qRzxZkZkS1HtIVFsu+wdIStsIfxn0nrdwkpjxGZ0i1CRHeMj+hS6o21mfQ2KX2QFrs7Q9wOfnt1FiysSsfa0vnuS1eN2NCdPj3aSqM2pPWNzsgieIFHqOEVHbOJTcJ9HyiLTkTzxply+seW9m9b7NzsgtLamo0a9ySa67ipjMbhGlTVCYXRqQo/2VsojSk++ec7IDJ7Nsa7aFkqz8PMP8KULI0rmSSVVaisuNaWCaSavfPr7IDJjweqtf1VXfiPddfI89aHTpCKLEMj6GrEJLpl1FPKCktfbQwesiw5G+aBatJps4/TTkRUrlLPjU+vWcUfVNRi0MwUeseajNR8ajzFRwZkXDsAW+v3FSrUgKnVupwqLCTwyajJRHbL7JZkQKj/lirWqqlN2rGrl+ukrVztekuyY+f7aWSI5dfdBA88OLNybKbaNAs2Oatki5aoqfJIuPe0QiRn1DkAOSwkuSvbbqxOuGagzzVBtxDVDjGXFrNEqQZdd8BdrZwLsG0JxT6badN5KZ63JOa0cyaZ8ZyHzW598AzpRmvLWM1ZcGseeQqADjMsyLomAs90XlQLIhlLuOuU2gRT4HqpMbjJPrGsyz7AisJbx/o9b1U2hQbmvpSz1UvUWkrbiGf7bk7iwZdVKzCylDX7xxHi07khVW7Iwpo+ZkqfdNWVPfQXVbbNhkj/2yhLKRoq+7buxRtqxAxHxieJRpcgYf09dPpiupviOlpGr7+UoFXW1LduSjyCk2Rg7ZGHLxmZ8mbomck6oouNaIxKMz99KEGTPYbXhc+278V7kmtmeZwLYbaoUYuprtkuQZf7YgVWW1gRh9ac8qhAtKmrqueZ1SoNnPmqPjORINxzP7IBni1Kcy11GvLYWseeQAAAAAAAAAAAAAAAOAGJVnFS2qJPdguznJcxk9V1mBGckm0fEs0EZJPqGefUAVFIxJteuqJuJXYW7n/1eQ5uDxdTUc1VfcAYLcFjXZbt6Sbks9Dc1EtTrhoM2zNs3NU3EqStSUrQa0JWlRKI0nmRkZGAjWtUEqNQafa7UlibVG1zFyijOEtpiRMNptDGuWRGoiQpxeWRFtPYWQInObjBa1PdOOxOeq62+cUqlRlyUEZbPTpLU7SjBVxtvEWg3XKOJBmLRPJJr3lMZUw+aS4VElRFrEXRNOeXRAYdijiHJjTpFEpczka3EbJypVNBkS2tYtYmmzPYlWrkpS+FJGki2nmQQamsRqka5FNs2VW46lGRz5BI1nj6Jkp4zUrrmYC8Wzd7FNqO96ZJqVnVZOSjhuEbSFbdnzNWs04WezYWfECKWTWKpaVX33KZcixkvqei1WjJPOEtZ8+hTSs8m1GZ86esnbkewiyDP0Y43FERuT82kOOZERql02Sw4ZdDNBLy/EQK6u4j3pWmlqjSZe5Ek1mdGoCy50izM90eJRFs6IIs1PptRxIlx2Wt93BIVGTMUquTl7jHbVsSak5GklKPMiSlHQPgIgVYbywiZiSUxJ9KTbdVeQvelRpyyWy9knniIyIiVkR7UKSR5bSzIEd6RdDEK2JT1QSUR6jp3vMZbLPVWhJEWoXRJRapp98RALXb+HKavU2np9MXWa9UHHJLFJSoiZipUrWVnmZJIk6xay1dE8iIzyIBm0+xKlYjsKTIp7VFTIcJhubQp60G24ZGaUOaqUGWtkeR88WZZbMyzKqaViDeEaGmVHnViRBNa20u1Kjb8bUaFmlWTjSSVwpMtp5gis9HW4CLct9UMnM+HeEslEfvNfhBWDXFd9cu6tOttKlVOrtpNlc2UycSLT0KyNRNoMsyWZEXQNWwjM8iIgRV3BdDdNp0SnViqSH2GW0MRqHTUrQ0SSLJKSZQesvYXpnFHntMBYFzUtoNbmHcluIkszXuLG6kXHqJ54u3mCpHw3xR5EJhuFUHajashaWVlKWa3acozIiUSlc9uZGZEpCjPVI9ZJ5EZGE03JdtJtCO27VpqIm6KNDTWqa3XVFwkhCSNSsuoWzogMbaxqtha9V9dRp7Z/wCnmU51DZddREeXZyARdWZNOXiNXHHqky3SaqmU2mqMrJxppuZGQht7WI8tQnGlNqPPZntyBFZAwwvev0yj29UExotv0xtbLMyO40ttLSyNKlI1DNTqtRSko1iQSSVmeZgqY6ld1uWow2zOrMCnoaQlCGXZCdckkWRESSM1HsLiAWVnGe03HiS5PkRGlHkmTLgvMsH/ALRSSIi6p5EAzZtxLqErQoloURKSpJ5kZHwGR9EgHYAAAAAAAAAAAAAAEmaFayTNKuNJ5GAxS8sKLMxCUS7mtSj1x9PpZMyGhUhB8aXiInEn1SUQDH2MGpttZKsvEW8bTJJZIhvTyrEJJcRMzScUkuohxPYBFsumiYg1aOli7rOw5xjgNJ1UHJYXSJyeqRPJkNa3Wcb7ADF261bNkoLdW8WsDybTwmS6zRiV1y35HQj7Xs4hRnll33eVwx92s+9cO8YITaNZaYslVLmp6ijZVIb1uu232AspkSsapVAyTeFgXba+Sc1y2YJVeGXV3WEbikl1VtpFtGR2firZuICjRbl0UmtPpLNcaJMQp9HUU0ZktJ9Q0kAyo+dPIyNJ8R7DFQAC2HmWZHxlsMBi144WWdiCZKuW16RW3UlkiRNhoW8jqpdy10n1SUQisXLA5yhJ/wAEL7uy1UpLJENc8qrCLqbjNJ0yLqIWkA3bGC2c9ePaV+xkl6Zhx6hzD+xVu7Kj+yQXWAF49RKGkyvC0brswklz0mZSznQy6u+YZvIIuqvV7ADMLQxEta/2Tdtm46VcCElmrkbNbfUj3yUmakn1DIgGQnsMyPYfEYqBFkZGWwy6JALBdtg2zfsdLFy29SrgaT6VNThtyDT701kZp65GQisQbwHhUHVOz7ruuyjQR6ken1VUuGnrRZhPNkXUQSewFFrXclnYhVCCmFXoFg4uUpBGe9a/TlU2Sf2ZFIZM/sGy6wlLbBkUmi2YlOtbWKODhozWuRbMlVYpCesy0cppKffMI7AC7U2s1PEqEdNpd64Z42wcj3SjXDETCnJTxL3PdUkrrxkgIdxA0P8ABytv75unAW68N6iRmoq1YLu/ozZ+rJMVS1EXVOMkEWez8I78oUko+BOl4qqOM5ki1b61ZLqC9QbbpG4j7SkFZVXNKLSk0d6PJqeK2DtCu62qc0bsu4LSqhMbm2XC4ttZrMu4SXWAtt1gticxjPhZbN7xaZLo8Wuw0zWYc7V3ZtCjPVz1TMtpESiy6BlwcAis2AAAAAAAAAAAAAAAAAAAAAAABwrgAfMywqNFwu01sdMNqhHvaqUuuSm7qpNv2fNXEKXu5az6nFocayQk3STmbqU84ZHmeQqNn7PsK46G8T9nYWWLhs4ZnrVWuPnVKmouNaY5FmfvpRgMuVhPcNw5Ku3E25qojPM4VCNuiRetmwRyDLrvmLSWutrYJ2HZkwp1JtSmM1LPM6k+zvmYo+M5DxrdM/sgGbqM1mRqM1GXBrHmKjgzIi4QFJV6xAt6A5Oqs2NS4TZZqkzXksNJLqrWZF90RUduaRtmznHGbacql9yUHq7naVMeqDefVkJImE9lwgBV1Yp3JrFSLGpNqRzPZKu2rk++Rce9YZLLsG+kA9Cy77gzO6MUKwptR5nBtSIzRmOtunzWRl1nSAXCg4BYfW7PKoM2rBnVUj1uSlY16lMz493kqcWXYMgEgHtSSTMzSXAR8BdYVABwZkXRyAW24rno9oQDnV6rQaHCLhkVOU3Gb7pZkQisDTpC25WD1LTp9wX45rapLtukuuxjP9tu7nH7O6BYpqxd+JfI9c+TR7Sw0pCFc/UbwrG+3W08ZssajRdmQYllIxfxEt25nnGHsVb4xUlIXkul4X0tUWCrqb4io2F7+WCq627brNPm78srBG1bMlGrWTX76qZT6n11Ij7s4Z9RUlIgyx+wb7urM7sxZrW4qPNVPtCGzRWC6hOnu0jLrOpAetD0f8PaBUU1JFqwqlVyPPkrXDXVJhnx7tKU4sj6xkCpCMzNCUGZmhJZJTnsIuoXQAAAAAAAAAAAAAAAAAAAAAYbixXZNDs90oTyo82c+1AZfQeSmjcM9ZZdUkJWZdXIBFdlUu0H97sXDU1QGpKnk0ympkLisbk04banHHUmWa1OJXkSlFsLgMzMwFJQLTZvq8pVEiVh16iRUynGpimW5OuyTiEMmrdEmSi1t1SSiy1iRnmfCCMZiUilblUmZ0lql1SI+phNHXSdeRJMlKT8zJD5IPI0nrZkRJ2GZ5GRmHnSrMeqM9tmW2VZnMIU81TGSSzCgNHnm47kRJIss81qzz2klJgq0TJ9QmslIqFcOlU81khluGo4zaSMiUkjMm3HFq1VJUZJSRJJac8jMiBFduFZtq6mKBVJkhajeNEaS6tK5MCWlJLbUh1JFroUlSTIzIj2mky4SAcVioS7ktkpc40olVObIlTtz9LmlazURdQtUjLiJBcQCR6Nh6q5LFmT6VDpUutt1F6PqVZknm2IzJmkmWkqI0oUZEhWsZbdbhLYZBg5vsrodNrUeG0TKkSF7xcI3GEusE2t1tJLNR7i8y6nNszMkqI8j2JyKke4LA5Gx1T7WcOs0c2ycdpJOk/JitqLPNvaZuJIj2tq54voTP0oCx0K9K/blDdYtmc3Jpshs0R2X3DMoKjPI3GTPoJ2mbKtmZbNXaRhIOCVMaXadVfelypz06oSG5SZL6nVJ1DNsizUZ88pGSzPomsugRAMCpVUquCVcfjzIG+2VR0Q9Zw1NIlNtqVuLzTpIUnW1VGlbasjI+DoZhc69WLjuawqrVq/EZgxuSMFdGYJlTbiVbsSVHz2SlJNKjIlKJJnz5kRJyAQteCiTfq4hF/ckt6lqk8RmTrmrn1yJPaBEyWnyabj3lLtxLS7gZTBS0hxtLilRs3FuJQlRkRqM9bIjMszSRZkeQKpbgxKq9/sQaImhGiY1IQ+9FjE6t191GZoQSVtp3FGtkpSnD2EWWfRASE/ZTdHwZm0OoTjjqbgvPypkdZpJL2anlqI+ijX2ZHwp2dEBG1Kve7lWy3R11B2FC1Eub/3dSppNqQRnHSo9qCQrWLdDM1auRFkZawD2tCz3rlitux3kUG2EGZck1GlCpJ9Eo+vsPM+F1Wef0JKPaQWeq0+mIu2pR4DaolIp2+k60VzN5TEZolyFk4eZm684ZI3Q8zJOWXAAu9oWOVZsis3BU4FFpEHeT0inSKe0aJUV1o15rU6ZmpSM0ZZLUo1dHLPIEYNSoqXKpV2ltkzHqMU1vNEWSUubk0a9nU3Y/uAKCqXZWqwilPuylN1mpQUvyZqUbouLFQkkoaZSezWUeXDwqUZn1A7zadWLaqs6A3cUhFXg5HKjSpZS0MnkWe6JNpHOlrJ1lNKVq557SIzIK6TbzkuJArDjSreqEvWaYqkMtaO67maXGHkHs19ZJkaF7TyzSpQDsVJpcGiyHalOhwqqyREVMKl7ZR+qZUTyUKRsM1GaSNBEesXBmF+rNmzLOtW3q7GNyO/U2nCcgnCZaJl1TBrZQe5lrKMzI+FW08iyzPIFZFVaPZaaTAat65HZFyy4xuxiOYuSiatLZrUh9G1LeuSVEXpDSfBwGQDIcCK5urE+jINW8G2WKjAQr/QtPaxKaLiSS05kXQ1zIthEAlkAAAAAAAAAAAAAAAAAAABCjbVrIUaFcaTyMBht34N2Nf0gpNwWlSKnNLamcuKluWg+NL7eq6k+qSgFnZwlrdtbbNxOu+3kkWSYVTkorkMi6BakslOpLqJeSCLLdtCvitpIr0w6w7xdYbTqolR9ak1BBcaUyUuoJXvX0dgBjybntiy05Lq2K+CBoSSUtVphyr0cj/ZFlLYSnrON9gUSFaV7X3WoSplr3Dh5jBTG0lm9SJyqZK6xkhUlk1dfcy6wWUvTmOKKBmm8LLu2z9ROa5L1N5Iw09U5EI3iSXVWSOrkLaMqtDEm08QG1Ktm5aTX9Us1op01t5xHvkEesk+oZECMkPYeR7D4j4RQACzSeaTNJ8ZHkAw+78H7Iv57fFwWpSapML0s12KlMpB8aX05OJPqkohFY+eC1QoRGdo4iXVb6Sy1IVQkorUMupqSyW4RdRLqQHB1DF+2tbfNItW+oycvmlMlO0aWZfsT27NGf8AtUkAL0gaRRMyu+3rosY05Ep6sUlb0Qv/AHUU3mSLqqUkBm9q3vb19RDlW3XqZcEcuFylzG5JF19Qzy7IIvOZZmXR4hRyWw8y2HxlwgMavDDS0sQEEVzWzSa8aSyQ5UIbbriOqlwy1kn1SMhFYsjA/kBkqz73u20dROSIrdS5JQ09TcJpPEkuohSOpkFFrLddl33V4qY1z25h7i9T2k5JRU4a6XMLqkayktGrqkbZdYSlah6cKWqPhNTLAt62b8sCv3nV4lGYocurnNo8tCnCUvciS+82WSiayJO5nzxbMiMgR9JbMtiLZVo0S3oJasKkwmIDBZZZIabShP3EiNL0AAAAAAAAAAAAAAAAAAAAAAAAA0b80Gp7+DWI2EmkbS2VK861TTRrhJrhepkgzTz3USanUl1XU8QJLcKHNjz4bEqK+iREfbS6y8g80uIURGlRHxGRkfZG2XFQnxaTCcmTpLMKG2WsuRJcS02kuM1KMiLtiKjmRpG2M9Ici0GoS72nI2HGtGnvVXI+I3Wkm0n7JwgsdFXpibcesVDw9iW4wZc7MvKsIS4XV3rDJ0z6ynUAOfQ1vi4tY7lxPnRmVZa0GzqczS2+tuzm7vn1yWg+sAq6To9YfUuemoO21HrlVIyMqlcTrlVlEfGTklThpP3uQCREoJDaW0lqtpLJKC2JSXULgIVHPAA4MyLhMBRVuu022aeudWKhEpMFG1UmfIRHaLrqWZF90RUfHpE2lUlrbtdFYvx9KtXK1aW9MZz6skyTHLsuhZTzqV3Ymy4L8xu1besGltbV1G9K0TzjafVGxF+Z9uQQllIvm4lUGvSnokzGa58QpqVc9RsJaQbcc/qTfjIdWnrqlJBXtQ7bmtTznWhgRRaFNNRKRcWJVXTMqKT9VqN75ePrKeR2BBmT9mYjXXn56MV50OOv01Osqms0poupu7u7v9lKkH1gCl6POHtPqKKlJttm4auk8yqlzPO1iVnxk5KU5qn70iBUioSTbKGUlqsoLJLadiElxERbCAMsgHIAAAAAAAAAAAAAAAAAAAAAAAMOxYocmuWa/vJpUibBeansso9M6bas1ILqmg1kXVyARRb1UtaZQypdzQnpdI3dyZTKrDQ4pTJOnrONqNvn0c/mfAaTI8jyNIDJoN923aFPeiWVRpM+S+ZKXKmIdaaUoiyJTrrvzRzIuBKSPZsLVAYvaVsVK+Ki+UKQnn33F1G4FtEaCcWvWWhouBa8/oczSgiLWMzLIw9qbbl51+jVuHbUXkBbynX4m95aktTJ/ChbjjjjS1LWos+eM0JLPJOwswGIRai7RanT6tE3vEn0qZIUhmqoNLKt0JJLaWrgbebUlSclGnMjQpKjyyMjwnz5dw3GVenramyVSSeNEDn0KdyShphsyzJSz1W0klJqyIlGpWasiC/1mwJ+HsWnxZqm1olGmSzJeLXjomLI93iufUL1lkXqkrURbSIFUSIiGG32GavWqMzJSTcmDvKRIWtJFkSTcZcS2+RFzpLXqKNORKBFbCgPVyo0y36PBU2TLbiGI840rcSTqknImSyRzqCMkpSltJ8BEkjzPYVlNbwImW3SyqdtVBx+uQ8nG22IbEZasulGjIyMuHUWpSVERpPhzAZDceG0uuU+PXoEZml3O8w27UKeayTHlOmktdJmWZIcI8yJwuHgVmW0gwKiV2pW9WZTtKeVTaonIp9JqDZ6rhkWRbq3nmRkWwnUHtLoqLYAz+HjgttrKbbdQbf6J0+Sy80rrGpSFF2UgMOve+ZV1uR5M9jkVSIbm6Mw903Z558yNKVLNOw1FrGSG057VZ5meREGD1jDSuPz59NnwHmLhuBceTT9RJqQwlskmklLLYk2eeNzM+jszzIBllFrNWtS43JLTLbdahpOJUaY+o0ofbM9YslERmRGfPtuZGWSjI+E8gkBWOaFMZFbVXU/l87W/HJvP3+6Hs6ur2AGD3jelSudgjrb7FNo5LI00yKpSkvKI80k6syJTp55ZISkizy2KAZHZuF79xLbqFzR1xqZmSmaO6WS3vq5JdBPRJrsr9SApiwsrOIlx1eo3QtdJjMvqj0+MTTL+TJGZINsl6yEN6pJPMk6ylGrMyIiIBjldtmVhlXIbC2YkyEsnURlqZKMxObdQaJEVzVzJtwyPMjLYeRGRbFEAsioEZmMuCzWa7Gpa17oqlS6Y++rWzz2k26Ud08yLnlapKMs1EZ5gipotuSLkrJUeE26xIko3N01rJ1yFFUo1OvvLLYbrhmo9mw1aiU86jMFWKvWo/b1UVTnTOPIpTW8lOHnsZJRmw/mRGeopOXPkRklaC1iyJWRFwuG6p97VAqpWJFJckRKfIiNJpxkpKjdQpCnn1pUpCEJJRqPNWZ5ElKeeMyKyOBQL6h2bNnU5hqVbknXmHRKkht1cppREajNnc9bJRFrEndCXtzIs8iAdq3Zz1PtuHWEw5Um2pkZLzkeUlS5dLJaMlJXmWstsiUZa+WukvTZltIL5RcRYci2m6Hd1OVWaUplDSKlDb3dD7actRTjaT1krLIj128yMyzLVMBQSKhZtEhzvOZCmTa9NZXGRUJiHzTDSstVa9d7LaRGfOpI1KMiIzyzMEZHgVRCQzUqy2k0wXm2afBUf+kZZ1tZwuNJrUZEfR1DMthgqVwAAAAAAAAAAAAAAAAAAAAAAAABClNmZoUpBnwmk8gGD3VgfYN6zd/Ve0aU/Uy2pqUdjes1J8ZSGTQ6R/ZALc1hfc9s5nZ+Kt00lBcEGvm1XouzgLOQRPkXWfAY/dtAu2tuG7e+FFg4pGnIk1OivnS6kgi6KESkqIle9kkCLIV52zZ+afPfifgsssktxLxhrqdJL/bvpkNEn3khHYFEkW1eWIVRp6p9BmWFi5SE5EUy3akqnSFfYGchkz/2iC6wWlLm5jzAoOsm8LXuqyTRlryKlSlSoaevKiG80RdVRp7AtjMLTvy2r9jHItq4KXcDKfTKpcxuRq++JBmaesZEAv2e0y4DLoCoACc0mZpM0mfRSeQDCbrwTsO9pZzKzadLk1HPMqk0xveYk+MpDWq6R9ZQirKeD1coWZ2niXc1KQR87Brim65EIuL+6C3ci6zxAODrWLltZ7+tq272jEfz+gVBylyjLj3vKJbZn/tyAFaQ9u0c9W7aZcNhLz1TXcVJcRGI/wBtM7rHy6puEAzy27qot5QSm2/WKfXYZ/8AWKZKbko7pBmQC6axZHl0BUaW0hnlmfNH5ErV31ZuCtP3BB5GbblYfz1j4s0nrdY4xcYzLUN7SLIshFcgAAAAAAAAAAAAAAAAAAAAAAAAI50i7CgYnYFX3bFTYVIiVGjyUaqE6yicS2a21JLoqStKFF1SIB8tdH3S3v52zaRh7XsRarZKrbprcdcRmyJMqW4ySiS0hUllS3U5INPPbk3sIi1jPadZS1BxZsmPUUVCoSaRdFRTkZTbqw/umrvEfGRyXlkk/ekkuoBSRmdN56Owhhm46KywgtVLLeGlxpQkuIkk5kQDty8Un1zUf+DW5PlADl45Prmo/wDBrcnygBy8cn1zUf8Ag1uT5QA5eOT65qP/AAa3J8oA4Vpxy8uduaj59XDa5PlAGEV7SfuG5p6lzMZ5cGmK/wCzaDhlW6eR9Q5Ba73crSCqaj4y2TQ6jySbTblVquZKKo1/Di56nKSfGT0l1xZH1jIBU3rpU3jeDhNx8bVWvTuBUKgYU1lpSk9At3c3RaeujV7AgxeHf1oInNz6rVKPd1UQeZVC7sPLqrLxHxlvl9aU/YpSKJGj6YU2JFRGYu2hMRkFkhhrC640NpLiJJOkRdggHblx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgHLj1D14UT+DC5PlQDlx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgHLj1D14UT+DC5PlQDlx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgHLj1D14UT+DC5PlQDlx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgHLj1D140X+DC5PlQGFV7GyJWZz06PekCizH1Gt5ym4a3EhDqj4VKbUtSDUfRUREZ9EzAUkPFuGletUb8j1pHSJmHFxoaP3yGlo1usozLqAM7i6XsqDGajxrqoEeO0kkNss4W3GhCElwESSdyIusA9j0yKifDeNFPr4YXJ8qAxi4tICDc805sq56THqCkklU2Dhvc0d5ZFwEo0vZLy6GsR5AOlu4+wranpnsXXTJlQQRpRLqGHFzSHGyPhJGs7kjPo6pEfVAZFO0uH6pDeiTLot+XEeTqOMP4W3GtCy4jI3cjAYYrFyjm5m3dsZhn/w7Nh3WlouoRbvmRdQjAZPQNKBq1oio1JuG3oDK1ayyawvuTWcVxrUbpqUfVUZgLny49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAs1x6S0a7Wm0Va4aBLU186e9DC5UPNe8cS8Sk9g8gGJO4sZrPcMTzYb6DZ4a153L7JZmrtmYC9W3jxCtqaic3dlLqFSb9JNqOGtyPON8eoW6ElHXSkj6oDLeXIqJFl58aLlxehhcnyoCw3RpHxrwS0dSuaiqkMkZMy2MNLlakNEfCSXEukeX1J5l1AGK+iwvX/VSPc/UehnXM8vfcPZAZDbmkBT7XlJlxLjoz1QIsinTcNLmkPl71Sned+xIgGTcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgKeo6Wz1XhOw51z2/MiPFquMSMLbjWhZdUjdyAYa5i7RzXm1dkaK10iPYd1ob6xFu55F1jIBlFA0om7WgnEpNx2/BYNWuom8L7k1nFeqWo3TUpXVUZmApbn0kmLvQzySuaireYz3CUzhpczT7OfDquJeIyI+iXAfEAs9NxppkCU1Ieuun1Z1pRLbKqYd3PIQhRcCiQbpIzLjMjAZry5FRzz8+NFz4/QwuT5UA5cio55+fGi58foY3J8qAwisYz06pSHJMW7qbRJLijUtdLw1uNpC1HwmbRuG2Z9UkkYCkiYtxidI6lf7FaZL/AKtLw2uFDKuopLa06xdQzy6gDP2tMKaw0hpu7aE22hJJQhGF9xpSkiLIiIidyIiLoAO3Lj1D14UT+DC5PlQDlx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgHLj1D14UT+DC5PlQDlx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgHLj1D14UT+DC5PlQDlx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAOXHqHrwon8GFyfKgHLj1D14UT+DC5PlQDlx6h68KJ/BhcnyoBy49Q9eFE/gwuT5UA5ceoevCifwYXJ8qAcuPUPXhRP4MLk+VAdk6ZVSQRkm8qMklbDIsMbkLPr/NQGAXHidZ10VA6jMctNirZ5lVaXhdc1PmkfGUiM825n11GAqrZ0i7ts6eldMx7qb9NLbyLreGtcqjfYed+bkX+1MBeLs0gbVv57fVxItCfUthlUm8LLiZlpPjS+hZOJ7CwFviaQtToEltduYy1akxEmWtTqhYFwViMZcRb7Nbqew6Az6PpwT0NIS/dVFecJJEpxOGVyI1j49XdDy62Zgj15eOT65qP/AAa3J8oAcvHJ9c1H/g1uT5QA5eOT65qP/BrcnygBy8cn1zUf+DW5PlAHKdOSUnPVuekpI+HLDa5Cz/jAGBXNjZZN2z+SE5u12apnrck6dhlcsGZnx74YdQ598CsRvLTJuPB6nMVOgYrVSrMLfJhqiVexqnKQazSo05SJ7rbhFmRFkTq1bcySeRgjZnzLyx3re0aiuGrRJbF1XXWZ9VrDk9lTb63t3U2nMlER5aqNbb0VqPoiLDb8FAAAAAAAAAAAAAAAAAAAAAAAAAHCi2GA0dwcz5qHpC5KMj87tL2kf/6cQVludk501zujFwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmud0YYGTnTXO6MMDJzprndGGBk501zujDAyc6a53RhgZOdNc7owwMnOmu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HSnftZgUbvI6U79rMCjd5HSnftZgUbvI6U79rMCjd5HSnftZgUbvI6U79rMCjd5HSnftZgUbvI6U79rMCjd5HSnftZgUbvI6U79rMCjd5HSnftZgUbvI6U79rMCmpVwrWrzVHDg1pUk/OFL2KIy+jkgN5dYur2jBQlZnwH2gHYAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8/dMywk4xac2DNgT7ir1BodXoE9cldBnHGd1mt2cSZHkaeFBEeaT2Aksl5l7YPsnYp/CFHyItIop3mUeGVTlRJMrEHEqTIiKNcd16tsrWyo8szQZsGaT2FtLIBUcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38iAcy0w99kzFHv+38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' \ No newline at end of file diff --git a/src/utils.ts b/src/utils.ts new file mode 100644 index 00000000..9e7e7610 --- /dev/null +++ b/src/utils.ts @@ -0,0 +1,72 @@ +import { Color, text, Stack, Text, layoutConfig, LayoutSpec, gravity, pullable, stack, image, Image, BridgeContext, log } from "doric"; +export const icon_refresh = 'data:image/png;base64,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' + +export const colors = [ + "#70a1ff", + "#7bed9f", + "#ff6b81", + "#a4b0be", + "#f0932b", + "#eb4d4b", + "#6ab04c", + "#e056fd", + "#686de0", + "#30336b", +].map(e => Color.parse(e)) + +export function label(str: string) { + return text({ + text: str, + textSize: 16, + }) +} + +export function box(idx = 0) { + return (new Stack).also(it => { + it.width = it.height = 20 + it.backgroundColor = colors[idx || 0] + }) +} +export function boxStr(str: string, idx = 0) { + return (new Text).also(it => { + it.width = it.height = 20 + it.text = str + it.textColor = Color.WHITE + it.backgroundColor = colors[idx || 0] + }) +} + +export function title(str: string) { + return text({ + text: str, + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[1], + textAlignment: gravity().center(), + height: 50, + }) +} + +export function rotatedArrow(context: BridgeContext) { + let refreshImage: Image + return pullable(context, + stack([ + image({ + layoutConfig: layoutConfig().exactly().m({ top: 50, bottom: 10, }), + width: 30, + height: 30, + imageBase64: icon_refresh, + }).also(v => refreshImage = v), + ]), { + startAnimation: () => { + log('startAnimation') + }, + stopAnimation: () => { + log('stopAnimation') + }, + setPullingDistance: (distance: number) => { + refreshImage.rotation = distance / 30 + }, + }) +} \ No newline at end of file diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..8a7c268d --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,61 @@ +{ + "compilerOptions": { + /* Basic Options */ + // "incremental": true, /* Enable incremental compilation */ + "target": "ES2015", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019' or 'ESNEXT'. */ + "module": "es2015", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": [], /* Specify library files to be included in the compilation. */ + // "allowJs": true, /* Allow javascript files to be compiled. */ + // "checkJs": true, /* Report errors in .js files. */ + // "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + // "declaration": true, /* Generates corresponding '.d.ts' file. */ + // "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": true, /* Generates corresponding '.map' file. */ + // "outFile": "./", /* Concatenate and emit output to single file. */ + "outDir": "build/", /* Redirect output structure to the directory. */ + // "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "composite": true, /* Enable project compilation */ + // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ + // "removeComments": true, /* Do not emit comments to output. */ + // "noEmit": true, /* Do not emit outputs. */ + // "importHelpers": true, /* Import emit helpers from 'tslib'. */ + // "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ + /* Strict Type-Checking Options */ + "strict": true, /* Enable all strict type-checking options. */ + // "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */ + // "strictNullChecks": true, /* Enable strict null checks. */ + // "strictFunctionTypes": true, /* Enable strict checking of function types. */ + // "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */ + // "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */ + // "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */ + // "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */ + /* Additional Checks */ + // "noUnusedLocals": true, /* Report errors on unused locals. */ + // "noUnusedParameters": true, /* Report errors on unused parameters. */ + // "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */ + // "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */ + /* Module Resolution Options */ + "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */ + // "baseUrl": "./", /* Base directory to resolve non-absolute module names. */ + // "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */ + // "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */ + // "typeRoots": [], /* List of folders to include type definitions from. */ + // "types": [], /* Type declaration files to be included in compilation. */ + // "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */ + "esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */ + // "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */ + // "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */ + /* Source Map Options */ + // "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ + // "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */ + // "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + // "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + /* Experimental Options */ + "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */ + "emitDecoratorMetadata": true /* Enables experimental support for emitting type metadata for decorators. */ + }, + "include": [ + "**/*.ts", + ] +} \ No newline at end of file From 8ee86f93175068c7d9a4e8b8c56d4f6aaace63d8 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 4 Dec 2019 14:09:20 +0800 Subject: [PATCH 03/35] add ignored files --- .gitignore | 3 +++ .vscode/launch.json | 24 ++++++++++++++++++++++++ .vscode/tasks.json | 28 ++++++++++++++++++++++++++++ 3 files changed, 55 insertions(+) create mode 100644 .gitignore create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..692a327e --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +node_modules/ +build/ +bundle/ \ No newline at end of file diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 00000000..39c84064 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,24 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "node", + "request": "launch", + "name": "Debug TS", + "program": "${workspaceFolder}/${relativeFile}", + "preLaunchTask": "Doric Build", + "sourceMaps": true, + "serverReadyAction": { + "pattern": "listening on port ([0-9]+)", + "uriFormat": "http://localhost:%s", + "action": "openExternally" + }, + "outFiles": [ + "${workspaceFolder}/bundle/**/*.js" + ] + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 00000000..d51f6710 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,28 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Doric Build", + "type": "shell", + "command": "doric build", + "group": "build", + "problemMatcher": [] + }, + { + "label": "Doric Clean", + "type": "shell", + "command": "doric clean", + "group": "build", + "problemMatcher": [] + }, + { + "label": "Doric Dev", + "type": "shell", + "command": "doric dev", + "group": "build", + "problemMatcher": [] + } + ] +} \ No newline at end of file From f79399310450405353f0ebff046af2d84cf6ffd9 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 4 Dec 2019 14:27:39 +0800 Subject: [PATCH 04/35] feat:update file path --- package-lock.json | 121 +--------------------------------------------- package.json | 2 +- 2 files changed, 2 insertions(+), 121 deletions(-) diff --git a/package-lock.json b/package-lock.json index ed538db2..40075af9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -33,7 +33,7 @@ "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" }, "doric": { - "version": "file:../js-framework", + "version": "file:../doric-js", "requires": { "@types/ws": "^6.0.3", "reflect-metadata": "^0.1.13", @@ -42,125 +42,6 @@ "tslib": "^1.10.0", "typescript": "^3.7.2", "ws": "^7.2.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" - }, - "@types/node": { - "version": "12.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.7.tgz", - "integrity": "sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==" - }, - "@types/resolve": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", - "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.3.tgz", - "integrity": "sha512-yBTM0P05Tx9iXGq00BbJPo37ox68R5vaGTXivs6RGh/BQ6QP5zqZDGWdAO6JbRE/iR1l80xeGAwCQS2nMV9S/w==", - "requires": { - "@types/node": "*" - } - }, - "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "builtin-modules": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" - }, - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "rollup": { - "version": "1.26.5", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.26.5.tgz", - "integrity": "sha512-c6Pv0yWzjYNpy2DIhLFUnyP6e1UTGownr4IfpJcPY/k186RJjpaGGPRwKQ62KCauctG6dgtHt88pw1EGrPRkuA==", - "requires": { - "@types/estree": "*", - "@types/node": "*", - "acorn": "^7.1.0" - } - }, - "rollup-plugin-node-resolve": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", - "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", - "requires": { - "@types/resolve": "0.0.8", - "builtin-modules": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.11.1", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "requires": { - "estree-walker": "^0.6.1" - } - }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" - }, - "typescript": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", - "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==" - }, - "ws": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", - "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", - "requires": { - "async-limiter": "^1.0.0" - } - } } }, "estree-walker": { diff --git a/package.json b/package.json index 7c36fcc3..5cbba9e2 100644 --- a/package.json +++ b/package.json @@ -10,7 +10,7 @@ }, "license": "Apache-2.0", "dependencies": { - "doric": "file:../js-framework", + "doric": "file:../doric-js", "reflect-metadata": "^0.1.13", "rollup": "^1.27.2", "rollup-plugin-commonjs": "^10.1.0", From 4a8aaebbc745bfe825149e08d8a7f9a820fef68a Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 4 Dec 2019 16:24:28 +0800 Subject: [PATCH 05/35] add license --- LICENSE | 201 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 201 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..97846020 --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [2019] [Doric.Pub] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. From 8712a0d401b762e1bc42053b3719a256ee57940f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Wed, 4 Dec 2019 17:04:30 +0800 Subject: [PATCH 06/35] update rollup & typescript --- package-lock.json | 162 ++++++++++++++++++++++++++++++++++++++++------ package.json | 4 +- 2 files changed, 146 insertions(+), 20 deletions(-) diff --git a/package-lock.json b/package-lock.json index 40075af9..f1d3a996 100644 --- a/package-lock.json +++ b/package-lock.json @@ -5,14 +5,14 @@ "requires": true, "dependencies": { "@types/estree": { - "version": "0.0.39", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", - "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + "version": "0.0.40", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", + "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" }, "@types/node": { - "version": "12.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.7.tgz", - "integrity": "sha512-E6Zn0rffhgd130zbCbAr/JdXfXkoOUFAKNs/rF8qnafSJ8KYaA/j3oz7dcwal+lYjLA7xvdd5J4wdYpCTlP8+w==" + "version": "12.12.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.14.tgz", + "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==" }, "@types/resolve": { "version": "0.0.8", @@ -35,13 +35,132 @@ "doric": { "version": "file:../doric-js", "requires": { - "@types/ws": "^6.0.3", + "@types/ws": "^6.0.4", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.2", + "rollup": "^1.27.8", "rollup-plugin-node-resolve": "^5.2.0", "tslib": "^1.10.0", - "typescript": "^3.7.2", + "typescript": "^3.7.3", "ws": "^7.2.0" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.40", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", + "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" + }, + "@types/node": { + "version": "12.12.14", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.14.tgz", + "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==" + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "resolve": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", + "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "1.27.8", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.8.tgz", + "integrity": "sha512-EVoEV5rAWl+5clnGznt1KY8PeVkzVQh/R0d2s3gHEkN7gfoyC4JmvIVuCtPbYE8NM5Ep/g+nAmvKXBjzaqTsHA==", + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "typescript": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", + "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" + }, + "ws": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", + "requires": { + "async-limiter": "^1.0.0" + } + } } }, "estree-walker": { @@ -60,6 +179,13 @@ "integrity": "sha512-uJA/CDPO3Tao3GTrxYn6AwkM4nUPJiGGYu5+cB8qbC7WGFlrKZbiRo7SFKxUAEpFUfiHofWCXBUNhvYJMh+6zw==", "requires": { "@types/estree": "0.0.39" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.39", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.39.tgz", + "integrity": "sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==" + } } }, "magic-string": { @@ -81,17 +207,17 @@ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, "resolve": { - "version": "1.12.0", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.12.0.tgz", - "integrity": "sha512-B/dOmuoAik5bKcD6s6nXDCjzUKnaDvdkRyAk6rsmsKLipWj4797iothd7jmmUhWTfinVMU+wc56rYKsit2Qy4w==", + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", + "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", "requires": { "path-parse": "^1.0.6" } }, "rollup": { - "version": "1.27.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.2.tgz", - "integrity": "sha512-sD3iyd0zlvgK1S3MmICi6F/Y+R/QWY5XxzsTGN4pAd+nCasDUizmAhgq2hdh1t2eLux974NHU2TW41fhuGPv+Q==", + "version": "1.27.8", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.8.tgz", + "integrity": "sha512-EVoEV5rAWl+5clnGznt1KY8PeVkzVQh/R0d2s3gHEkN7gfoyC4JmvIVuCtPbYE8NM5Ep/g+nAmvKXBjzaqTsHA==", "requires": { "@types/estree": "*", "@types/node": "*", @@ -141,9 +267,9 @@ "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" }, "typescript": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.2.tgz", - "integrity": "sha512-ml7V7JfiN2Xwvcer+XAf2csGO1bPBdRbFCkYBczNZggrBZ9c7G3riSUeJmqEU5uOtXNPMhE3n+R4FA/3YOAWOQ==" + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", + "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" } } } diff --git a/package.json b/package.json index 5cbba9e2..6ec581e9 100644 --- a/package.json +++ b/package.json @@ -12,10 +12,10 @@ "dependencies": { "doric": "file:../doric-js", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.2", + "rollup": "^1.27.8", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "tslib": "^1.10.0", - "typescript": "^3.7.2" + "typescript": "^3.7.3" } } From 82c338bf76c9f9159cddc8dd4beb6ea90f57900c Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 4 Dec 2019 18:15:41 +0800 Subject: [PATCH 07/35] feat:sync lost changes --- src/ComplicatedDemo.ts | 22 ++++++++++++++++------ src/Counter.ts | 6 ++++++ src/ListDemo.ts | 2 +- src/RefreshableDemo.ts | 2 +- src/utils.ts | 4 ++-- 5 files changed, 26 insertions(+), 10 deletions(-) diff --git a/src/ComplicatedDemo.ts b/src/ComplicatedDemo.ts index c4c4db2f..203f2878 100644 --- a/src/ComplicatedDemo.ts +++ b/src/ComplicatedDemo.ts @@ -1,5 +1,5 @@ -import { Panel, Group, vlayout, image, layoutConfig, ScaleType, refreshable, Color, pullable, stack, Image, Refreshable, TranslationAnimation, loge, log } from "doric"; -import { title, icon_refresh } from "./utils"; +import { Panel, Group, vlayout, image, layoutConfig, ScaleType, refreshable, Color, pullable, stack, Image, Refreshable, TranslationAnimation, loge, log, list, listItem, text } from "doric"; +import { title, icon_refresh, colors } from "./utils"; @Entry class MyDemo extends Panel { @@ -11,7 +11,7 @@ class MyDemo extends Panel { onRefresh: () => { refreshed.setRefreshing(context, false) }, - header: pullable(context, + header: pullable( stack([]).apply({ backgroundColor: Color.RED, layoutConfig: layoutConfig().exactly(), @@ -25,11 +25,21 @@ class MyDemo extends Panel { }, setPullingDistance: (distance: number) => { headerImage.scaleX = headerImage.scaleY = (headerImage.height + distance * 2) / headerImage.height - log(`Header Image scaleY:${headerImage.scaleY},height:${headerImage.height},distance:${distance}`) }, }), - content: vlayout([]).apply({ - backgroundColor: Color.YELLOW, + content: list({ + itemCount: 20, + renderItem: (idx) => { + return listItem(text({ + text: `Item :${idx}`, + layoutConfig: layoutConfig().exactly(), + width: root.width, + height: 50, + textColor: Color.WHITE, + backgroundColor: colors[idx % colors.length], + })) + } + }).apply({ }), }).apply({ layoutConfig: layoutConfig().atmost(), diff --git a/src/Counter.ts b/src/Counter.ts index 3b152919..32f4f5e5 100644 --- a/src/Counter.ts +++ b/src/Counter.ts @@ -31,6 +31,12 @@ class CounterView extends ViewHolder { widthSpec: LayoutSpec.WRAP_CONTENT, heightSpec: LayoutSpec.WRAP_CONTENT, }, + padding: { + left: 10, + right: 10, + top: 10, + bottom: 10, + }, shadow: { color: Color.parse("#00ff00"), opacity: 0.5, diff --git a/src/ListDemo.ts b/src/ListDemo.ts index ebd5c186..bd416a0f 100644 --- a/src/ListDemo.ts +++ b/src/ListDemo.ts @@ -91,7 +91,7 @@ class ListPanel extends Panel { }) }) }, - header: rotatedArrow(context), + header: rotatedArrow(), content: list({ itemCount: 0, renderItem: () => new ListItem, diff --git a/src/RefreshableDemo.ts b/src/RefreshableDemo.ts index b91c7e02..3d9d30c8 100644 --- a/src/RefreshableDemo.ts +++ b/src/RefreshableDemo.ts @@ -13,7 +13,7 @@ class RefreshableDemo extends Panel { refreshView.setRefreshing(context, false) }, 5000) }, - header: pullable(context, + header: pullable( stack([ image({ layoutConfig: layoutConfig().exactly().m({ top: 50, bottom: 10, }), diff --git a/src/utils.ts b/src/utils.ts index 9e7e7610..c8d98f37 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -48,9 +48,9 @@ export function title(str: string) { }) } -export function rotatedArrow(context: BridgeContext) { +export function rotatedArrow() { let refreshImage: Image - return pullable(context, + return pullable( stack([ image({ layoutConfig: layoutConfig().exactly().m({ top: 50, bottom: 10, }), From 64a703b83bccfaaeacba399ef37550662deb9d91 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 4 Dec 2019 18:17:12 +0800 Subject: [PATCH 08/35] update package-lock.json --- package-lock.json | 125 ++-------------------------------------------- 1 file changed, 3 insertions(+), 122 deletions(-) diff --git a/package-lock.json b/package-lock.json index f1d3a996..569d975d 100644 --- a/package-lock.json +++ b/package-lock.json @@ -35,132 +35,13 @@ "doric": { "version": "file:../doric-js", "requires": { - "@types/ws": "^6.0.4", + "@types/ws": "^6.0.3", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.8", + "rollup": "^1.27.2", "rollup-plugin-node-resolve": "^5.2.0", "tslib": "^1.10.0", - "typescript": "^3.7.3", + "typescript": "^3.7.2", "ws": "^7.2.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", - "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" - }, - "@types/node": { - "version": "12.12.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.14.tgz", - "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==" - }, - "@types/resolve": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", - "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", - "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", - "requires": { - "@types/node": "*" - } - }, - "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "builtin-modules": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" - }, - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "resolve": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", - "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "rollup": { - "version": "1.27.8", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.8.tgz", - "integrity": "sha512-EVoEV5rAWl+5clnGznt1KY8PeVkzVQh/R0d2s3gHEkN7gfoyC4JmvIVuCtPbYE8NM5Ep/g+nAmvKXBjzaqTsHA==", - "requires": { - "@types/estree": "*", - "@types/node": "*", - "acorn": "^7.1.0" - } - }, - "rollup-plugin-node-resolve": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", - "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", - "requires": { - "@types/resolve": "0.0.8", - "builtin-modules": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.11.1", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "requires": { - "estree-walker": "^0.6.1" - } - }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" - }, - "typescript": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", - "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" - }, - "ws": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", - "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", - "requires": { - "async-limiter": "^1.0.0" - } - } } }, "estree-walker": { From 540177f77ae404136ac7d1df1b457c6238aea59a Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Fri, 6 Dec 2019 11:41:51 +0800 Subject: [PATCH 09/35] update demo --- src/Counter.ts | 17 +++++------------ src/Snake.ts | 8 +++++--- 2 files changed, 10 insertions(+), 15 deletions(-) diff --git a/src/Counter.ts b/src/Counter.ts index 32f4f5e5..76f4852e 100644 --- a/src/Counter.ts +++ b/src/Counter.ts @@ -3,9 +3,7 @@ import { text, vlayout, Image, ViewHolder, VMPanel, ViewModel, Gravity, NativeCa interface CountModel { count: number } - -class CounterView extends ViewHolder { - +class CounterView extends ViewHolder { number!: Text counter!: Text build(root: Group) { @@ -76,24 +74,19 @@ class CounterView extends ViewHolder { } })) } - - bind(state: CountModel) { - this.number.text = `${state.count}` - } - - setCounter(v: Function) { - this.counter.onClick = v - } } class CounterVM extends ViewModel { - onAttached(s: CountModel, vh: CounterView): void { + onAttached(s: CountModel, vh: CounterView) { vh.counter.onClick = () => { this.updateState(state => { state.count++ }) } } + onBind(s: CountModel, vh: CounterView) { + vh.number.text = `${s.count}` + } } @Entry diff --git a/src/Snake.ts b/src/Snake.ts index 05bcba33..962835c4 100644 --- a/src/Snake.ts +++ b/src/Snake.ts @@ -134,7 +134,7 @@ class SnakeModel { } } -class SnakeView extends ViewHolder { +class SnakeView extends ViewHolder { panel!: Stack start?: Text @@ -346,14 +346,16 @@ class SnakeVM extends ViewModel{ this.updateState(it => it.direction = Direction.down) } - onAttached(state: SnakeModel, v: SnakeView): void { + onAttached(state: SnakeModel, v: SnakeView) { takeNonNull(v.start)(it => it.onClick = this.start) takeNonNull(v.left)(it => it.onClick = this.left) takeNonNull(v.right)(it => it.onClick = this.right) takeNonNull(v.up)(it => it.onClick = this.up) takeNonNull(v.down)(it => it.onClick = this.down) } - + onBind(state: SnakeModel, v: SnakeView) { + v.bind(state) + } } @Entry class SnakePanel extends VMPanel{ From 7d83431d6841014b5eadca95fd950b57378c03f5 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Sat, 7 Dec 2019 15:50:37 +0800 Subject: [PATCH 10/35] add input and stick demo --- index.ts | 2 + src/InputDemo.ts | 47 ++++++++++++++++++ src/StickDemo.ts | 124 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+) create mode 100644 src/InputDemo.ts create mode 100644 src/StickDemo.ts diff --git a/index.ts b/index.ts index bd7e494d..2fbf2642 100644 --- a/index.ts +++ b/index.ts @@ -18,4 +18,6 @@ export default [ 'src/AnimatorDemo', 'src/ComplicatedAnimations', 'src/ComplicatedDemo', + 'src/InputDemo', + 'src/StickDemo' ] \ No newline at end of file diff --git a/src/InputDemo.ts b/src/InputDemo.ts new file mode 100644 index 00000000..e1222045 --- /dev/null +++ b/src/InputDemo.ts @@ -0,0 +1,47 @@ +import { Panel, Group, scroller, vlayout, layoutConfig, LayoutSpec, Input, Gravity, log } from "doric"; +import { title, colors } from "./utils"; +@Entry +class InputDemo extends Panel { + build(root: Group) { + scroller( + vlayout([ + title("Input Demo"), + (new Input).also(it => { + it.layoutConfig = layoutConfig().exactly().h(LayoutSpec.WRAP_CONTENT) + it.width = 300 + it.multiline = false + it.hintText = "HintText" + it.textAlignment = Gravity.Left + it.onTextChange = (s) => { + log(`onTextChange:${s}`) + } + it.onFocusChange = (f) => { + log(`onFocusChange:${f}`) + } + }), + (new Input).also(it => { + it.layoutConfig = layoutConfig().wrap() + it.hintText = "HintText" + it.hintTextColor = colors[2] + it.textAlignment = Gravity.Left + it.textColor = colors[3] + it.onTextChange = (s) => { + log(`onTextChange:${s}`) + } + it.onFocusChange = (f) => { + log(`onFocusChange:${f}`) + } + it.backgroundColor = colors[1].alpha(0.3) + }), + ]) + .also(it => { + it.space = 10 + it.layoutConfig = layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT) + })) + .apply({ + layoutConfig: layoutConfig().atmost() + }) + .in(root) + } + +} \ No newline at end of file diff --git a/src/StickDemo.ts b/src/StickDemo.ts new file mode 100644 index 00000000..433609ae --- /dev/null +++ b/src/StickDemo.ts @@ -0,0 +1,124 @@ +import { Panel, Group, scroller, vlayout, layoutConfig, LayoutSpec, Input, Gravity, log, stack, hlayout, text, IHLayout, CENTER, slider, slideItem, modal, Slider, Text, Color, View, Stack, animate, flowlayout, FlowLayoutItem, NestedSlider } from "doric"; +import { title, colors } from "./utils"; + +function tab(idx: number, title: string, sliderView: Slider) { + return text({ + text: title, + layoutConfig: layoutConfig().exactly().wg(1), + height: 41, + onClick: () => { + sliderView.slidePage(context, 0, true) + }, + }) +} + +@Entry +class StickDemo extends Panel { + private tabs!: Text[] + private indicator!: View + private sliderView!: NestedSlider + build(root: Group) { + this.indicator = new Stack + this.indicator.backgroundColor = colors[0] + this.indicator.width = 20 + this.indicator.height = 2 + + scroller( + vlayout([ + stack([]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY), + height: 200, + backgroundColor: colors[0], + }), + stack([ + hlayout([ + ...this.tabs = [0, 1, 2].map(idx => { + return text({ + text: `Tab ${idx}`, + layoutConfig: layoutConfig().exactly().wg(1), + height: 41, + onClick: () => { + this.sliderView.slidePage(context, idx, true) + }, + }) + }) + ]).apply({ + layoutConfig: layoutConfig().atmost(), + gravity: Gravity.Center, + } as IHLayout), + this.indicator, + ]).apply({ + layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY), + height: 57, + }), + + (new NestedSlider).also(v => { + this.sliderView = v; + v.onPageSlided = (idx) => { + this.refreshTabs(idx) + } + [0, 1, 2].map(idx => { + return flowlayout({ + layoutConfig: layoutConfig().exactly(), + width: root.width, + height: root.height - 57, + itemCount: 100, + columnCount: 2, + columnSpace: 10, + rowSpace: 10, + renderItem: (itemIdx) => { + return new FlowLayoutItem().apply({ + backgroundColor: colors[itemIdx % colors.length], + height: 50, + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + }).also(it => { + it.addChild(text({ + text: `In Page ${idx},${itemIdx}`, + textColor: Color.WHITE, + textSize: 20, + layoutConfig: layoutConfig().wrap().a(Gravity.Center) + }).also(v => { + v.onClick = () => { + v.text = "Clicked" + } + })) + }) + }, + }) + }).forEach(e => { + v.addSlideItem(e) + }) + }).apply({ + layoutConfig: layoutConfig().exactly(), + width: root.width, + height: root.height - 57, + }), + ]) + .also(it => { + it.layoutConfig = layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT) + })) + .apply({ + layoutConfig: layoutConfig().atmost() + }) + .in(root) + this.indicator.centerX = this.getRootView().width / this.tabs.length / 2 + this.refreshTabs(0) + } + + refreshTabs(page: number) { + this.tabs.forEach((e, idx) => { + if (idx == page) { + e.textColor = colors[0] + } else { + e.textColor = Color.BLACK + } + }) + this.indicator.layoutConfig = layoutConfig().exactly().a(Gravity.Bottom).m({ bottom: 13 }) + animate(this)({ + animations: () => { + this.indicator.centerX = this.getRootView().width / this.tabs.length * (page + 0.5) + }, + duration: 300, + }) + } +} \ No newline at end of file From 59acec65951101472b2cbed46b275265ada15bad Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 9 Dec 2019 20:34:28 +0800 Subject: [PATCH 11/35] feat:navigator add extra --- src/NavigatorDemo.ts | 12 ++++++++++-- src/StickDemo.ts | 11 +++++++++-- 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/src/NavigatorDemo.ts b/src/NavigatorDemo.ts index 03796ef5..b5ae7eca 100644 --- a/src/NavigatorDemo.ts +++ b/src/NavigatorDemo.ts @@ -1,8 +1,11 @@ -import { Panel, scroller, vlayout, text, layoutConfig, LayoutSpec, Color, gravity, IVLayout, Group, IText, navigator } from "doric"; +import { Panel, scroller, vlayout, text, layoutConfig, LayoutSpec, Color, gravity, IVLayout, Group, IText, navigator, modal } from "doric"; import { colors, label } from "./utils"; @Entry class NaivgatorDemo extends Panel { build(root: Group) { + if (this.getInitData()) { + modal(context).alert(`Init Data :${JSON.stringify(this.getInitData())}`) + } scroller(vlayout([ text({ text: "Navigator Demo", @@ -25,7 +28,12 @@ class NaivgatorDemo extends Panel { textColor: Color.WHITE, layoutConfig: layoutConfig().exactly().w(LayoutSpec.AT_MOST), onClick: () => { - navigator(context).push(`assets://demo/${e}.js`, `${e}.js`) + navigator(context).push(`assets://demo/${e}.js`, { + alias: `${e}.js`, + extra: { + from: "navigatorDemo" + }, + }) }, } as IText) ), diff --git a/src/StickDemo.ts b/src/StickDemo.ts index 433609ae..43d9b3b6 100644 --- a/src/StickDemo.ts +++ b/src/StickDemo.ts @@ -1,4 +1,4 @@ -import { Panel, Group, scroller, vlayout, layoutConfig, LayoutSpec, Input, Gravity, log, stack, hlayout, text, IHLayout, CENTER, slider, slideItem, modal, Slider, Text, Color, View, Stack, animate, flowlayout, FlowLayoutItem, NestedSlider } from "doric"; +import { Panel, Group, scroller, vlayout, image, layoutConfig, LayoutSpec, Input, Gravity, log, stack, hlayout, text, IHLayout, CENTER, slider, slideItem, modal, Slider, Text, Color, View, Stack, animate, flowlayout, FlowLayoutItem, NestedSlider, ScaleType } from "doric"; import { title, colors } from "./utils"; function tab(idx: number, title: string, sliderView: Slider) { @@ -25,7 +25,14 @@ class StickDemo extends Panel { scroller( vlayout([ - stack([]).apply({ + stack([ + image({ + layoutConfig: layoutConfig().atmost(), + imageUrl: "https://p.upyun.com/demo/webp/webp/jpg-0.webp", + scaleType: ScaleType.ScaleAspectFill, + }), + + ]).apply({ layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY), height: 200, backgroundColor: colors[0], From ecd40b9641b14f9761f2b3446f445439b4347bca Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 10 Dec 2019 20:32:17 +0800 Subject: [PATCH 12/35] feat:add list onLoadMore --- src/ListDemo.ts | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/src/ListDemo.ts b/src/ListDemo.ts index bd416a0f..b5ec9ee4 100644 --- a/src/ListDemo.ts +++ b/src/ListDemo.ts @@ -1,4 +1,4 @@ -import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, refreshable, Refreshable, ListItem } from "doric"; +import { Group, Panel, List, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, Text, refreshable, Refreshable, ListItem, layoutConfig } from "doric"; import { rotatedArrow, colors } from "./utils"; @Entry class ListPanel extends Panel { @@ -25,6 +25,17 @@ class ListPanel extends Panel { it.reset() offset = Math.ceil(Math.random() * colors.length) it.itemCount = 40 + it.loadMore = true + it.onLoadMore = () => { + setTimeout(() => { + it.itemCount += 10 + }, 1000) + } + it.loadMoreView = listItem(text({ + text: "Loading", + layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY).a(Gravity.Center), + height: 50, + })) it.renderItem = (idx: number) => { let counter!: Text return listItem( From 83d8da4b9ce9e9cabf248b236285fc9a982fc2e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Thu, 12 Dec 2019 11:59:46 +0800 Subject: [PATCH 13/35] update dependency --- package-lock.json | 137 +++++++++++++++++++++++++++++++++++++++++++--- package.json | 2 +- 2 files changed, 129 insertions(+), 10 deletions(-) diff --git a/package-lock.json b/package-lock.json index 569d975d..29b2b4d5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -10,9 +10,9 @@ "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" }, "@types/node": { - "version": "12.12.14", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.14.tgz", - "integrity": "sha512-u/SJDyXwuihpwjXy7hOOghagLEV1KdAST6syfnOk6QZAMzZuWZqXy5aYYZbh8Jdpd4escVFP0MvftHNDb9pruA==" + "version": "12.12.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", + "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" }, "@types/resolve": { "version": "0.0.8", @@ -35,13 +35,132 @@ "doric": { "version": "file:../doric-js", "requires": { - "@types/ws": "^6.0.3", + "@types/ws": "^6.0.4", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.2", + "rollup": "^1.27.10", "rollup-plugin-node-resolve": "^5.2.0", "tslib": "^1.10.0", - "typescript": "^3.7.2", + "typescript": "^3.7.3", "ws": "^7.2.0" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.40", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", + "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" + }, + "@types/node": { + "version": "12.12.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", + "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "resolve": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", + "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "1.27.10", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.10.tgz", + "integrity": "sha512-5PjBSKney8zLu7tTn/y4iVBL3OyK+G9rA/wfkcY78bZ9kAMtgNqb8nOfR5KpoDYyt8Vs5o2o8DyDjf9RpwYbAg==", + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "typescript": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", + "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" + }, + "ws": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", + "requires": { + "async-limiter": "^1.0.0" + } + } } }, "estree-walker": { @@ -96,9 +215,9 @@ } }, "rollup": { - "version": "1.27.8", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.8.tgz", - "integrity": "sha512-EVoEV5rAWl+5clnGznt1KY8PeVkzVQh/R0d2s3gHEkN7gfoyC4JmvIVuCtPbYE8NM5Ep/g+nAmvKXBjzaqTsHA==", + "version": "1.27.10", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.10.tgz", + "integrity": "sha512-5PjBSKney8zLu7tTn/y4iVBL3OyK+G9rA/wfkcY78bZ9kAMtgNqb8nOfR5KpoDYyt8Vs5o2o8DyDjf9RpwYbAg==", "requires": { "@types/estree": "*", "@types/node": "*", diff --git a/package.json b/package.json index 6ec581e9..4bfba784 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "doric": "file:../doric-js", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.8", + "rollup": "^1.27.10", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "tslib": "^1.10.0", From 4569e6416a8e58820c78a9a3248a925375018dce Mon Sep 17 00:00:00 2001 From: yao <294149113@qq.com> Date: Thu, 12 Dec 2019 16:57:00 +0800 Subject: [PATCH 14/35] add image Blur --- src/ImageDemo.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/ImageDemo.ts b/src/ImageDemo.ts index 357a8e22..c1ca6830 100644 --- a/src/ImageDemo.ts +++ b/src/ImageDemo.ts @@ -53,6 +53,7 @@ class ImageDemo extends Panel { imageUrl, width: 300, height: 300, + isBlur: true, border: { width: 2, color: Color.GRAY, From 0be742d167b449e7ad685c431e9ae3760058934c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Fri, 13 Dec 2019 14:33:24 +0800 Subject: [PATCH 15/35] flow layout demo load more --- src/FlowLayoutDemo.ts | 21 ++++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/src/FlowLayoutDemo.ts b/src/FlowLayoutDemo.ts index f668cc08..5bc11e37 100644 --- a/src/FlowLayoutDemo.ts +++ b/src/FlowLayoutDemo.ts @@ -17,7 +17,7 @@ class FlowDemo extends Panel { build(rootView: Group): void { flowlayout({ layoutConfig: layoutConfig().atmost(), - itemCount: 500, + itemCount: 100, columnCount: 3, columnSpace: 10, rowSpace: 10, @@ -35,6 +35,25 @@ class FlowDemo extends Panel { })) }) }, + }).also(it => { + it.loadMore = true + it.onLoadMore = () => { + setTimeout(() => { + it.itemCount += 20 + }, 1000) + } + it.loadMoreView = new FlowLayoutItem().apply({ + backgroundColor: colors[500 % colors.length], + height: 50, + layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + }).also(it => { + it.addChild(text({ + text: 'load more', + textColor: Color.WHITE, + textSize: 20, + layoutConfig: layoutConfig().wrap().a(Gravity.Center) + })) + }) }) .in(rootView) } From b238485894915508b20af815c136b691fd1966a4 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Sat, 14 Dec 2019 11:30:56 +0800 Subject: [PATCH 16/35] feat:update demo --- src/AnimatorDemo.ts | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/AnimatorDemo.ts b/src/AnimatorDemo.ts index 185acd51..723c9776 100644 --- a/src/AnimatorDemo.ts +++ b/src/AnimatorDemo.ts @@ -29,7 +29,7 @@ class AnimatorDemo extends Panel { hlayout([ thisLabel('Reset').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { view.width = view.height = 20 view.x = view.y = 0 @@ -54,7 +54,7 @@ class AnimatorDemo extends Panel { hlayout([ thisLabel('X').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { view.x = view.x || 0 view.x += 100 @@ -66,7 +66,7 @@ class AnimatorDemo extends Panel { }), thisLabel('Y').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { view.y = view.y || 0 view.y += 100 @@ -78,7 +78,7 @@ class AnimatorDemo extends Panel { }), thisLabel('Width').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { view.width += 100 }, @@ -88,7 +88,7 @@ class AnimatorDemo extends Panel { }), thisLabel('Height').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { view.height += 100 }, @@ -100,7 +100,7 @@ class AnimatorDemo extends Panel { hlayout([ thisLabel('BgColor').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { view.backgroundColor = colors[(idx++) % colors.length] }, @@ -110,7 +110,7 @@ class AnimatorDemo extends Panel { }), thisLabel('Rotation').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { if (view.rotation) { view.rotation += 0.5 @@ -124,7 +124,7 @@ class AnimatorDemo extends Panel { }), thisLabel('Corner').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { if (typeof view.corners === 'number') { view.corners += 10 @@ -141,7 +141,7 @@ class AnimatorDemo extends Panel { hlayout([ thisLabel('scaleX').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { if (view.scaleX) { view.scaleX += 0.1 @@ -155,7 +155,7 @@ class AnimatorDemo extends Panel { }), thisLabel('scaleY').apply({ onClick: () => { - animate(this)({ + animate(context)({ animations: () => { if (view.scaleY) { view.scaleY += 0.1 From 74ee52ed09a8df23d279de945a23613fa2f34fed Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Sat, 14 Dec 2019 14:20:05 +0800 Subject: [PATCH 17/35] update demo --- package-lock.json | 119 ---------------------------------------------- src/StickDemo.ts | 2 +- 2 files changed, 1 insertion(+), 120 deletions(-) diff --git a/package-lock.json b/package-lock.json index 29b2b4d5..7ffbe636 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,125 +42,6 @@ "tslib": "^1.10.0", "typescript": "^3.7.3", "ws": "^7.2.0" - }, - "dependencies": { - "@types/estree": { - "version": "0.0.40", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", - "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" - }, - "@types/node": { - "version": "12.12.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", - "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" - }, - "@types/resolve": { - "version": "0.0.8", - "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", - "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", - "requires": { - "@types/node": "*" - } - }, - "@types/ws": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", - "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", - "requires": { - "@types/node": "*" - } - }, - "acorn": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", - "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" - }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, - "builtin-modules": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", - "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" - }, - "estree-walker": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", - "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" - }, - "is-module": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", - "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" - }, - "path-parse": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", - "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" - }, - "reflect-metadata": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", - "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" - }, - "resolve": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", - "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", - "requires": { - "path-parse": "^1.0.6" - } - }, - "rollup": { - "version": "1.27.10", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.10.tgz", - "integrity": "sha512-5PjBSKney8zLu7tTn/y4iVBL3OyK+G9rA/wfkcY78bZ9kAMtgNqb8nOfR5KpoDYyt8Vs5o2o8DyDjf9RpwYbAg==", - "requires": { - "@types/estree": "*", - "@types/node": "*", - "acorn": "^7.1.0" - } - }, - "rollup-plugin-node-resolve": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", - "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", - "requires": { - "@types/resolve": "0.0.8", - "builtin-modules": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.11.1", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "requires": { - "estree-walker": "^0.6.1" - } - }, - "tslib": { - "version": "1.10.0", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", - "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" - }, - "typescript": { - "version": "3.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", - "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" - }, - "ws": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", - "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", - "requires": { - "async-limiter": "^1.0.0" - } - } } }, "estree-walker": { diff --git a/src/StickDemo.ts b/src/StickDemo.ts index 43d9b3b6..3f74e083 100644 --- a/src/StickDemo.ts +++ b/src/StickDemo.ts @@ -121,7 +121,7 @@ class StickDemo extends Panel { } }) this.indicator.layoutConfig = layoutConfig().exactly().a(Gravity.Bottom).m({ bottom: 13 }) - animate(this)({ + animate(context)({ animations: () => { this.indicator.centerX = this.getRootView().width / this.tabs.length * (page + 0.5) }, From 02dc70270175d78a1f389e4c877e37ddbd63bf61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Sat, 14 Dec 2019 15:36:52 +0800 Subject: [PATCH 18/35] update deps --- package-lock.json | 125 ++++++++++++++++++++++++++++++++++++++++++++-- package.json | 2 +- 2 files changed, 123 insertions(+), 4 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7ffbe636..b074ffed 100644 --- a/package-lock.json +++ b/package-lock.json @@ -42,6 +42,125 @@ "tslib": "^1.10.0", "typescript": "^3.7.3", "ws": "^7.2.0" + }, + "dependencies": { + "@types/estree": { + "version": "0.0.40", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", + "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" + }, + "@types/node": { + "version": "12.12.17", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", + "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" + }, + "@types/resolve": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-0.0.8.tgz", + "integrity": "sha512-auApPaJf3NPfe18hSoJkp8EbZzer2ISk7o8mCC3M9he/a04+gbMF97NkpD2S8riMGvm4BMRI59/SZQSaLTKpsQ==", + "requires": { + "@types/node": "*" + } + }, + "@types/ws": { + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", + "requires": { + "@types/node": "*" + } + }, + "acorn": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", + "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" + }, + "async-limiter": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", + "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" + }, + "builtin-modules": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", + "integrity": "sha512-k0KL0aWZuBt2lrxrcASWDfwOLMnodeQjodT/1SxEQAXsHANgo6ZC/VEaSEHCXt7aSTZ4/4H5LKa+tBXmW7Vtvw==" + }, + "estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha1-Mlj7afeMFNW4FdZkM2tM/7ZEFZE=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "reflect-metadata": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", + "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" + }, + "resolve": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", + "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", + "requires": { + "path-parse": "^1.0.6" + } + }, + "rollup": { + "version": "1.27.12", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.12.tgz", + "integrity": "sha512-51iR7n6NQfdQJlRrIktaGmkdt395A8Vue7CdnlrK6UhY9DY2GaKsTdljWeXisJuZh+w90Gz8VFNh5X+yxP20oQ==", + "requires": { + "@types/estree": "*", + "@types/node": "*", + "acorn": "^7.1.0" + } + }, + "rollup-plugin-node-resolve": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", + "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", + "requires": { + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1", + "rollup-pluginutils": "^2.8.1" + } + }, + "rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, + "tslib": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", + "integrity": "sha512-qOebF53frne81cf0S9B41ByenJ3/IuH8yJKngAX35CmiZySA0khhkovshKK+jGCaMnVomla7gVlIcc3EvKPbTQ==" + }, + "typescript": { + "version": "3.7.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.7.3.tgz", + "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" + }, + "ws": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", + "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", + "requires": { + "async-limiter": "^1.0.0" + } + } } }, "estree-walker": { @@ -96,9 +215,9 @@ } }, "rollup": { - "version": "1.27.10", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.10.tgz", - "integrity": "sha512-5PjBSKney8zLu7tTn/y4iVBL3OyK+G9rA/wfkcY78bZ9kAMtgNqb8nOfR5KpoDYyt8Vs5o2o8DyDjf9RpwYbAg==", + "version": "1.27.12", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.12.tgz", + "integrity": "sha512-51iR7n6NQfdQJlRrIktaGmkdt395A8Vue7CdnlrK6UhY9DY2GaKsTdljWeXisJuZh+w90Gz8VFNh5X+yxP20oQ==", "requires": { "@types/estree": "*", "@types/node": "*", diff --git a/package.json b/package.json index 4bfba784..c8f9338a 100644 --- a/package.json +++ b/package.json @@ -12,7 +12,7 @@ "dependencies": { "doric": "file:../doric-js", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.10", + "rollup": "^1.27.12", "rollup-plugin-commonjs": "^10.1.0", "rollup-plugin-node-resolve": "^5.2.0", "tslib": "^1.10.0", From 02615bc17e52421ad103797c7209c9c852b5a552 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Sat, 14 Dec 2019 16:32:04 +0800 Subject: [PATCH 19/35] update demo --- src/AnimatorDemo.ts | 6 +- src/ComplicatedAnimations.ts | 6 +- src/ComplicatedDemo.ts | 8 +-- src/Counter.ts | 12 ++-- src/EffectsDemo.ts | 34 ++++----- src/FlowLayoutDemo.ts | 10 +-- src/ImageDemo.ts | 14 ++-- src/InputDemo.ts | 8 +-- src/LayoutDemo.ts | 134 +++++++++++++++++------------------ src/ListDemo.ts | 30 ++++---- src/ModalDemo.ts | 24 +++---- src/NavbarDemo.ts | 14 ++-- src/NavigatorDemo.ts | 10 +-- src/NetworkDemo.ts | 6 +- src/PopoverDemo.ts | 8 +-- src/RefreshableDemo.ts | 14 ++-- src/ScrollerDemo.ts | 6 +- src/SliderDemo.ts | 14 ++-- src/Snake.ts | 44 ++++++------ src/StickDemo.ts | 26 +++---- src/StorageDemo.ts | 14 ++-- src/utils.ts | 4 +- 22 files changed, 223 insertions(+), 223 deletions(-) diff --git a/src/AnimatorDemo.ts b/src/AnimatorDemo.ts index 723c9776..d5335d0c 100644 --- a/src/AnimatorDemo.ts +++ b/src/AnimatorDemo.ts @@ -9,7 +9,7 @@ function thisLabel(str: string) { backgroundColor: colors[0], textSize: 15, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), }) } @@ -173,11 +173,11 @@ class AnimatorDemo extends Panel { stack([ view, ]).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), backgroundColor: colors[1].alpha(0.3 * 255), }), ]).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), gravity: gravity().center(), space: 10, } as IVLayout).in(rootView) diff --git a/src/ComplicatedAnimations.ts b/src/ComplicatedAnimations.ts index bc477830..bf437b59 100644 --- a/src/ComplicatedAnimations.ts +++ b/src/ComplicatedAnimations.ts @@ -9,7 +9,7 @@ function thisLabel(str: string) { backgroundColor: colors[0], textSize: 10, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), }) } @@ -190,11 +190,11 @@ class AnimationDemo extends Panel { v.scaleX = 1.5 }) ]).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), backgroundColor: colors[1].alpha(0.3 * 255), }), ]).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), gravity: gravity().center(), space: 10, } as IVLayout).in(rootView) diff --git a/src/ComplicatedDemo.ts b/src/ComplicatedDemo.ts index 203f2878..e5620aaf 100644 --- a/src/ComplicatedDemo.ts +++ b/src/ComplicatedDemo.ts @@ -14,7 +14,7 @@ class MyDemo extends Panel { header: pullable( stack([]).apply({ backgroundColor: Color.RED, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), width: 100, height: 30, }), @@ -32,7 +32,7 @@ class MyDemo extends Panel { renderItem: (idx) => { return listItem(text({ text: `Item :${idx}`, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), width: root.width, height: 50, textColor: Color.WHITE, @@ -42,14 +42,14 @@ class MyDemo extends Panel { }).apply({ }), }).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).also(v => { v.top = 200 }), headerImage = image({ imageUrl: "https://img.zcool.cn/community/01e75b5da933daa801209e1ffa4649.jpg@1280w_1l_2o_100sh.jpg", - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), width: root.width, height: 200, scaleType: ScaleType.ScaleAspectFill, diff --git a/src/Counter.ts b/src/Counter.ts index 76f4852e..96e9876e 100644 --- a/src/Counter.ts +++ b/src/Counter.ts @@ -12,8 +12,8 @@ class CounterView extends ViewHolder { textSize: 40, layoutConfig: { alignment: Gravity.Center, - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, }, }).also(it => { this.number = it }), text({ @@ -26,8 +26,8 @@ class CounterView extends ViewHolder { corners: 5, layoutConfig: { alignment: Gravity.Center, - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, }, padding: { left: 10, @@ -69,8 +69,8 @@ class CounterView extends ViewHolder { root.addChild((new Image).also(iv => { iv.imageUrl = "https://misc.aotu.io/ONE-SUNDAY/SteamEngine.png" iv.layoutConfig = { - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, } })) } diff --git a/src/EffectsDemo.ts b/src/EffectsDemo.ts index 126d6728..1914e360 100644 --- a/src/EffectsDemo.ts +++ b/src/EffectsDemo.ts @@ -50,7 +50,7 @@ class EffectsDemo extends Panel { width: 5, color: colors[3] }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -65,7 +65,7 @@ class EffectsDemo extends Panel { width: 100, height: 100, corners: 10, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ bottom: 10 }) }),]).apply({ @@ -84,7 +84,7 @@ class EffectsDemo extends Panel { offsetY: 3, radius: 5, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ bottom: 10 }) }),]).apply({ @@ -103,7 +103,7 @@ class EffectsDemo extends Panel { color: colors[3] }, corners: 10, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -128,7 +128,7 @@ class EffectsDemo extends Panel { offsetY: 3, radius: 5, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ bottom: 10 }) }),]).apply({ @@ -148,7 +148,7 @@ class EffectsDemo extends Panel { offsetY: 3, radius: 5, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ bottom: 10 }) }),]).apply({ @@ -172,7 +172,7 @@ class EffectsDemo extends Panel { offsetY: 3, radius: 5, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -196,7 +196,7 @@ class EffectsDemo extends Panel { offsetY: 0, radius: 10, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 10, right: 10, bottom: 10, @@ -218,7 +218,7 @@ class EffectsDemo extends Panel { offsetY: 5, radius: 5, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 10, right: 10, bottom: 10, @@ -240,7 +240,7 @@ class EffectsDemo extends Panel { offsetY: 5, radius: 5, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 10, right: 10, bottom: 10, @@ -262,7 +262,7 @@ class EffectsDemo extends Panel { offsetY: 5, radius: 5, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 10, right: 10, bottom: 10, @@ -279,7 +279,7 @@ class EffectsDemo extends Panel { width: 100, height: 100, corners: 50, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -296,7 +296,7 @@ class EffectsDemo extends Panel { corners: { leftTop: 50, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -313,7 +313,7 @@ class EffectsDemo extends Panel { corners: { rightTop: 50, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -330,7 +330,7 @@ class EffectsDemo extends Panel { corners: { leftBottom: 50, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -347,7 +347,7 @@ class EffectsDemo extends Panel { corners: { rightBottom: 50, }, - layoutConfig: layoutConfig().exactly().m({ + layoutConfig: layoutConfig().just().configMargin({ left: 5, right: 5, bottom: 5, @@ -361,7 +361,7 @@ class EffectsDemo extends Panel { it.space = 20 }), ).also(it => { - it.layoutConfig = layoutConfig().atmost() + it.layoutConfig = layoutConfig().most() }).in(rootView) } } \ No newline at end of file diff --git a/src/FlowLayoutDemo.ts b/src/FlowLayoutDemo.ts index 5bc11e37..25b6415b 100644 --- a/src/FlowLayoutDemo.ts +++ b/src/FlowLayoutDemo.ts @@ -16,7 +16,7 @@ const imageUrls = [ class FlowDemo extends Panel { build(rootView: Group): void { flowlayout({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), itemCount: 100, columnCount: 3, columnSpace: 10, @@ -25,13 +25,13 @@ class FlowDemo extends Panel { return new FlowLayoutItem().apply({ backgroundColor: colors[idx % colors.length], height: 50 + (idx % 3) * 20, - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), }).also(it => { it.addChild(text({ text: `${idx}`, textColor: Color.WHITE, textSize: 20, - layoutConfig: layoutConfig().wrap().a(Gravity.Center) + layoutConfig: layoutConfig().fit().configAligmnet(Gravity.Center) })) }) }, @@ -45,13 +45,13 @@ class FlowDemo extends Panel { it.loadMoreView = new FlowLayoutItem().apply({ backgroundColor: colors[500 % colors.length], height: 50, - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), }).also(it => { it.addChild(text({ text: 'load more', textColor: Color.WHITE, textSize: 20, - layoutConfig: layoutConfig().wrap().a(Gravity.Center) + layoutConfig: layoutConfig().fit().configAligmnet(Gravity.Center) })) }) }) diff --git a/src/ImageDemo.ts b/src/ImageDemo.ts index c1ca6830..513f5d6b 100644 --- a/src/ImageDemo.ts +++ b/src/ImageDemo.ts @@ -10,7 +10,7 @@ class ImageDemo extends Panel { scroller(vlayout([ text({ text: "Image Demo", - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[5], @@ -59,7 +59,7 @@ class ImageDemo extends Panel { color: Color.GRAY, }, scaleType: ScaleType.ScaleToFill, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), loadCallback: (ret) => { } }), @@ -73,7 +73,7 @@ class ImageDemo extends Panel { color: Color.GRAY, }, scaleType: ScaleType.ScaleAspectFit, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), }), label('ScaleAspectFill'), image({ @@ -85,7 +85,7 @@ class ImageDemo extends Panel { color: Color.GRAY, }, scaleType: ScaleType.ScaleAspectFill, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), }), label('ImageBase64'), image({ @@ -97,14 +97,14 @@ class ImageDemo extends Panel { color: Color.GRAY, }, scaleType: ScaleType.ScaleAspectFill, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), }), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: gravity().center(), space: 10, } as IVLayout)).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).in(rootView) } } \ No newline at end of file diff --git a/src/InputDemo.ts b/src/InputDemo.ts index e1222045..8b52c831 100644 --- a/src/InputDemo.ts +++ b/src/InputDemo.ts @@ -7,7 +7,7 @@ class InputDemo extends Panel { vlayout([ title("Input Demo"), (new Input).also(it => { - it.layoutConfig = layoutConfig().exactly().h(LayoutSpec.WRAP_CONTENT) + it.layoutConfig = layoutConfig().just().configHeight(LayoutSpec.FIT) it.width = 300 it.multiline = false it.hintText = "HintText" @@ -20,7 +20,7 @@ class InputDemo extends Panel { } }), (new Input).also(it => { - it.layoutConfig = layoutConfig().wrap() + it.layoutConfig = layoutConfig().fit() it.hintText = "HintText" it.hintTextColor = colors[2] it.textAlignment = Gravity.Left @@ -36,10 +36,10 @@ class InputDemo extends Panel { ]) .also(it => { it.space = 10 - it.layoutConfig = layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT) + it.layoutConfig = layoutConfig().most().configHeight(LayoutSpec.FIT) })) .apply({ - layoutConfig: layoutConfig().atmost() + layoutConfig: layoutConfig().most() }) .in(root) } diff --git a/src/LayoutDemo.ts b/src/LayoutDemo.ts index b4762dbb..6a08b068 100644 --- a/src/LayoutDemo.ts +++ b/src/LayoutDemo.ts @@ -103,8 +103,8 @@ class LayoutDemo extends Panel { hlayout([ boxStr('weight=1', 3).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), @@ -114,8 +114,8 @@ class LayoutDemo extends Panel { width: 200, height: 30, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -124,8 +124,8 @@ class LayoutDemo extends Panel { box(3), boxStr('weight=1', 2).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), @@ -134,8 +134,8 @@ class LayoutDemo extends Panel { width: 200, height: 30, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -145,8 +145,8 @@ class LayoutDemo extends Panel { box(2), boxStr('weight=1', 4).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), @@ -154,8 +154,8 @@ class LayoutDemo extends Panel { width: 200, height: 30, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -163,15 +163,15 @@ class LayoutDemo extends Panel { hlayout([ boxStr('weight=1', 3).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), boxStr('weight=1', 2).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), @@ -180,8 +180,8 @@ class LayoutDemo extends Panel { width: 200, height: 30, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -189,22 +189,22 @@ class LayoutDemo extends Panel { hlayout([ boxStr('weight=1', 3).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), boxStr('weight=1', 2).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), boxStr('weight=1', 4).apply({ layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), @@ -212,8 +212,8 @@ class LayoutDemo extends Panel { width: 200, height: 30, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -291,29 +291,29 @@ class LayoutDemo extends Panel { vlayout([ boxStr('weight=1', 3).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, }, }), box(2).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, } }), box(4).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, } }), ]).apply({ width: 100, height: 200, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -321,29 +321,29 @@ class LayoutDemo extends Panel { vlayout([ box(3).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, }, }), boxStr('weight=1', 2).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), box(4).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, } }), ]).apply({ width: 100, height: 200, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -351,20 +351,20 @@ class LayoutDemo extends Panel { vlayout([ box(3).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, }, }), box(2).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, }, }), boxStr('weight=1', 4).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), @@ -372,8 +372,8 @@ class LayoutDemo extends Panel { width: 100, height: 200, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -381,30 +381,30 @@ class LayoutDemo extends Panel { vlayout([ boxStr('weight=1', 3).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, }, }), boxStr('weight=1', 2).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), box(4).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, } }), ]).apply({ width: 100, height: 200, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -412,22 +412,22 @@ class LayoutDemo extends Panel { vlayout([ boxStr('weight=1', 3).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, }, }), boxStr('weight=1', 2).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), boxStr('weight=1', 4).apply({ layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, weight: 1, } }), @@ -435,8 +435,8 @@ class LayoutDemo extends Panel { width: 100, height: 200, layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, backgroundColor: Color.parse('#eeeeee'), gravity: gravity().center(), @@ -453,7 +453,7 @@ class LayoutDemo extends Panel { it.space = 20 }), ).also(it => { - it.layoutConfig = layoutConfig().atmost() + it.layoutConfig = layoutConfig().most() }) .in(rootView) } diff --git a/src/ListDemo.ts b/src/ListDemo.ts index b5ec9ee4..71d4066c 100644 --- a/src/ListDemo.ts +++ b/src/ListDemo.ts @@ -9,8 +9,8 @@ class ListPanel extends Panel { text({ text: "ListDemo", layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, }, textSize: 30, textColor: Color.parse("#535c68"), @@ -33,7 +33,7 @@ class ListPanel extends Panel { } it.loadMoreView = listItem(text({ text: "Loading", - layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY).a(Gravity.Center), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.JUST).configAligmnet(Gravity.Center), height: 50, })) it.renderItem = (idx: number) => { @@ -42,8 +42,8 @@ class ListPanel extends Panel { hlayout([ text({ layoutConfig: { - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.JUST, alignment: gravity().center(), }, text: `Cell At Line ${idx}`, @@ -59,8 +59,8 @@ class ListPanel extends Panel { }).also(it => { counter = it it.layoutConfig = { - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, margin: { left: 10, } @@ -68,8 +68,8 @@ class ListPanel extends Panel { }) ]).also(it => { it.layoutConfig = { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.FIT, margin: { bottom: 2, } @@ -83,8 +83,8 @@ class ListPanel extends Panel { }) ).also(it => { it.layoutConfig = { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.FIT, } it.onClick = () => { log(`Click item at ${idx}`) @@ -107,16 +107,16 @@ class ListPanel extends Panel { itemCount: 0, renderItem: () => new ListItem, layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.AT_MOST, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.MOST, }, }), }), ]).also(it => { it.layoutConfig = { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.AT_MOST, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.MOST, } it.backgroundColor = Color.WHITE }).in(rootView) diff --git a/src/ModalDemo.ts b/src/ModalDemo.ts index 2086e1b0..f4756080 100644 --- a/src/ModalDemo.ts +++ b/src/ModalDemo.ts @@ -7,7 +7,7 @@ class ModalDemo extends Panel { scroller(vlayout([ text({ text: "Modal", - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[1], @@ -21,7 +21,7 @@ class ModalDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { modal(context).toast('This is a toast.') } @@ -33,7 +33,7 @@ class ModalDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { modal(context).toast('This is a toast.', Gravity.Top) } @@ -46,14 +46,14 @@ class ModalDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { modal(context).toast('This is a toast.', Gravity.Center) } } as IText), text({ text: "Alert", - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[2], @@ -66,7 +66,7 @@ class ModalDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { modal(context).alert({ msg: 'This is alert.', @@ -79,7 +79,7 @@ class ModalDemo extends Panel { } as IText), text({ text: "Confirm", - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[3], @@ -92,7 +92,7 @@ class ModalDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { modal(context).confirm({ msg: 'This is Confirm.', @@ -110,7 +110,7 @@ class ModalDemo extends Panel { } as IText), text({ text: "Prompt", - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[4], @@ -123,7 +123,7 @@ class ModalDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { modal(context).prompt({ msg: 'This is Prompt.', @@ -140,11 +140,11 @@ class ModalDemo extends Panel { } } as IText), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: Gravity.Center, space: 10, } as IVLayout)).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).in(rootView) } } \ No newline at end of file diff --git a/src/NavbarDemo.ts b/src/NavbarDemo.ts index 43b743ca..b88fdc7e 100644 --- a/src/NavbarDemo.ts +++ b/src/NavbarDemo.ts @@ -12,7 +12,7 @@ class NavbarDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { navbar(context).isHidden().then(e => modal(context).alert(`Navbar isHidden:${e}`)).catch(e => { modal(context).alert(e) @@ -25,7 +25,7 @@ class NavbarDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { navbar(context).isHidden() .then(e => navbar(context).setHidden(!e)) @@ -40,7 +40,7 @@ class NavbarDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { navbar(context).setTitle('Setted Title') .catch(e => { @@ -54,7 +54,7 @@ class NavbarDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { navbar(context).setBgColor(Color.YELLOW) .catch(e => { @@ -68,17 +68,17 @@ class NavbarDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { navigator(context).pop() } } as IText), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: gravity().center(), space: 10, } as IVLayout)).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).in(rootView) } } \ No newline at end of file diff --git a/src/NavigatorDemo.ts b/src/NavigatorDemo.ts index b5ae7eca..3190be23 100644 --- a/src/NavigatorDemo.ts +++ b/src/NavigatorDemo.ts @@ -9,7 +9,7 @@ class NaivgatorDemo extends Panel { scroller(vlayout([ text({ text: "Navigator Demo", - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[1], @@ -26,7 +26,7 @@ class NaivgatorDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().just().configWidth(LayoutSpec.MOST), onClick: () => { navigator(context).push(`assets://demo/${e}.js`, { alias: `${e}.js`, @@ -43,17 +43,17 @@ class NaivgatorDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { navigator(context).pop() }, } as IText), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: gravity().center(), space: 10, } as IVLayout)).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).in(root) } diff --git a/src/NetworkDemo.ts b/src/NetworkDemo.ts index 851b5704..1515415a 100644 --- a/src/NetworkDemo.ts +++ b/src/NetworkDemo.ts @@ -12,7 +12,7 @@ class NetworkDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { network(context).get('https://m.baidu.com').then( e => { @@ -24,11 +24,11 @@ class NetworkDemo extends Panel { } } as IText), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: gravity().center(), space: 10, } as IVLayout)).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).in(rootView) } } \ No newline at end of file diff --git a/src/PopoverDemo.ts b/src/PopoverDemo.ts index fd0e4f99..8782578b 100644 --- a/src/PopoverDemo.ts +++ b/src/PopoverDemo.ts @@ -12,14 +12,14 @@ class PopoverDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { popover(context).show(text({ width: 200, height: 50, backgroundColor: colors[0], textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly().a(Gravity.Center), + layoutConfig: layoutConfig().just().configAligmnet(Gravity.Center), text: "This is PopOver Window", }).also(v => { let idx = 0 @@ -34,11 +34,11 @@ class PopoverDemo extends Panel { } } as IText), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: gravity().center(), space: 10, } as IVLayout)).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).in(rootView) } } \ No newline at end of file diff --git a/src/RefreshableDemo.ts b/src/RefreshableDemo.ts index 3d9d30c8..a9e012c8 100644 --- a/src/RefreshableDemo.ts +++ b/src/RefreshableDemo.ts @@ -6,7 +6,7 @@ class RefreshableDemo extends Panel { build(rootView: Group): void { let refreshImage: Image let refreshView = refreshable({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), onRefresh: () => { log('onRefresh') setTimeout(() => { @@ -16,7 +16,7 @@ class RefreshableDemo extends Panel { header: pullable( stack([ image({ - layoutConfig: layoutConfig().exactly().m({ top: 50, bottom: 10, }), + layoutConfig: layoutConfig().just().configMargin({ top: 50, bottom: 10, }), width: 30, height: 30, imageBase64: icon_refresh, @@ -43,7 +43,7 @@ class RefreshableDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { refreshView.setRefreshing(context, true) } @@ -54,7 +54,7 @@ class RefreshableDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { refreshView.setRefreshing(context, false) } @@ -66,7 +66,7 @@ class RefreshableDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { refreshView.setRefreshable(context, true) } @@ -78,13 +78,13 @@ class RefreshableDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { refreshView.setRefreshable(context, false) } } as IText), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: gravity().centerX(), space: 10, } as IVLayout)) diff --git a/src/ScrollerDemo.ts b/src/ScrollerDemo.ts index 9870d3d1..0f7a949d 100644 --- a/src/ScrollerDemo.ts +++ b/src/ScrollerDemo.ts @@ -9,7 +9,7 @@ class ScrollerPanel extends Panel { scroller( vlayout(new Array(100).fill(1).map(e => label('Scroll Content'))) ).apply({ - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), width: 300, height: 500, backgroundColor: Color.RED, @@ -17,7 +17,7 @@ class ScrollerPanel extends Panel { scroller( vlayout(new Array(100).fill(1).map(e => label('Scroll Content'))) ).apply({ - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), width: 300, height: 500, backgroundColor: Color.BLUE, @@ -25,7 +25,7 @@ class ScrollerPanel extends Panel { ]) ) .apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.JUST), height: 500, backgroundColor: Color.YELLOW, }) diff --git a/src/SliderDemo.ts b/src/SliderDemo.ts index 6ab55c38..100ab458 100644 --- a/src/SliderDemo.ts +++ b/src/SliderDemo.ts @@ -19,8 +19,8 @@ class SliderPanel extends Panel { text({ text: "Gallery", layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.JUST, }, textSize: 30, textColor: Color.WHITE, @@ -34,7 +34,7 @@ class SliderPanel extends Panel { return slideItem(image({ imageUrl: imageUrls[idx % imageUrls.length], scaleType: ScaleType.ScaleAspectFit, - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST).h(LayoutSpec.AT_MOST).a(gravity().center()), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST).configHeight(LayoutSpec.MOST).configAligmnet(gravity().center()), })).also(it => { let start = idx it.onClick = () => { @@ -43,15 +43,15 @@ class SliderPanel extends Panel { }) }, layoutConfig: { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.FIT, weight: 1, }, }), ]).also(it => { it.layoutConfig = { - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.AT_MOST, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.MOST, } })) } diff --git a/src/Snake.ts b/src/Snake.ts index 962835c4..1998f217 100644 --- a/src/Snake.ts +++ b/src/Snake.ts @@ -155,8 +155,8 @@ class SnakeView extends ViewHolder { margin: { top: 20 }, - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, }, }), (new Stack).also(panel => { @@ -169,14 +169,14 @@ class SnakeView extends ViewHolder { textSize: 30, textColor: Color.parse("#ffffff"), layoutConfig: { - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, }, }).also(it => this.start = it), ]).also(it => { it.layoutConfig = { - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, } }), @@ -190,14 +190,14 @@ class SnakeView extends ViewHolder { textAlignment: new Gravity().center(), backgroundColor: Color.parse('#ffff00'), layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, }).also(it => this.up = it) ]).also(it => { it.layoutConfig = { - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, } }), hlayout([ @@ -209,8 +209,8 @@ class SnakeView extends ViewHolder { textAlignment: new Gravity().center(), backgroundColor: Color.parse('#ffff00'), layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, }).also(it => this.left = it), text({ @@ -221,8 +221,8 @@ class SnakeView extends ViewHolder { textAlignment: new Gravity().center(), backgroundColor: Color.parse('#ffff00'), layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, }).also(it => this.down = it), text({ @@ -233,14 +233,14 @@ class SnakeView extends ViewHolder { textAlignment: new Gravity().center(), backgroundColor: Color.parse('#ffff00'), layoutConfig: { - widthSpec: LayoutSpec.EXACTLY, - heightSpec: LayoutSpec.EXACTLY, + widthSpec: LayoutSpec.JUST, + heightSpec: LayoutSpec.JUST, }, }).also(it => this.right = it), ]).also(it => { it.layoutConfig = { - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, } it.space = 10 }), @@ -249,16 +249,16 @@ class SnakeView extends ViewHolder { controlArea.space = 10 controlArea.layoutConfig = { alignment: new Gravity().centerX(), - widthSpec: LayoutSpec.WRAP_CONTENT, - heightSpec: LayoutSpec.WRAP_CONTENT, + widthSpec: LayoutSpec.FIT, + heightSpec: LayoutSpec.FIT, } }), ]).also(it => { it.space = 20 it.layoutConfig = { alignment: new Gravity().centerX().top(), - widthSpec: LayoutSpec.AT_MOST, - heightSpec: LayoutSpec.AT_MOST, + widthSpec: LayoutSpec.MOST, + heightSpec: LayoutSpec.MOST, } it.gravity = new Gravity().centerX() }).in(root) diff --git a/src/StickDemo.ts b/src/StickDemo.ts index 3f74e083..3fc1b14c 100644 --- a/src/StickDemo.ts +++ b/src/StickDemo.ts @@ -4,7 +4,7 @@ import { title, colors } from "./utils"; function tab(idx: number, title: string, sliderView: Slider) { return text({ text: title, - layoutConfig: layoutConfig().exactly().wg(1), + layoutConfig: layoutConfig().just().configWeight(1), height: 41, onClick: () => { sliderView.slidePage(context, 0, true) @@ -27,13 +27,13 @@ class StickDemo extends Panel { vlayout([ stack([ image({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), imageUrl: "https://p.upyun.com/demo/webp/webp/jpg-0.webp", scaleType: ScaleType.ScaleAspectFill, }), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.JUST), height: 200, backgroundColor: colors[0], }), @@ -42,7 +42,7 @@ class StickDemo extends Panel { ...this.tabs = [0, 1, 2].map(idx => { return text({ text: `Tab ${idx}`, - layoutConfig: layoutConfig().exactly().wg(1), + layoutConfig: layoutConfig().just().configWeight(1), height: 41, onClick: () => { this.sliderView.slidePage(context, idx, true) @@ -50,12 +50,12 @@ class StickDemo extends Panel { }) }) ]).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), gravity: Gravity.Center, } as IHLayout), this.indicator, ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.EXACTLY), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.JUST), height: 57, }), @@ -66,7 +66,7 @@ class StickDemo extends Panel { } [0, 1, 2].map(idx => { return flowlayout({ - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), width: root.width, height: root.height - 57, itemCount: 100, @@ -77,13 +77,13 @@ class StickDemo extends Panel { return new FlowLayoutItem().apply({ backgroundColor: colors[itemIdx % colors.length], height: 50, - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.JUST), }).also(it => { it.addChild(text({ text: `In Page ${idx},${itemIdx}`, textColor: Color.WHITE, textSize: 20, - layoutConfig: layoutConfig().wrap().a(Gravity.Center) + layoutConfig: layoutConfig().fit().configAligmnet(Gravity.Center) }).also(v => { v.onClick = () => { v.text = "Clicked" @@ -96,16 +96,16 @@ class StickDemo extends Panel { v.addSlideItem(e) }) }).apply({ - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), width: root.width, height: root.height - 57, }), ]) .also(it => { - it.layoutConfig = layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT) + it.layoutConfig = layoutConfig().most().configHeight(LayoutSpec.FIT) })) .apply({ - layoutConfig: layoutConfig().atmost() + layoutConfig: layoutConfig().most() }) .in(root) this.indicator.centerX = this.getRootView().width / this.tabs.length / 2 @@ -120,7 +120,7 @@ class StickDemo extends Panel { e.textColor = Color.BLACK } }) - this.indicator.layoutConfig = layoutConfig().exactly().a(Gravity.Bottom).m({ bottom: 13 }) + this.indicator.layoutConfig = layoutConfig().just().configAligmnet(Gravity.Bottom).configMargin({ bottom: 13 }) animate(context)({ animations: () => { this.indicator.centerX = this.getRootView().width / this.tabs.length * (page + 0.5) diff --git a/src/StorageDemo.ts b/src/StorageDemo.ts index f13db93b..fa814397 100644 --- a/src/StorageDemo.ts +++ b/src/StorageDemo.ts @@ -17,7 +17,7 @@ class StorageDemo extends Panel { scroller(vlayout([ text({ text: "Storage Demo", - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[1], @@ -26,7 +26,7 @@ class StorageDemo extends Panel { }), label('Stored'), text({ - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 20, textColor: Color.WHITE, backgroundColor: colors[3], @@ -39,7 +39,7 @@ class StorageDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { storage(context).getItem(storedKey, zone).then(e => { modal(context).prompt({ @@ -60,7 +60,7 @@ class StorageDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { storage(context).remove(storedKey, zone).then(e => { this.update() @@ -73,7 +73,7 @@ class StorageDemo extends Panel { backgroundColor: colors[0], textSize: 30, textColor: Color.WHITE, - layoutConfig: layoutConfig().exactly(), + layoutConfig: layoutConfig().just(), onClick: () => { storage(context).clear(zone).then(e => { this.update() @@ -81,11 +81,11 @@ class StorageDemo extends Panel { }, } as IText), ]).apply({ - layoutConfig: layoutConfig().atmost().h(LayoutSpec.WRAP_CONTENT), + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.FIT), gravity: gravity().center(), space: 10, } as IVLayout)).apply({ - layoutConfig: layoutConfig().atmost(), + layoutConfig: layoutConfig().most(), }).in(root) this.update() } diff --git a/src/utils.ts b/src/utils.ts index c8d98f37..96e1847d 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -39,7 +39,7 @@ export function boxStr(str: string, idx = 0) { export function title(str: string) { return text({ text: str, - layoutConfig: layoutConfig().w(LayoutSpec.AT_MOST), + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), textSize: 30, textColor: Color.WHITE, backgroundColor: colors[1], @@ -53,7 +53,7 @@ export function rotatedArrow() { return pullable( stack([ image({ - layoutConfig: layoutConfig().exactly().m({ top: 50, bottom: 10, }), + layoutConfig: layoutConfig().just().configMargin({ top: 50, bottom: 10, }), width: 30, height: 30, imageBase64: icon_refresh, From a459e0440da0219119484eb32fda512bcea084fc Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 16 Dec 2019 14:08:30 +0800 Subject: [PATCH 20/35] add Gobang --- index.ts | 3 +- src/Gobang.ts | 184 ++++++++++++++++++++++++++++++++++++++++++++++ src/LayoutDemo.ts | 1 - 3 files changed, 186 insertions(+), 2 deletions(-) create mode 100644 src/Gobang.ts diff --git a/index.ts b/index.ts index 2fbf2642..fade3a4a 100644 --- a/index.ts +++ b/index.ts @@ -19,5 +19,6 @@ export default [ 'src/ComplicatedAnimations', 'src/ComplicatedDemo', 'src/InputDemo', - 'src/StickDemo' + 'src/StickDemo', + 'src/Gobang', ] \ No newline at end of file diff --git a/src/Gobang.ts b/src/Gobang.ts new file mode 100644 index 00000000..9f93fb47 --- /dev/null +++ b/src/Gobang.ts @@ -0,0 +1,184 @@ +import { Stack, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller } from "doric"; +import { title } from "./utils"; + + +const lineColor = Color.BLACK +function columLine() { + return (new Stack).apply({ + layoutConfig: layoutConfig().most().configWidth(LayoutSpec.JUST), + width: 1, + backgroundColor: lineColor, + }) +} + +function rowLine() { + return (new Stack).apply({ + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.JUST), + height: 1, + backgroundColor: lineColor, + }) +} + +function pointer(size: number) { + return (new Stack).apply({ + layoutConfig: layoutConfig().just(), + width: size, + height: size, + }) +} + +const count = 13 +enum State { + Unspecified, + BLACK, + WHITE, +} + +interface GoBangState { + count: number + gap: number + role: "white" | "black" + matrix: Map +} + +class GoBangVH extends ViewHolder { + pieces!: Stack + root!: Group + gap = 0 + onPieceDown?: (x: number, y: number) => void + build(root: Group): void { + this.root = root + } + actualBuild(state: GoBangState): void { + const boardSize = state.gap * (state.count - 1) + const gap = state.gap + const borderWidth = gap + let hintText: Text + this.gap = state.gap + scroller( + vlayout([ + title("GoBang"), + stack([ + stack([ + ...(new Array(count - 2)).fill(0).map((_, idx) => { + return columLine().also(v => { + v.left = (idx + 1) * gap + }) + } + ), + ...(new Array(count - 2)).fill(0).map((_, idx) => { + return rowLine().also(v => { + v.top = (idx + 1) * gap + }) + } + ), + ]) + .apply({ + layoutConfig: layoutConfig().just() + .configMargin({ top: borderWidth, left: borderWidth }), + width: boardSize, + height: boardSize, + border: { + width: 1, + color: lineColor, + }, + }), + + ...(new Array(count * count)).fill(0).map((_, idx) => { + const row = Math.floor(idx / count) + const colum = idx % count + return pointer(gap).also(v => { + v.top = (row - 0.5) * gap + borderWidth + v.left = (colum - 0.5) * gap + borderWidth + v.onClick = () => { + hintText.text = `row:${row},colum:${colum}` + if (this.onPieceDown) { + this.onPieceDown(colum, row) + } + } + }) + }), + this.pieces = (new Stack).apply({ + layoutConfig: layoutConfig().most(), + }), + ]).apply({ + layoutConfig: layoutConfig().just(), + width: boardSize + 2 * borderWidth, + height: boardSize + 2 * borderWidth, + backgroundColor: Color.parse("#E6B080"), + }), + hintText = title('Hint'), + ]) + .apply({ + layoutConfig: layoutConfig().fit(), + backgroundColor: Color.parse('#ecf0f1'), + } as IVLayout) + ).in(this.root) + } + + addPiece(pos: number, role: "black" | "white") { + const x = Math.floor(pos / count) + const y = pos % count + const piece = (new Stack).also(v => { + v.width = v.height = 30 + v.corners = 15 + v.backgroundColor = role === 'black' ? Color.BLACK : Color.WHITE + }) + piece.centerX = (x + 1) * this.gap + piece.centerY = (y + 1) * this.gap + this.pieces.addChild(piece) + } +} + +class GoBangVM extends ViewModel{ + onAttached(state: GoBangState, vh: GoBangVH) { + vh.actualBuild(state) + vh.onPieceDown = (x, y) => { + this.updateState(it => { + if (it.role === 'black') { + it.matrix.set(x * count + y, State.BLACK) + it.role = 'white' + } else { + it.matrix.set(x * count + y, State.WHITE) + it.role = 'black' + } + }) + } + } + + onBind(state: GoBangState, vh: GoBangVH) { + vh.pieces.children.length = 0 + for (let e of state.matrix.keys()) { + const v = state.matrix.get(e) + if (v === State.BLACK) { + vh.addPiece(e, 'black') + } + switch (v) { + case State.BLACK: + vh.addPiece(e, 'black') + break + case State.WHITE: + vh.addPiece(e, 'white') + break + } + } + } +} + +@Entry +class Gobang extends VMPanel { + getViewModelClass() { + return GoBangVM + } + getState(): GoBangState { + return { + count, + gap: 40, + role: "black", + matrix: new Map + } + } + getViewHolderClass() { + return GoBangVH + } +} \ No newline at end of file diff --git a/src/LayoutDemo.ts b/src/LayoutDemo.ts index 6a08b068..79027d39 100644 --- a/src/LayoutDemo.ts +++ b/src/LayoutDemo.ts @@ -1,6 +1,5 @@ import { Group, Panel, Text, text, gravity, Color, Stack, LayoutSpec, list, NativeCall, listItem, log, vlayout, Gravity, hlayout, slider, slideItem, scroller, IVLayout, IHLayout, layoutConfig } from "doric"; -import { O_TRUNC } from "constants"; const colors = [ "#f0932b", From 1b7952d1ae6bf8313577d11d397b1e94e1449198 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 16 Dec 2019 14:40:10 +0800 Subject: [PATCH 21/35] feat:adjust anchor style --- src/Gobang.ts | 93 ++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 81 insertions(+), 12 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 9f93fb47..296745bf 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -1,5 +1,5 @@ -import { Stack, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller } from "doric"; -import { title } from "./utils"; +import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull } from "doric"; +import { colors } from "./utils"; const lineColor = Color.BLACK @@ -39,13 +39,17 @@ interface GoBangState { gap: number role: "white" | "black" matrix: Map + anchor?: { x: number, y: number } } class GoBangVH extends ViewHolder { pieces!: Stack root!: Group gap = 0 + currentRole!: Text + result!: Text onPieceDown?: (x: number, y: number) => void + onAnchorDown?: (x: number, y: number) => void build(root: Group): void { this.root = root } @@ -53,11 +57,18 @@ class GoBangVH extends ViewHolder { const boardSize = state.gap * (state.count - 1) const gap = state.gap const borderWidth = gap - let hintText: Text this.gap = state.gap scroller( vlayout([ - title("GoBang"), + text({ + text: "五子棋", + layoutConfig: layoutConfig().configWidth(LayoutSpec.MOST), + textSize: 30, + textColor: Color.WHITE, + backgroundColor: colors[0], + textAlignment: gravity().center(), + height: 50, + }), stack([ stack([ ...(new Array(count - 2)).fill(0).map((_, idx) => { @@ -91,9 +102,8 @@ class GoBangVH extends ViewHolder { v.top = (row - 0.5) * gap + borderWidth v.left = (colum - 0.5) * gap + borderWidth v.onClick = () => { - hintText.text = `row:${row},colum:${colum}` - if (this.onPieceDown) { - this.onPieceDown(colum, row) + if (this.onAnchorDown) { + this.onAnchorDown(colum, row) } } }) @@ -107,7 +117,26 @@ class GoBangVH extends ViewHolder { height: boardSize + 2 * borderWidth, backgroundColor: Color.parse("#E6B080"), }), - hintText = title('Hint'), + hlayout([ + this.currentRole = text({ + text: "当前:", + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().just().configWeight(1), + height: 50, + backgroundColor: colors[1], + }), + this.result = text({ + text: "获胜方:", + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().just().configWeight(1), + height: 50, + backgroundColor: colors[2], + }), + ]).apply({ + layoutConfig: layoutConfig().fit().configWidth(LayoutSpec.MOST), + } as IHLayout), ]) .apply({ layoutConfig: layoutConfig().fit(), @@ -120,7 +149,7 @@ class GoBangVH extends ViewHolder { const x = Math.floor(pos / count) const y = pos % count const piece = (new Stack).also(v => { - v.width = v.height = 30 + v.width = v.height = this.gap v.corners = 15 v.backgroundColor = role === 'black' ? Color.BLACK : Color.WHITE }) @@ -128,20 +157,56 @@ class GoBangVH extends ViewHolder { piece.centerY = (y + 1) * this.gap this.pieces.addChild(piece) } + + addAnchor(x: number, y: number) { + const piece = (new Stack).also(v => { + v.width = v.height = 30 + v.border = { + color: Color.RED, + width: 1, + } + }) + piece.centerX = (x + 1) * this.gap + piece.centerY = (y + 1) * this.gap + piece.onClick = () => { + if (this.onPieceDown) { + this.onPieceDown(x, y) + } + } + this.pieces.addChild(piece) + } } class GoBangVM extends ViewModel{ onAttached(state: GoBangState, vh: GoBangVH) { vh.actualBuild(state) + vh.onAnchorDown = (x, y) => { + const pos = x * count + y + if (state.matrix.get(pos) == State.BLACK + || state.matrix.get(pos) == State.WHITE) { + modal(context).toast('This position had been token.') + return + } + this.updateState(it => { + it.anchor = { x, y } + }) + } vh.onPieceDown = (x, y) => { + const pos = x * count + y + if (state.matrix.get(pos) == State.BLACK + || state.matrix.get(pos) == State.WHITE) { + modal(context).toast('This position had been token.') + return + } this.updateState(it => { if (it.role === 'black') { - it.matrix.set(x * count + y, State.BLACK) + it.matrix.set(pos, State.BLACK) it.role = 'white' } else { - it.matrix.set(x * count + y, State.WHITE) + it.matrix.set(pos, State.WHITE) it.role = 'black' } + it.anchor = undefined }) } } @@ -162,6 +227,10 @@ class GoBangVM extends ViewModel{ break } } + takeNonNull(state.anchor)(it => { + vh.addAnchor(it.x, it.y) + }) + vh.currentRole.text = `当前: ${(state.role === 'black') ? "黑方" : "白方"}` } } @@ -173,7 +242,7 @@ class Gobang extends VMPanel { getState(): GoBangState { return { count, - gap: 40, + gap: this.getRootView().width / 14, role: "black", matrix: new Map } From 3b43a2bd8d8564245ce54e5eecfa303514b6c94f Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 16 Dec 2019 15:39:29 +0800 Subject: [PATCH 22/35] feat:update ui --- src/Gobang.ts | 160 ++++++++++++++++++++++---------------------------- 1 file changed, 70 insertions(+), 90 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 296745bf..3ff7c65a 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -1,4 +1,4 @@ -import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull } from "doric"; +import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull, View } from "doric"; import { colors } from "./utils"; @@ -39,17 +39,16 @@ interface GoBangState { gap: number role: "white" | "black" matrix: Map - anchor?: { x: number, y: number } + anchor?: number } class GoBangVH extends ViewHolder { - pieces!: Stack root!: Group gap = 0 currentRole!: Text result!: Text - onPieceDown?: (x: number, y: number) => void - onAnchorDown?: (x: number, y: number) => void + targetZone: View[] = [] + build(root: Group): void { this.root = root } @@ -75,14 +74,12 @@ class GoBangVH extends ViewHolder { return columLine().also(v => { v.left = (idx + 1) * gap }) - } - ), + }), ...(new Array(count - 2)).fill(0).map((_, idx) => { return rowLine().also(v => { v.top = (idx + 1) * gap }) - } - ), + }), ]) .apply({ layoutConfig: layoutConfig().just() @@ -94,23 +91,14 @@ class GoBangVH extends ViewHolder { color: lineColor, }, }), - - ...(new Array(count * count)).fill(0).map((_, idx) => { + ...this.targetZone = (new Array(count * count)).fill(0).map((_, idx) => { const row = Math.floor(idx / count) const colum = idx % count return pointer(gap).also(v => { v.top = (row - 0.5) * gap + borderWidth v.left = (colum - 0.5) * gap + borderWidth - v.onClick = () => { - if (this.onAnchorDown) { - this.onAnchorDown(colum, row) - } - } }) }), - this.pieces = (new Stack).apply({ - layoutConfig: layoutConfig().most(), - }), ]).apply({ layoutConfig: layoutConfig().just(), width: boardSize + 2 * borderWidth, @@ -144,91 +132,83 @@ class GoBangVH extends ViewHolder { } as IVLayout) ).in(this.root) } - - addPiece(pos: number, role: "black" | "white") { - const x = Math.floor(pos / count) - const y = pos % count - const piece = (new Stack).also(v => { - v.width = v.height = this.gap - v.corners = 15 - v.backgroundColor = role === 'black' ? Color.BLACK : Color.WHITE - }) - piece.centerX = (x + 1) * this.gap - piece.centerY = (y + 1) * this.gap - this.pieces.addChild(piece) - } - - addAnchor(x: number, y: number) { - const piece = (new Stack).also(v => { - v.width = v.height = 30 - v.border = { - color: Color.RED, - width: 1, - } - }) - piece.centerX = (x + 1) * this.gap - piece.centerY = (y + 1) * this.gap - piece.onClick = () => { - if (this.onPieceDown) { - this.onPieceDown(x, y) - } - } - this.pieces.addChild(piece) - } } class GoBangVM extends ViewModel{ onAttached(state: GoBangState, vh: GoBangVH) { vh.actualBuild(state) - vh.onAnchorDown = (x, y) => { - const pos = x * count + y - if (state.matrix.get(pos) == State.BLACK - || state.matrix.get(pos) == State.WHITE) { - modal(context).toast('This position had been token.') - return - } - this.updateState(it => { - it.anchor = { x, y } - }) - } - vh.onPieceDown = (x, y) => { - const pos = x * count + y - if (state.matrix.get(pos) == State.BLACK - || state.matrix.get(pos) == State.WHITE) { - modal(context).toast('This position had been token.') - return - } - this.updateState(it => { - if (it.role === 'black') { - it.matrix.set(pos, State.BLACK) - it.role = 'white' - } else { - it.matrix.set(pos, State.WHITE) - it.role = 'black' + vh.targetZone.forEach((e, idx) => { + e.onClick = () => { + const zoneState = state.matrix.get(idx) + if (zoneState === State.BLACK || zoneState === State.WHITE) { + modal(context).toast('This position had been token.') + return } - it.anchor = undefined - }) - } + if (state.anchor === undefined || state.anchor != idx) { + this.updateState(it => { + it.anchor = idx + }) + } else { + this.updateState(it => { + if (it.role === 'black') { + it.matrix.set(idx, State.BLACK) + it.role = 'white' + } else { + it.matrix.set(idx, State.WHITE) + it.role = 'black' + } + it.anchor = undefined + }) + } + } + }) } onBind(state: GoBangState, vh: GoBangVH) { - vh.pieces.children.length = 0 - for (let e of state.matrix.keys()) { - const v = state.matrix.get(e) - if (v === State.BLACK) { - vh.addPiece(e, 'black') - } - switch (v) { + vh.targetZone.forEach((v, idx) => { + const zoneState = state.matrix.get(idx) + switch (zoneState) { case State.BLACK: - vh.addPiece(e, 'black') + v.also(it => { + it.backgroundColor = Color.BLACK + it.corners = state.gap / 2 + it.border = { + color: Color.TRANSPARENT, + width: 0, + } + }) break case State.WHITE: - vh.addPiece(e, 'white') + v.also(it => { + it.backgroundColor = Color.WHITE + it.corners = state.gap / 2 + it.border = { + color: Color.TRANSPARENT, + width: 0, + } + }) + break + default: + v.also(it => { + it.backgroundColor = Color.TRANSPARENT + it.corners = 0 + it.border = { + color: Color.TRANSPARENT, + width: 0, + } + }) break } - } - takeNonNull(state.anchor)(it => { - vh.addAnchor(it.x, it.y) + if (state.anchor === idx) { + v.also(it => { + it.backgroundColor = Color.RED.alpha(0.1) + it.corners = 0 + it.border = { + color: Color.RED, + width: 1, + } + }) + } }) vh.currentRole.text = `当前: ${(state.role === 'black') ? "黑方" : "白方"}` } From 641bad072d28686d78237af400375234ecc45d5b Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 16 Dec 2019 16:38:53 +0800 Subject: [PATCH 23/35] add gobang roles --- src/Gobang.ts | 117 +++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 116 insertions(+), 1 deletion(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 3ff7c65a..10e8f6cc 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -1,4 +1,4 @@ -import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull, View } from "doric"; +import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull, View, log } from "doric"; import { colors } from "./utils"; @@ -158,6 +158,18 @@ class GoBangVM extends ViewModel{ it.role = 'black' } it.anchor = undefined + if (this.checkResult(idx)) { + modal(context).alert({ + title: "游戏结束", + msg: `恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`, + }).then(() => { + this.updateState(s => { + s.matrix.clear() + s.role = 'black' + }) + }) + } + }) } } @@ -212,6 +224,109 @@ class GoBangVM extends ViewModel{ }) vh.currentRole.text = `当前: ${(state.role === 'black') ? "黑方" : "白方"}` } + + checkResult(pos: number) { + const matrix = this.getState().matrix + const state = matrix.get(pos) + const y = Math.floor(pos / count) + const x = pos % count + const getState = (x: number, y: number) => matrix.get(y * count + x) + ///Horitonzal + { + let left = x + while (left >= 1) { + if (getState(left - 1, y) === state) { + left -= 1 + } else { + break + } + } + let right = x + while (right <= count - 2) { + if (getState(right + 1, y) === state) { + right += 1 + } else { + break + } + } + if (right - left >= 4) { + return true + } + } + ///Vertical + { + let top = y + while (top >= 1) { + if (getState(x, top - 1) === state) { + top -= 1 + } else { + break + } + } + let bottom = y + while (bottom <= count - 2) { + if (getState(x, bottom + 1) === state) { + bottom += 1 + } else { + break + } + } + if (bottom - top >= 4) { + return true + } + } + + ///LT-RB + { + let startX = x, startY = y + while (startX >= 1 && startY >= 1) { + if (getState(startX - 1, startY - 1) === state) { + startX -= 1 + startY -= 1 + } else { + break + } + } + let endX = x, endY = y + while (endX <= count - 2 && endY <= count - 2) { + if (getState(endX + 1, endY + 1) === state) { + endX += 1 + endY += 1 + } else { + break + } + } + if (endX - startX >= 4) { + return true + } + } + + ///LB-RT + { + let startX = x, startY = y + while (startX >= 1 && startY <= count + 2) { + if (getState(startX - 1, startY + 1) === state) { + startX -= 1 + startY += 1 + } else { + break + } + } + let endX = x, endY = y + while (endX <= count - 2 && endY >= 1) { + if (getState(endX + 1, endY - 1) === state) { + endX += 1 + endY -= 1 + } else { + break + } + } + if (endX - startX >= 4) { + return true + } + } + return false + } } @Entry From faaf8fd99d69041b2d22423477e8c60793d1ce47 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 16 Dec 2019 17:06:42 +0800 Subject: [PATCH 24/35] add game mode --- src/Gobang.ts | 74 ++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 68 insertions(+), 6 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 10e8f6cc..2309ef93 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -1,4 +1,4 @@ -import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull, View, log } from "doric"; +import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull, View, log, popover } from "doric"; import { colors } from "./utils"; @@ -33,6 +33,11 @@ enum State { BLACK, WHITE, } +enum GameMode { + P2P, + P2C, + C2P, +} interface GoBangState { count: number @@ -40,6 +45,8 @@ interface GoBangState { role: "white" | "black" matrix: Map anchor?: number + gameMode: GameMode + reset: () => void } class GoBangVH extends ViewHolder { @@ -48,7 +55,7 @@ class GoBangVH extends ViewHolder { currentRole!: Text result!: Text targetZone: View[] = [] - + gameMode!: Text build(root: Group): void { this.root = root } @@ -105,6 +112,15 @@ class GoBangVH extends ViewHolder { height: boardSize + 2 * borderWidth, backgroundColor: Color.parse("#E6B080"), }), + + this.gameMode = text({ + text: "游戏模式", + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().most().configHeight(LayoutSpec.JUST), + height: 50, + backgroundColor: colors[3], + }), hlayout([ this.currentRole = text({ text: "当前:", @@ -164,16 +180,55 @@ class GoBangVM extends ViewModel{ msg: `恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`, }).then(() => { this.updateState(s => { - s.matrix.clear() - s.role = 'black' + s.reset() }) }) } - }) } } }) + vh.gameMode.onClick = () => { + popover(context).show(vlayout([ + ...[ + { + label: "黑方:人 白方:人", + mode: GameMode.P2P, + }, + { + label: "黑方:人 白方:机", + mode: GameMode.P2C, + }, + { + label: "黑方:机 白方:人", + mode: GameMode.C2P, + }, + ].map((e) => text({ + text: e.label, + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().just(), + height: 50, + width: 300, + backgroundColor: (state.gameMode === e.mode) ? Color.parse('#636e72') : Color.parse('#b2bec3'), + onClick: () => { + this.updateState(s => { + s.gameMode = e.mode + s.reset() + }) + popover(context).dismiss() + }, + })) + ]) + .apply({ + layoutConfig: layoutConfig().most(), + onClick: () => { + popover(context).dismiss() + }, + gravity: Gravity.Center, + } as IVLayout) + ) + } } onBind(state: GoBangState, vh: GoBangVH) { @@ -223,6 +278,7 @@ class GoBangVM extends ViewModel{ } }) vh.currentRole.text = `当前: ${(state.role === 'black') ? "黑方" : "白方"}` + vh.gameMode.text = `游戏模式: 黑方 ${state.gameMode === GameMode.C2P ? "机" : "人"} 白方 ${state.gameMode === GameMode.P2C ? "机" : "人"}` } checkResult(pos: number) { @@ -339,7 +395,13 @@ class Gobang extends VMPanel { count, gap: this.getRootView().width / 14, role: "black", - matrix: new Map + matrix: new Map, + gameMode: GameMode.P2P, + reset: function () { + this.matrix.clear() + this.role = "black" + this.anchor = undefined + } } } getViewHolderClass() { From 84ea697eb2eb82a8206b9d7c9c2c6150cba9a007 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Mon, 16 Dec 2019 17:28:50 +0800 Subject: [PATCH 25/35] current support random play --- src/Gobang.ts | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 2309ef93..341b9f50 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -46,7 +46,6 @@ interface GoBangState { matrix: Map anchor?: number gameMode: GameMode - reset: () => void } class GoBangVH extends ViewHolder { @@ -180,9 +179,15 @@ class GoBangVM extends ViewModel{ msg: `恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`, }).then(() => { this.updateState(s => { - s.reset() + this.reset(s) }) }) + } else { + if (it.role === 'black' && it.gameMode === GameMode.C2P) { + this.computeNextStep(it) + } else if (it.role === 'white' && it.gameMode === GameMode.P2C) { + this.computeNextStep(it) + } } }) } @@ -214,7 +219,7 @@ class GoBangVM extends ViewModel{ onClick: () => { this.updateState(s => { s.gameMode = e.mode - s.reset() + this.reset(s) }) popover(context).dismiss() }, @@ -231,6 +236,25 @@ class GoBangVM extends ViewModel{ } } + computeNextStep(it: GoBangState) { + let x = 0, y = 0 + do { + x = Math.floor(Math.random() * count) + y = Math.floor(Math.random() * count) + } while (it.matrix.get(x * count + y) === State.Unspecified) + this.updateState(state => { + state.matrix.set(x * count + y, state.role === 'black' ? State.BLACK : State.WHITE) + state.role = state.role === 'black' ? 'white' : 'black' + }) + } + reset(it: GoBangState) { + it.matrix.clear() + it.role = "black" + it.anchor = undefined + if (it.gameMode === GameMode.C2P) { + this.computeNextStep(it) + } + } onBind(state: GoBangState, vh: GoBangVH) { vh.targetZone.forEach((v, idx) => { const zoneState = state.matrix.get(idx) @@ -397,11 +421,6 @@ class Gobang extends VMPanel { role: "black", matrix: new Map, gameMode: GameMode.P2P, - reset: function () { - this.matrix.clear() - this.role = "black" - this.anchor = undefined - } } } getViewHolderClass() { From 4a5cb1739f1493df4b301b6ac95f58c0a966bcdd Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 17 Dec 2019 15:45:00 +0800 Subject: [PATCH 26/35] add ai --- src/Gobang.ts | 185 ++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 172 insertions(+), 13 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 341b9f50..2a17f43c 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -1,7 +1,152 @@ import { Stack, hlayout, Group, Color, stack, layoutConfig, LayoutSpec, vlayout, IVLayout, Text, ViewHolder, ViewModel, VMPanel, scroller, modal, text, gravity, Gravity, IHLayout, takeNonNull, View, log, popover } from "doric"; import { colors } from "./utils"; +enum State { + Unspecified, + BLACK, + WHITE, +} +const count = 13 + + +class AIComputer { + wins: Array>> = new Array(count).fill(0).map(_ => new Array(count).fill(0).map(_ => [])); + winCount = 0 + blackWins: number[] + whiteWins: number[] + constructor() { + for (let y = 0; y < count; y++) { + for (let x = 0; x < count - 4; x++) { + for (let k = 0; k < 5; k++) { + this.wins[x + k][y][this.winCount] = true; + } + this.winCount++; + } + } + + for (let x = 0; x < count; x++) { + for (let y = 0; y < count - 4; y++) { + for (let k = 0; k < 5; k++) { + this.wins[x][y + k][this.winCount] = true; + } + this.winCount++; + } + } + + for (let x = 0; x < count - 4; x++) { + for (let y = 0; y < count - 4; y++) { + for (let k = 0; k < 5; k++) { + this.wins[x + k][y + k][this.winCount] = true; + } + this.winCount++; + } + } + + for (let x = 0; x < count - 4; x++) { + for (let y = count - 1; y > 3; y--) { + for (let k = 0; k < 5; k++) { + this.wins[x + k][y - k][this.winCount] = true; + } + this.winCount++; + } + } + this.blackWins = new Array(this.winCount).fill(0) + this.whiteWins = new Array(this.winCount).fill(0) + } + + + oneStep(idx: number, role: State.BLACK | State.WHITE) { + const { x, y } = this.index2Position(idx) + for (let loop = 0; loop < this.winCount; loop++) { + if (this.wins[x][y][loop]) { + if (role === State.BLACK) { + this.blackWins[loop] += 1 + } else { + this.whiteWins[loop] += 1 + } + } + } + } + + index2Position(idx: number) { + const x = idx % count + const y = Math.floor(idx / count) + return { x, y } + } + + compute(matrix: State[], role: State.BLACK | State.WHITE) { + const myScore = new Array(matrix.length).fill(0) + const rivalScore = new Array(matrix.length).fill(0) + const myWins = role === State.BLACK ? this.blackWins : this.whiteWins + const rivalWins = role === State.BLACK ? this.whiteWins : this.blackWins + let max = 0 + let retIdx = 0 + matrix.forEach((state, idx) => { + if (state != State.Unspecified) { + return + } + const { x, y } = this.index2Position(idx) + for (let loop = 0; loop < this.winCount; loop++) { + if (this.wins[x][y][loop]) { + switch (rivalWins[loop]) { + case 1: + rivalScore[idx] += 200 + break + case 2: + rivalScore[idx] += 400 + break + case 3: + rivalScore[idx] += 2000 + break + case 4: + rivalScore[idx] += 10000 + break + default: + break + } + + switch (myWins[loop]) { + case 1: + myScore[idx] += 220 + break + case 2: + myScore[idx] += 420 + break + case 3: + myScore[idx] += 2200 + break + case 4: + myScore[idx] += 20000 + break + default: + break + } + } + } + if (rivalScore[idx] > max) { + max = rivalScore[idx]; + retIdx = idx + } else if (rivalScore[idx] == max) { + if (myScore[idx] > myScore[retIdx]) { + retIdx = idx + } + } + + if (myScore[idx] > max) { + max = myScore[idx] + retIdx = idx + } else if (myScore[idx] == max) { + if (rivalScore[idx] > rivalScore[retIdx]) { + retIdx = idx + } + } + + + }) + return retIdx + } +} const lineColor = Color.BLACK function columLine() { return (new Stack).apply({ @@ -26,13 +171,6 @@ function pointer(size: number) { height: size, }) } - -const count = 13 -enum State { - Unspecified, - BLACK, - WHITE, -} enum GameMode { P2P, P2C, @@ -150,6 +288,7 @@ class GoBangVH extends ViewHolder { } class GoBangVM extends ViewModel{ + computer!: AIComputer onAttached(state: GoBangState, vh: GoBangVH) { vh.actualBuild(state) vh.targetZone.forEach((e, idx) => { @@ -168,9 +307,15 @@ class GoBangVM extends ViewModel{ if (it.role === 'black') { it.matrix.set(idx, State.BLACK) it.role = 'white' + if (this.computer) { + this.computer.oneStep(idx, State.BLACK) + } } else { it.matrix.set(idx, State.WHITE) it.role = 'black' + if (this.computer) { + this.computer.oneStep(idx, State.WHITE) + } } it.anchor = undefined if (this.checkResult(idx)) { @@ -235,22 +380,36 @@ class GoBangVM extends ViewModel{ ) } } - computeNextStep(it: GoBangState) { - let x = 0, y = 0 + const tempMatrix: State[] = new Array(count * count).fill(0).map((_, idx) => { + return it.matrix.get(idx) || State.Unspecified + }) + let idx = 0 do { - x = Math.floor(Math.random() * count) - y = Math.floor(Math.random() * count) - } while (it.matrix.get(x * count + y) === State.Unspecified) + idx = this.computer.compute(tempMatrix, it.role === 'black' ? State.BLACK : State.WHITE) + } while (it.matrix.get(idx) === State.Unspecified) + this.computer.oneStep(idx, it.role === 'black' ? State.BLACK : State.WHITE) this.updateState(state => { - state.matrix.set(x * count + y, state.role === 'black' ? State.BLACK : State.WHITE) + state.matrix.set(idx, state.role === 'black' ? State.BLACK : State.WHITE) state.role = state.role === 'black' ? 'white' : 'black' }) + if (this.checkResult(idx)) { + modal(context).alert({ + title: "游戏结束", + msg: `恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`, + }).then(() => { + this.updateState(s => { + this.reset(s) + }) + }) + } } + reset(it: GoBangState) { it.matrix.clear() it.role = "black" it.anchor = undefined + this.computer = new AIComputer if (it.gameMode === GameMode.C2P) { this.computeNextStep(it) } From d7a95b5958e477a59b50e61913196c7f74a249ad Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 17 Dec 2019 16:02:14 +0800 Subject: [PATCH 27/35] update ai --- src/Gobang.ts | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 2a17f43c..ab916106 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -11,7 +11,7 @@ const count = 13 class AIComputer { - wins: Array>> = new Array(count).fill(0).map(_ => new Array(count).fill(0).map(_ => [])); + wins: Array>> = new Array(count).fill(0).map(_ => new Array(count).fill(0).map(_ => [])) winCount = 0 blackWins: number[] whiteWins: number[] @@ -411,7 +411,10 @@ class GoBangVM extends ViewModel{ it.anchor = undefined this.computer = new AIComputer if (it.gameMode === GameMode.C2P) { - this.computeNextStep(it) + const idx = Math.floor(Math.random() * count) * count + Math.floor(Math.random() * count) + this.computer.oneStep(idx, State.BLACK) + it.matrix.set(idx, State.BLACK) + it.role = 'white' } } onBind(state: GoBangState, vh: GoBangVH) { From 2850f2a4368e83e5c1c80b3c29fc792c42d5e0c4 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 17 Dec 2019 16:39:59 +0800 Subject: [PATCH 28/35] upgrade ai --- src/Gobang.ts | 177 +++++++++++++++++++++++++++++--------------------- 1 file changed, 103 insertions(+), 74 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index ab916106..70a87b1f 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -11,15 +11,19 @@ const count = 13 class AIComputer { - wins: Array>> = new Array(count).fill(0).map(_ => new Array(count).fill(0).map(_ => [])) + wins: Array> = [] winCount = 0 - blackWins: number[] - whiteWins: number[] - constructor() { + matrix: Map + constructor(matrix: Map) { + this.matrix = matrix for (let y = 0; y < count; y++) { for (let x = 0; x < count - 4; x++) { + this.wins.push([]) for (let k = 0; k < 5; k++) { - this.wins[x + k][y][this.winCount] = true; + this.wins[this.winCount].push({ + x: x + k, + y, + }) } this.winCount++; } @@ -27,8 +31,12 @@ class AIComputer { for (let x = 0; x < count; x++) { for (let y = 0; y < count - 4; y++) { + this.wins.push([]) for (let k = 0; k < 5; k++) { - this.wins[x][y + k][this.winCount] = true; + this.wins[this.winCount].push({ + x, + y: y + k, + }) } this.winCount++; } @@ -36,8 +44,12 @@ class AIComputer { for (let x = 0; x < count - 4; x++) { for (let y = 0; y < count - 4; y++) { + this.wins.push([]) for (let k = 0; k < 5; k++) { - this.wins[x + k][y + k][this.winCount] = true; + this.wins[this.winCount].push({ + x: x + k, + y: y + k, + }) } this.winCount++; } @@ -45,28 +57,16 @@ class AIComputer { for (let x = 0; x < count - 4; x++) { for (let y = count - 1; y > 3; y--) { + this.wins.push([]) for (let k = 0; k < 5; k++) { - this.wins[x + k][y - k][this.winCount] = true; + this.wins[this.winCount].push({ + x: x + k, + y: y - k, + }) } this.winCount++; } } - this.blackWins = new Array(this.winCount).fill(0) - this.whiteWins = new Array(this.winCount).fill(0) - } - - - oneStep(idx: number, role: State.BLACK | State.WHITE) { - const { x, y } = this.index2Position(idx) - for (let loop = 0; loop < this.winCount; loop++) { - if (this.wins[x][y][loop]) { - if (role === State.BLACK) { - this.blackWins[loop] += 1 - } else { - this.whiteWins[loop] += 1 - } - } - } } index2Position(idx: number) { @@ -74,6 +74,41 @@ class AIComputer { const y = Math.floor(idx / count) return { x, y } } + get blackWins() { + return this.wins.map((win) => { + let idx = 0 + for (let e of win) { + switch (this.matrix.get(e.x + e.y * count)) { + case State.BLACK: + idx++ + break + case State.WHITE: + return 0 + default: + break + } + } + return idx + }) + } + + get whiteWins() { + return this.wins.map((win) => { + let count = 0 + for (let e of win) { + switch (this.matrix.get(e.x + e.y * count)) { + case State.WHITE: + count++ + break + case State.BLACK: + return 0 + default: + break + } + } + return count + }) + } compute(matrix: State[], role: State.BLACK | State.WHITE) { const myScore = new Array(matrix.length).fill(0) @@ -86,44 +121,44 @@ class AIComputer { if (state != State.Unspecified) { return } - const { x, y } = this.index2Position(idx) - for (let loop = 0; loop < this.winCount; loop++) { - if (this.wins[x][y][loop]) { - switch (rivalWins[loop]) { - case 1: - rivalScore[idx] += 200 - break - case 2: - rivalScore[idx] += 400 - break - case 3: - rivalScore[idx] += 2000 - break - case 4: - rivalScore[idx] += 10000 - break - default: - break - } - - switch (myWins[loop]) { - case 1: - myScore[idx] += 220 - break - case 2: - myScore[idx] += 420 - break - case 3: - myScore[idx] += 2200 - break - case 4: - myScore[idx] += 20000 - break - default: - break - } + this.wins.forEach((e, winIdx) => { + if (e.filter(e => (e.x + e.y * count) === idx).length === 0) { + return } - } + switch (rivalWins[winIdx]) { + case 1: + rivalScore[idx] += 200 + break + case 2: + rivalScore[idx] += 400 + break + case 3: + rivalScore[idx] += 2000 + break + case 4: + rivalScore[idx] += 10000 + break + default: + break + } + + switch (myWins[winIdx]) { + case 1: + myScore[idx] += 220 + break + case 2: + myScore[idx] += 420 + break + case 3: + myScore[idx] += 2200 + break + case 4: + myScore[idx] += 20000 + break + default: + break + } + }) if (rivalScore[idx] > max) { max = rivalScore[idx]; retIdx = idx @@ -141,8 +176,6 @@ class AIComputer { retIdx = idx } } - - }) return retIdx } @@ -307,15 +340,9 @@ class GoBangVM extends ViewModel{ if (it.role === 'black') { it.matrix.set(idx, State.BLACK) it.role = 'white' - if (this.computer) { - this.computer.oneStep(idx, State.BLACK) - } } else { it.matrix.set(idx, State.WHITE) it.role = 'black' - if (this.computer) { - this.computer.oneStep(idx, State.WHITE) - } } it.anchor = undefined if (this.checkResult(idx)) { @@ -329,9 +356,13 @@ class GoBangVM extends ViewModel{ }) } else { if (it.role === 'black' && it.gameMode === GameMode.C2P) { - this.computeNextStep(it) + setTimeout(() => { + this.computeNextStep(it) + }, 0) } else if (it.role === 'white' && it.gameMode === GameMode.P2C) { - this.computeNextStep(it) + setTimeout(() => { + this.computeNextStep(it) + }, 0) } } }) @@ -388,7 +419,6 @@ class GoBangVM extends ViewModel{ do { idx = this.computer.compute(tempMatrix, it.role === 'black' ? State.BLACK : State.WHITE) } while (it.matrix.get(idx) === State.Unspecified) - this.computer.oneStep(idx, it.role === 'black' ? State.BLACK : State.WHITE) this.updateState(state => { state.matrix.set(idx, state.role === 'black' ? State.BLACK : State.WHITE) state.role = state.role === 'black' ? 'white' : 'black' @@ -409,10 +439,9 @@ class GoBangVM extends ViewModel{ it.matrix.clear() it.role = "black" it.anchor = undefined - this.computer = new AIComputer + this.computer = new AIComputer(it.matrix) if (it.gameMode === GameMode.C2P) { const idx = Math.floor(Math.random() * count) * count + Math.floor(Math.random() * count) - this.computer.oneStep(idx, State.BLACK) it.matrix.set(idx, State.BLACK) it.role = 'white' } From 78d1b5d929e0e355cc46610fa4f9dd06dd406294 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 17 Dec 2019 16:52:43 +0800 Subject: [PATCH 29/35] fix ai --- src/Gobang.ts | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 70a87b1f..fcf528c3 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -69,11 +69,6 @@ class AIComputer { } } - index2Position(idx: number) { - const x = idx % count - const y = Math.floor(idx / count) - return { x, y } - } get blackWins() { return this.wins.map((win) => { let idx = 0 @@ -94,11 +89,11 @@ class AIComputer { get whiteWins() { return this.wins.map((win) => { - let count = 0 + let idx = 0 for (let e of win) { switch (this.matrix.get(e.x + e.y * count)) { case State.WHITE: - count++ + idx++ break case State.BLACK: return 0 @@ -106,7 +101,7 @@ class AIComputer { break } } - return count + return idx }) } @@ -323,6 +318,9 @@ class GoBangVH extends ViewHolder { class GoBangVM extends ViewModel{ computer!: AIComputer onAttached(state: GoBangState, vh: GoBangVH) { + if (!this.computer) { + this.computer = new AIComputer(state.matrix) + } vh.actualBuild(state) vh.targetZone.forEach((e, idx) => { e.onClick = () => { @@ -611,7 +609,7 @@ class Gobang extends VMPanel { gap: this.getRootView().width / 14, role: "black", matrix: new Map, - gameMode: GameMode.P2P, + gameMode: GameMode.P2C, } } getViewHolderClass() { From 81da004341da6c4d17216fc7a15c658c97ce7088 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 17 Dec 2019 17:01:21 +0800 Subject: [PATCH 30/35] update ai --- src/Gobang.ts | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index fcf528c3..ca89403b 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -122,13 +122,13 @@ class AIComputer { } switch (rivalWins[winIdx]) { case 1: - rivalScore[idx] += 200 + rivalScore[idx] += 1 break case 2: - rivalScore[idx] += 400 + rivalScore[idx] += 10 break case 3: - rivalScore[idx] += 2000 + rivalScore[idx] += 100 break case 4: rivalScore[idx] += 10000 @@ -139,13 +139,13 @@ class AIComputer { switch (myWins[winIdx]) { case 1: - myScore[idx] += 220 + myScore[idx] += 2 break case 2: - myScore[idx] += 420 + myScore[idx] += 20 break case 3: - myScore[idx] += 2200 + myScore[idx] += 200 break case 4: myScore[idx] += 20000 From 723636c90278d3603c5c3610c5e13448227ce66c Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 17 Dec 2019 17:29:36 +0800 Subject: [PATCH 31/35] feat:optimize --- src/Gobang.ts | 69 +++++++++++++++++++++++++++++++++++++-------------- 1 file changed, 50 insertions(+), 19 deletions(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index ca89403b..6d6b38f1 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -212,6 +212,7 @@ interface GoBangState { matrix: Map anchor?: number gameMode: GameMode + gameState: "blackWin" | "whiteWin" | "idle" } class GoBangVH extends ViewHolder { @@ -324,6 +325,9 @@ class GoBangVM extends ViewModel{ vh.actualBuild(state) vh.targetZone.forEach((e, idx) => { e.onClick = () => { + if (state.gameState !== 'idle') { + return + } const zoneState = state.matrix.get(idx) if (zoneState === State.BLACK || zoneState === State.WHITE) { modal(context).toast('This position had been token.') @@ -344,14 +348,8 @@ class GoBangVM extends ViewModel{ } it.anchor = undefined if (this.checkResult(idx)) { - modal(context).alert({ - title: "游戏结束", - msg: `恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`, - }).then(() => { - this.updateState(s => { - this.reset(s) - }) - }) + modal(context).toast(`恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`) + it.gameState = it.role === 'white' ? 'blackWin' : 'whiteWin' } else { if (it.role === 'black' && it.gameMode === GameMode.C2P) { setTimeout(() => { @@ -408,6 +406,30 @@ class GoBangVM extends ViewModel{ } as IVLayout) ) } + vh.result.onClick = () => { + switch (state.gameState) { + case "idle": + this.updateState(state => { + this.reset(state) + }) + break + case "blackWin": + case "whiteWin": + break + } + } + vh.currentRole.onClick = () => { + switch (state.gameState) { + case "idle": + break + case "blackWin": + case "whiteWin": + this.updateState(state => { + this.reset(state) + }) + break + } + } } computeNextStep(it: GoBangState) { const tempMatrix: State[] = new Array(count * count).fill(0).map((_, idx) => { @@ -420,21 +442,16 @@ class GoBangVM extends ViewModel{ this.updateState(state => { state.matrix.set(idx, state.role === 'black' ? State.BLACK : State.WHITE) state.role = state.role === 'black' ? 'white' : 'black' + if (this.checkResult(idx)) { + modal(context).toast(`恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`) + it.gameState = it.role === 'white' ? 'blackWin' : 'whiteWin' + } }) - if (this.checkResult(idx)) { - modal(context).alert({ - title: "游戏结束", - msg: `恭喜获胜方${it.role === 'white' ? "黑方" : "白方"}`, - }).then(() => { - this.updateState(s => { - this.reset(s) - }) - }) - } } reset(it: GoBangState) { it.matrix.clear() + it.gameState = 'idle' it.role = "black" it.anchor = undefined this.computer = new AIComputer(it.matrix) @@ -490,8 +507,21 @@ class GoBangVM extends ViewModel{ }) } }) - vh.currentRole.text = `当前: ${(state.role === 'black') ? "黑方" : "白方"}` vh.gameMode.text = `游戏模式: 黑方 ${state.gameMode === GameMode.C2P ? "机" : "人"} 白方 ${state.gameMode === GameMode.P2C ? "机" : "人"}` + switch (state.gameState) { + case "idle": + vh.result.text = "重新开始" + vh.currentRole.text = `当前: ${(state.role === 'black') ? "黑方" : "白方"}` + break + case "blackWin": + vh.result.text = "黑方获胜" + vh.currentRole.text = "重新开始" + break + case "whiteWin": + vh.result.text = "白方获胜" + vh.currentRole.text = "重新开始" + break + } } checkResult(pos: number) { @@ -610,6 +640,7 @@ class Gobang extends VMPanel { role: "black", matrix: new Map, gameMode: GameMode.P2C, + gameState: "idle" } } getViewHolderClass() { From 2ccb2193d0bb0eb220fdbf2564461544856ca8e6 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Tue, 17 Dec 2019 17:50:51 +0800 Subject: [PATCH 32/35] feat:add assistant --- src/Gobang.ts | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/src/Gobang.ts b/src/Gobang.ts index 6d6b38f1..d1563c32 100644 --- a/src/Gobang.ts +++ b/src/Gobang.ts @@ -222,6 +222,7 @@ class GoBangVH extends ViewHolder { result!: Text targetZone: View[] = [] gameMode!: Text + assistant!: Text build(root: Group): void { this.root = root } @@ -285,7 +286,7 @@ class GoBangVH extends ViewHolder { textColor: Color.WHITE, layoutConfig: layoutConfig().most().configHeight(LayoutSpec.JUST), height: 50, - backgroundColor: colors[3], + backgroundColor: colors[8], }), hlayout([ this.currentRole = text({ @@ -307,6 +308,14 @@ class GoBangVH extends ViewHolder { ]).apply({ layoutConfig: layoutConfig().fit().configWidth(LayoutSpec.MOST), } as IHLayout), + this.assistant = text({ + text: "提示", + textSize: 20, + textColor: Color.WHITE, + layoutConfig: layoutConfig().just().configWidth(LayoutSpec.MOST), + height: 50, + backgroundColor: colors[3], + }), ]) .apply({ layoutConfig: layoutConfig().fit(), @@ -430,6 +439,25 @@ class GoBangVM extends ViewModel{ break } } + vh.assistant.onClick = () => { + const it = this.getState() + if (it.gameState !== 'idle') { + return + } + this.computeNextStep(it) + if (it.gameState !== 'idle') { + return + } + if (it.role === 'black' && it.gameMode === GameMode.C2P) { + setTimeout(() => { + this.computeNextStep(it) + }, 0) + } else if (it.role === 'white' && it.gameMode === GameMode.P2C) { + setTimeout(() => { + this.computeNextStep(it) + }, 0) + } + } } computeNextStep(it: GoBangState) { const tempMatrix: State[] = new Array(count * count).fill(0).map((_, idx) => { From 4a8769684c1df71633ff4693ca2363ebdf217128 Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Wed, 18 Dec 2019 15:28:32 +0800 Subject: [PATCH 33/35] update rollup config --- index.ts | 19 +------------ rollup.config.js | 69 ++++++++++++++++++++++++++++++++++++------------ 2 files changed, 53 insertions(+), 35 deletions(-) diff --git a/index.ts b/index.ts index fade3a4a..5f778ea2 100644 --- a/index.ts +++ b/index.ts @@ -1,24 +1,7 @@ export default [ 'src/Counter', 'src/Snake', - 'src/ListDemo', - 'src/ScrollerDemo', - 'src/SliderDemo', - 'src/LayoutDemo', - 'src/EffectsDemo', - 'src/ImageDemo', - 'src/ModalDemo', - 'src/NetworkDemo', - 'src/StorageDemo', - 'src/NavigatorDemo', - 'src/NavbarDemo', - 'src/RefreshableDemo', - 'src/FlowLayoutDemo', - 'src/PopoverDemo', - 'src/AnimatorDemo', 'src/ComplicatedAnimations', - 'src/ComplicatedDemo', - 'src/InputDemo', - 'src/StickDemo', + 'src/.*Demo', 'src/Gobang', ] \ No newline at end of file diff --git a/rollup.config.js b/rollup.config.js index 3e5b5b75..85dd2275 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,23 +1,58 @@ import resolve from 'rollup-plugin-node-resolve' import commonjs from 'rollup-plugin-commonjs' import bundles from './build/index' +import fs from 'fs' +import path from 'path' -export default bundles.map(bundle => { - return { - input: `build/${bundle}.js`, - output: { - format: "cjs", - file: `bundle/${bundle}.js`, - sourcemap: true, - }, - plugins: [ - resolve({ mainFields: ["jsnext"] }), - commonjs() - ], - external: ['reflect-metadata', 'doric'], - onwarn: function (warning) { - if (warning.code === 'THIS_IS_UNDEFINED') { return; } - console.warn(warning.message); +function readDirs(dirPath, files) { + if (fs.statSync(dirPath).isDirectory()) { + fs.readdirSync(dirPath).forEach(e => { + readDirs(path.join(dirPath, e), files) + }) + } else { + for (let bundle of bundles) { + if (dirPath.match(new RegExp(`^${bundle}`))) { + files.push(dirPath) + } } } -}) \ No newline at end of file +} + + +const dirs = fs.readdirSync('.') + .filter(e => { + for (let bundle of bundles) { + if (bundle.match(new RegExp(`^${e}/`))) { + return true + } + } + return false + }) + +const allFiles = [] + +dirs.forEach(e => { + readDirs(e, allFiles) +}) + +export default allFiles + .map(e => e.replace('.ts', '')) + .map(bundle => { + return { + input: `build/${bundle}.js`, + output: { + format: "cjs", + file: `bundle/${bundle}.js`, + sourcemap: true, + }, + plugins: [ + resolve({ mainFields: ["jsnext"] }), + commonjs() + ], + external: ['reflect-metadata', 'doric'], + onwarn: function (warning) { + if (warning.code === 'THIS_IS_UNDEFINED') { return; } + console.warn(warning.message); + } + } + }) \ No newline at end of file From c76274b76255560e051270f6a803ec822be8605f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=8A=B2=E9=B9=8F?= Date: Fri, 20 Dec 2019 11:19:30 +0800 Subject: [PATCH 34/35] update rollup & rollup plugin node resolve --- package-lock.json | 128 +++++++++++++++++++++++----------------------- package.json | 4 +- rollup.config.js | 2 +- 3 files changed, 67 insertions(+), 67 deletions(-) diff --git a/package-lock.json b/package-lock.json index b074ffed..36c4f6a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,15 +4,35 @@ "lockfileVersion": 1, "requires": true, "dependencies": { + "@rollup/plugin-node-resolve": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-6.0.0.tgz", + "integrity": "sha512-GqWz1CfXOsqpeVMcoM315+O7zMxpRsmhWyhJoxLFHVSp9S64/u02i7len/FnbTNbmgYs+sZyilasijH8UiuboQ==", + "requires": { + "@rollup/pluginutils": "^3.0.0", + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1" + } + }, + "@rollup/pluginutils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.0.tgz", + "integrity": "sha512-qBbGQQaUUiId/lBU9VMeYlVLOoRNvz1fV8HWY5tiGDpI2gdPZHbmOfCjzSdXPhdq3XOfyWvXEBlIPbnM3+9ogQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, "@types/estree": { "version": "0.0.40", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" }, "@types/node": { - "version": "12.12.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", - "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" + "version": "12.12.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", + "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" }, "@types/resolve": { "version": "0.0.8", @@ -35,24 +55,44 @@ "doric": { "version": "file:../doric-js", "requires": { + "@rollup/plugin-node-resolve": "^6.0.0", "@types/ws": "^6.0.4", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.10", - "rollup-plugin-node-resolve": "^5.2.0", + "rollup": "^1.27.13", "tslib": "^1.10.0", "typescript": "^3.7.3", - "ws": "^7.2.0" + "ws": "^7.2.1" }, "dependencies": { + "@rollup/plugin-node-resolve": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-6.0.0.tgz", + "integrity": "sha512-GqWz1CfXOsqpeVMcoM315+O7zMxpRsmhWyhJoxLFHVSp9S64/u02i7len/FnbTNbmgYs+sZyilasijH8UiuboQ==", + "requires": { + "@rollup/pluginutils": "^3.0.0", + "@types/resolve": "0.0.8", + "builtin-modules": "^3.1.0", + "is-module": "^1.0.0", + "resolve": "^1.11.1" + } + }, + "@rollup/pluginutils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-3.0.0.tgz", + "integrity": "sha512-qBbGQQaUUiId/lBU9VMeYlVLOoRNvz1fV8HWY5tiGDpI2gdPZHbmOfCjzSdXPhdq3XOfyWvXEBlIPbnM3+9ogQ==", + "requires": { + "estree-walker": "^0.6.1" + } + }, "@types/estree": { "version": "0.0.40", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-0.0.40.tgz", "integrity": "sha512-p3KZgMto/JyxosKGmnLDJ/dG5wf+qTRMUjHJcspC2oQKa4jP7mz+tv0ND56lLBu3ojHlhzY33Ol+khLyNmilkA==" }, "@types/node": { - "version": "12.12.17", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.17.tgz", - "integrity": "sha512-Is+l3mcHvs47sKy+afn2O1rV4ldZFU7W8101cNlOd+MRbjM4Onida8jSZnJdTe/0Pcf25g9BNIUsuugmE6puHA==" + "version": "12.12.21", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.21.tgz", + "integrity": "sha512-8sRGhbpU+ck1n0PGAUgVrWrWdjSW2aqNeyC15W88GRsMpSwzv6RJGlLhE7s2RhVSOdyDmxbqlWSeThq4/7xqlA==" }, "@types/resolve": { "version": "0.0.8", @@ -75,11 +115,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.1.0.tgz", "integrity": "sha512-kL5CuoXA/dgxlBbVrflsflzQ3PAas7RYZB52NOm/6839iVYJgKMJ3cQJD+t2i5+qFa8h3MDpEOJiS64E8JLnSQ==" }, - "async-limiter": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz", - "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==" - }, "builtin-modules": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.1.0.tgz", @@ -106,43 +141,23 @@ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, "resolve": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", - "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", + "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", "requires": { "path-parse": "^1.0.6" } }, "rollup": { - "version": "1.27.12", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.12.tgz", - "integrity": "sha512-51iR7n6NQfdQJlRrIktaGmkdt395A8Vue7CdnlrK6UhY9DY2GaKsTdljWeXisJuZh+w90Gz8VFNh5X+yxP20oQ==", + "version": "1.27.13", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.13.tgz", + "integrity": "sha512-hDi7M07MpmNSDE8YVwGVFA8L7n8jTLJ4lG65nMAijAyqBe//rtu4JdxjUBE7JqXfdpqxqDTbCDys9WcqdpsQvw==", "requires": { "@types/estree": "*", "@types/node": "*", "acorn": "^7.1.0" } }, - "rollup-plugin-node-resolve": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", - "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", - "requires": { - "@types/resolve": "0.0.8", - "builtin-modules": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.11.1", - "rollup-pluginutils": "^2.8.1" - } - }, - "rollup-pluginutils": { - "version": "2.8.2", - "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", - "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", - "requires": { - "estree-walker": "^0.6.1" - } - }, "tslib": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.10.0.tgz", @@ -154,12 +169,9 @@ "integrity": "sha512-Mcr/Qk7hXqFBXMN7p7Lusj1ktCBydylfQM/FZCk5glCNQJrCUKPkMHdo9R0MTFWsC/4kPFvDS0fDPvukfCkFsw==" }, "ws": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.0.tgz", - "integrity": "sha512-+SqNqFbwTm/0DC18KYzIsMTnEWpLwJsiasW/O17la4iDRRIO9uaHbvKiAS3AHgTiuuWerK/brj4O6MYZkei9xg==", - "requires": { - "async-limiter": "^1.0.0" - } + "version": "7.2.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.2.1.tgz", + "integrity": "sha512-sucePNSafamSKoOqoNfBd8V0StlkzJKL2ZAhGQinCfNQ+oacw+Pk7lcdAElecBF2VkLNZRiIb5Oi1Q5lVUVt2A==" } } }, @@ -207,17 +219,17 @@ "integrity": "sha512-Ts1Y/anZELhSsjMcU605fU9RE4Oi3p5ORujwbIKXfWa+0Zxs510Qrmrce5/Jowq3cHSZSJqBjypxmHarc+vEWg==" }, "resolve": { - "version": "1.13.1", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.13.1.tgz", - "integrity": "sha512-CxqObCX8K8YtAhOBRg+lrcdn+LK+WYOS8tSjqSFbjtrI5PnS63QPhZl4+yKfrU9tdsbMu9Anr/amegT87M9Z6w==", + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.14.1.tgz", + "integrity": "sha512-fn5Wobh4cxbLzuHaE+nphztHy43/b++4M6SsGFC2gB8uYwf0C8LcarfCz1un7UTW8OFQg9iNjZ4xpcFVGebDPg==", "requires": { "path-parse": "^1.0.6" } }, "rollup": { - "version": "1.27.12", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.12.tgz", - "integrity": "sha512-51iR7n6NQfdQJlRrIktaGmkdt395A8Vue7CdnlrK6UhY9DY2GaKsTdljWeXisJuZh+w90Gz8VFNh5X+yxP20oQ==", + "version": "1.27.13", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.13.tgz", + "integrity": "sha512-hDi7M07MpmNSDE8YVwGVFA8L7n8jTLJ4lG65nMAijAyqBe//rtu4JdxjUBE7JqXfdpqxqDTbCDys9WcqdpsQvw==", "requires": { "@types/estree": "*", "@types/node": "*", @@ -236,18 +248,6 @@ "rollup-pluginutils": "^2.8.1" } }, - "rollup-plugin-node-resolve": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/rollup-plugin-node-resolve/-/rollup-plugin-node-resolve-5.2.0.tgz", - "integrity": "sha512-jUlyaDXts7TW2CqQ4GaO5VJ4PwwaV8VUGA7+km3n6k6xtOEacf61u0VXwN80phY/evMcaS+9eIeJ9MOyDxt5Zw==", - "requires": { - "@types/resolve": "0.0.8", - "builtin-modules": "^3.1.0", - "is-module": "^1.0.0", - "resolve": "^1.11.1", - "rollup-pluginutils": "^2.8.1" - } - }, "rollup-pluginutils": { "version": "2.8.2", "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", diff --git a/package.json b/package.json index c8f9338a..46e11717 100644 --- a/package.json +++ b/package.json @@ -12,9 +12,9 @@ "dependencies": { "doric": "file:../doric-js", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.12", + "rollup": "^1.27.13", "rollup-plugin-commonjs": "^10.1.0", - "rollup-plugin-node-resolve": "^5.2.0", + "@rollup/plugin-node-resolve": "^6.0.0", "tslib": "^1.10.0", "typescript": "^3.7.3" } diff --git a/rollup.config.js b/rollup.config.js index 85dd2275..cc4cd96d 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,4 +1,4 @@ -import resolve from 'rollup-plugin-node-resolve' +import resolve from '@rollup/plugin-node-resolve' import commonjs from 'rollup-plugin-commonjs' import bundles from './build/index' import fs from 'fs' From 5fcba0a28bce0aea0900988c22dfdde30704b44e Mon Sep 17 00:00:00 2001 From: "pengfei.zhou" Date: Sat, 21 Dec 2019 22:07:15 +0800 Subject: [PATCH 35/35] rename dir --- .gitignore => doric-demo/.gitignore | 0 {.vscode => doric-demo/.vscode}/launch.json | 0 {.vscode => doric-demo/.vscode}/tasks.json | 0 LICENSE => doric-demo/LICENSE | 0 README.md => doric-demo/README.md | 0 index.ts => doric-demo/index.ts | 0 package-lock.json => doric-demo/package-lock.json | 0 package.json => doric-demo/package.json | 0 rollup.config.js => doric-demo/rollup.config.js | 0 {src => doric-demo/src}/AnimatorDemo.ts | 0 {src => doric-demo/src}/ComplicatedAnimations.ts | 0 {src => doric-demo/src}/ComplicatedDemo.ts | 0 {src => doric-demo/src}/Counter.ts | 0 {src => doric-demo/src}/EffectsDemo.ts | 0 {src => doric-demo/src}/FlowLayoutDemo.ts | 0 {src => doric-demo/src}/Gobang.ts | 0 {src => doric-demo/src}/ImageDemo.ts | 0 {src => doric-demo/src}/InputDemo.ts | 0 {src => doric-demo/src}/LayoutDemo.ts | 0 {src => doric-demo/src}/ListDemo.ts | 0 {src => doric-demo/src}/ModalDemo.ts | 0 {src => doric-demo/src}/NavbarDemo.ts | 0 {src => doric-demo/src}/NavigatorDemo.ts | 0 {src => doric-demo/src}/NetworkDemo.ts | 0 {src => doric-demo/src}/PopoverDemo.ts | 0 {src => doric-demo/src}/RefreshableDemo.ts | 0 {src => doric-demo/src}/ScrollerDemo.ts | 0 {src => doric-demo/src}/SliderDemo.ts | 0 {src => doric-demo/src}/Snake.ts | 0 {src => doric-demo/src}/StickDemo.ts | 0 {src => doric-demo/src}/StorageDemo.ts | 0 {src => doric-demo/src}/image_base64.ts | 0 {src => doric-demo/src}/utils.ts | 0 tsconfig.json => doric-demo/tsconfig.json | 0 34 files changed, 0 insertions(+), 0 deletions(-) rename .gitignore => doric-demo/.gitignore (100%) rename {.vscode => doric-demo/.vscode}/launch.json (100%) rename {.vscode => doric-demo/.vscode}/tasks.json (100%) rename LICENSE => doric-demo/LICENSE (100%) rename README.md => doric-demo/README.md (100%) rename index.ts => doric-demo/index.ts (100%) rename package-lock.json => doric-demo/package-lock.json (100%) rename package.json => doric-demo/package.json (100%) rename rollup.config.js => doric-demo/rollup.config.js (100%) rename {src => doric-demo/src}/AnimatorDemo.ts (100%) rename {src => doric-demo/src}/ComplicatedAnimations.ts (100%) rename {src => doric-demo/src}/ComplicatedDemo.ts (100%) rename {src => doric-demo/src}/Counter.ts (100%) rename {src => doric-demo/src}/EffectsDemo.ts (100%) rename {src => doric-demo/src}/FlowLayoutDemo.ts (100%) rename {src => doric-demo/src}/Gobang.ts (100%) rename {src => doric-demo/src}/ImageDemo.ts (100%) rename {src => doric-demo/src}/InputDemo.ts (100%) rename {src => doric-demo/src}/LayoutDemo.ts (100%) rename {src => doric-demo/src}/ListDemo.ts (100%) rename {src => doric-demo/src}/ModalDemo.ts (100%) rename {src => doric-demo/src}/NavbarDemo.ts (100%) rename {src => doric-demo/src}/NavigatorDemo.ts (100%) rename {src => doric-demo/src}/NetworkDemo.ts (100%) rename {src => doric-demo/src}/PopoverDemo.ts (100%) rename {src => doric-demo/src}/RefreshableDemo.ts (100%) rename {src => doric-demo/src}/ScrollerDemo.ts (100%) rename {src => doric-demo/src}/SliderDemo.ts (100%) rename {src => doric-demo/src}/Snake.ts (100%) rename {src => doric-demo/src}/StickDemo.ts (100%) rename {src => doric-demo/src}/StorageDemo.ts (100%) rename {src => doric-demo/src}/image_base64.ts (100%) rename {src => doric-demo/src}/utils.ts (100%) rename tsconfig.json => doric-demo/tsconfig.json (100%) diff --git a/.gitignore b/doric-demo/.gitignore similarity index 100% rename from .gitignore rename to doric-demo/.gitignore diff --git a/.vscode/launch.json b/doric-demo/.vscode/launch.json similarity index 100% rename from .vscode/launch.json rename to doric-demo/.vscode/launch.json diff --git a/.vscode/tasks.json b/doric-demo/.vscode/tasks.json similarity index 100% rename from .vscode/tasks.json rename to doric-demo/.vscode/tasks.json diff --git a/LICENSE b/doric-demo/LICENSE similarity index 100% rename from LICENSE rename to doric-demo/LICENSE diff --git a/README.md b/doric-demo/README.md similarity index 100% rename from README.md rename to doric-demo/README.md diff --git a/index.ts b/doric-demo/index.ts similarity index 100% rename from index.ts rename to doric-demo/index.ts diff --git a/package-lock.json b/doric-demo/package-lock.json similarity index 100% rename from package-lock.json rename to doric-demo/package-lock.json diff --git a/package.json b/doric-demo/package.json similarity index 100% rename from package.json rename to doric-demo/package.json diff --git a/rollup.config.js b/doric-demo/rollup.config.js similarity index 100% rename from rollup.config.js rename to doric-demo/rollup.config.js diff --git a/src/AnimatorDemo.ts b/doric-demo/src/AnimatorDemo.ts similarity index 100% rename from src/AnimatorDemo.ts rename to doric-demo/src/AnimatorDemo.ts diff --git a/src/ComplicatedAnimations.ts b/doric-demo/src/ComplicatedAnimations.ts similarity index 100% rename from src/ComplicatedAnimations.ts rename to doric-demo/src/ComplicatedAnimations.ts diff --git a/src/ComplicatedDemo.ts b/doric-demo/src/ComplicatedDemo.ts similarity index 100% rename from src/ComplicatedDemo.ts rename to doric-demo/src/ComplicatedDemo.ts diff --git a/src/Counter.ts b/doric-demo/src/Counter.ts similarity index 100% rename from src/Counter.ts rename to doric-demo/src/Counter.ts diff --git a/src/EffectsDemo.ts b/doric-demo/src/EffectsDemo.ts similarity index 100% rename from src/EffectsDemo.ts rename to doric-demo/src/EffectsDemo.ts diff --git a/src/FlowLayoutDemo.ts b/doric-demo/src/FlowLayoutDemo.ts similarity index 100% rename from src/FlowLayoutDemo.ts rename to doric-demo/src/FlowLayoutDemo.ts diff --git a/src/Gobang.ts b/doric-demo/src/Gobang.ts similarity index 100% rename from src/Gobang.ts rename to doric-demo/src/Gobang.ts diff --git a/src/ImageDemo.ts b/doric-demo/src/ImageDemo.ts similarity index 100% rename from src/ImageDemo.ts rename to doric-demo/src/ImageDemo.ts diff --git a/src/InputDemo.ts b/doric-demo/src/InputDemo.ts similarity index 100% rename from src/InputDemo.ts rename to doric-demo/src/InputDemo.ts diff --git a/src/LayoutDemo.ts b/doric-demo/src/LayoutDemo.ts similarity index 100% rename from src/LayoutDemo.ts rename to doric-demo/src/LayoutDemo.ts diff --git a/src/ListDemo.ts b/doric-demo/src/ListDemo.ts similarity index 100% rename from src/ListDemo.ts rename to doric-demo/src/ListDemo.ts diff --git a/src/ModalDemo.ts b/doric-demo/src/ModalDemo.ts similarity index 100% rename from src/ModalDemo.ts rename to doric-demo/src/ModalDemo.ts diff --git a/src/NavbarDemo.ts b/doric-demo/src/NavbarDemo.ts similarity index 100% rename from src/NavbarDemo.ts rename to doric-demo/src/NavbarDemo.ts diff --git a/src/NavigatorDemo.ts b/doric-demo/src/NavigatorDemo.ts similarity index 100% rename from src/NavigatorDemo.ts rename to doric-demo/src/NavigatorDemo.ts diff --git a/src/NetworkDemo.ts b/doric-demo/src/NetworkDemo.ts similarity index 100% rename from src/NetworkDemo.ts rename to doric-demo/src/NetworkDemo.ts diff --git a/src/PopoverDemo.ts b/doric-demo/src/PopoverDemo.ts similarity index 100% rename from src/PopoverDemo.ts rename to doric-demo/src/PopoverDemo.ts diff --git a/src/RefreshableDemo.ts b/doric-demo/src/RefreshableDemo.ts similarity index 100% rename from src/RefreshableDemo.ts rename to doric-demo/src/RefreshableDemo.ts diff --git a/src/ScrollerDemo.ts b/doric-demo/src/ScrollerDemo.ts similarity index 100% rename from src/ScrollerDemo.ts rename to doric-demo/src/ScrollerDemo.ts diff --git a/src/SliderDemo.ts b/doric-demo/src/SliderDemo.ts similarity index 100% rename from src/SliderDemo.ts rename to doric-demo/src/SliderDemo.ts diff --git a/src/Snake.ts b/doric-demo/src/Snake.ts similarity index 100% rename from src/Snake.ts rename to doric-demo/src/Snake.ts diff --git a/src/StickDemo.ts b/doric-demo/src/StickDemo.ts similarity index 100% rename from src/StickDemo.ts rename to doric-demo/src/StickDemo.ts diff --git a/src/StorageDemo.ts b/doric-demo/src/StorageDemo.ts similarity index 100% rename from src/StorageDemo.ts rename to doric-demo/src/StorageDemo.ts diff --git a/src/image_base64.ts b/doric-demo/src/image_base64.ts similarity index 100% rename from src/image_base64.ts rename to doric-demo/src/image_base64.ts diff --git a/src/utils.ts b/doric-demo/src/utils.ts similarity index 100% rename from src/utils.ts rename to doric-demo/src/utils.ts diff --git a/tsconfig.json b/doric-demo/tsconfig.json similarity index 100% rename from tsconfig.json rename to doric-demo/tsconfig.json