diff --git a/doric-js/.gitignore b/doric-js/.gitignore index 99672424..53fc2543 100644 --- a/doric-js/.gitignore +++ b/doric-js/.gitignore @@ -1,4 +1,5 @@ node_modules/ build/ bundle/ -demo/ \ No newline at end of file +demo/ +.DS_Store \ No newline at end of file diff --git a/doric-js/LICENSE b/doric-js/LICENSE new file mode 100644 index 00000000..97846020 --- /dev/null +++ b/doric-js/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. diff --git a/doric-js/README.md b/doric-js/README.md new file mode 100644 index 00000000..b304a242 --- /dev/null +++ b/doric-js/README.md @@ -0,0 +1 @@ +# Doric JS Framework \ No newline at end of file diff --git a/doric-js/index.debug.ts b/doric-js/index.debug.ts index 9f2d8eba..71efb893 100644 --- a/doric-js/index.debug.ts +++ b/doric-js/index.debug.ts @@ -19,7 +19,7 @@ const WebSocketClient = require('ws') const fs = require('fs') let context = process.cwd() + '/build/context' const contextId = fs.readFileSync(context, { encoding: 'utf8' }) -console.log(contextId) +console.log("debugging context id: " + contextId) let global = new Function('return this')() global.doric = doric global.context = doric.jsObtainContext(contextId) diff --git a/doric-js/package-lock.json b/doric-js/package-lock.json index 4755ef3c..b7b720eb 100644 --- a/doric-js/package-lock.json +++ b/doric-js/package-lock.json @@ -1,18 +1,38 @@ { "name": "doric", - "version": "0.1.0", + "version": "0.1.3", "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.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.11", - "resolved": "https://registry.npmjs.org/@types/node/-/node-12.12.11.tgz", - "integrity": "sha512-O+x6uIpa6oMNTkPuHDa9MhMMehlxLAd5QcOvKRjAFsBVpeFWTOPnXbDvILvFgFFZfQ1xh1EZi1FbXxUix+zpsQ==" + "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", @@ -23,9 +43,9 @@ } }, "@types/ws": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.3.tgz", - "integrity": "sha512-yBTM0P05Tx9iXGq00BbJPo37ox68R5vaGTXivs6RGh/BQ6QP5zqZDGWdAO6JbRE/iR1l80xeGAwCQS2nMV9S/w==", + "version": "6.0.4", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-6.0.4.tgz", + "integrity": "sha512-PpPrX7SZW9re6+Ha8ojZG4Se8AZXgf0GK6zmfqEuCsY49LFDNXO3SByp44X3dFEqtB73lkCDAdUazhAjVPiNwg==", "requires": { "@types/node": "*" } @@ -35,11 +55,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", @@ -66,60 +81,37 @@ "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.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.2", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-1.27.2.tgz", - "integrity": "sha512-sD3iyd0zlvgK1S3MmICi6F/Y+R/QWY5XxzsTGN4pAd+nCasDUizmAhgq2hdh1t2eLux974NHU2TW41fhuGPv+Q==", + "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", "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==" }, "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==" } } } diff --git a/doric-js/package.json b/doric-js/package.json index dab007f9..84f087eb 100644 --- a/doric-js/package.json +++ b/doric-js/package.json @@ -1,6 +1,6 @@ { "name": "doric", - "version": "0.1.0", + "version": "0.1.3", "description": "The JS Framework of Doric", "main": "bundle/doric-vm.js", "scripts": { @@ -20,12 +20,12 @@ }, "homepage": "https://github.com/doric-pub/doric#readme", "dependencies": { - "@types/ws": "^6.0.3", + "@types/ws": "^6.0.4", "reflect-metadata": "^0.1.13", - "rollup": "^1.27.2", - "rollup-plugin-node-resolve": "^5.2.0", + "rollup": "^1.27.13", + "@rollup/plugin-node-resolve": "^6.0.0", "tslib": "^1.10.0", - "typescript": "^3.7.2", - "ws": "^7.2.0" + "typescript": "^3.7.3", + "ws": "^7.2.1" } } diff --git a/doric-js/rollup.config.js b/doric-js/rollup.config.js index 6cec211a..c2d1388c 100644 --- a/doric-js/rollup.config.js +++ b/doric-js/rollup.config.js @@ -1,6 +1,6 @@ const path = require('path') const fs = require('fs') -import resolve from 'rollup-plugin-node-resolve' +import resolve from '@rollup/plugin-node-resolve' export default [ { diff --git a/doric-js/src/native/animate.ts b/doric-js/src/native/animate.ts index a9e7a155..df3a24e8 100644 --- a/doric-js/src/native/animate.ts +++ b/doric-js/src/native/animate.ts @@ -15,37 +15,50 @@ */ import { Panel } from "../ui/panel" import { takeLet } from "../pattern/candies" +import { BridgeContext } from "../runtime/global" /** * Only supports x,y,width,height,corner(just for four corners),rotation,bgColor, * @param panel @see Panel */ -export function animate(panel: Panel) { - return (args: { - animations: () => void, - duration: number, - }) => { - return takeLet(panel.context.animate)(it => { - return it.submit().then(() => { - args.animations() - return takeLet(panel.getRootView())(root => { - if (root.isDirty()) { - const model = root.toModel(); - (model as any).duration = args.duration - const ret = it.animateRender(model) - root.clean() - return ret - } - for (let v of panel.allHeadViews()) { - if (v.isDirty()) { - const model = v.toModel() +export function animate(context: BridgeContext) { + const entity = context.entity + if (entity instanceof Panel) { + let panel = entity + return (args: { + animations: () => void, + duration: number, + }) => { + return takeLet(panel.context.animate)(it => { + return it.submit().then(() => { + args.animations() + return takeLet(panel.getRootView())(root => { + if (root.isDirty()) { + const model = root.toModel(); + (model as any).duration = args.duration const ret = it.animateRender(model) - it.clean() + root.clean() return ret } - } - throw new Error('Cannot find any animated elements') + for (let v of panel.allHeadViews()) { + if (v.isDirty()) { + const model = v.toModel() + const ret = it.animateRender(model) + it.clean() + return ret + } + } + throw new Error('Cannot find any animated elements') + }) }) - }) - }) as Promise + }) as Promise + } + } else { + return (args: { + animations: () => void, + duration: number, + }) => { + return Promise.reject(`Cannot find panel in Context:${context.id}`) + } } + } \ No newline at end of file diff --git a/doric-js/src/native/navigator.ts b/doric-js/src/native/navigator.ts index 6e849613..fc92d92e 100644 --- a/doric-js/src/native/navigator.ts +++ b/doric-js/src/native/navigator.ts @@ -17,9 +17,16 @@ import { BridgeContext } from "../runtime/global" export function navigator(context: BridgeContext) { return { - push: (scheme: string, alias: string, animated = true) => { + push: (scheme: string, config?: { + alias?: string, + animated?: boolean, + extra?: object, + }) => { + if (config && config.extra) { + (config as any).extra = JSON.stringify(config.extra) + } return context.navigator.push({ - scheme, alias, animated + scheme, config }) }, pop: (animated = true) => { diff --git a/doric-js/src/pattern/mvvm.ts b/doric-js/src/pattern/mvvm.ts index 47cdb0cf..a898d68d 100644 --- a/doric-js/src/pattern/mvvm.ts +++ b/doric-js/src/pattern/mvvm.ts @@ -16,14 +16,13 @@ import { Group } from "../ui/view" import { Panel } from "../ui/panel" -export abstract class ViewHolder{ +export abstract class ViewHolder { abstract build(root: Group): void - abstract bind(state: M): void } export type Setter = (state: M) => void -export abstract class ViewModel> { +export abstract class ViewModel { private state: M private viewHolder: V @@ -38,22 +37,24 @@ export abstract class ViewModel> { updateState(setter: Setter) { setter(this.state) - this.viewHolder.bind(this.state) + this.onBind(this.state, this.viewHolder) } attach(view: Group) { this.viewHolder.build(view) - this.viewHolder.bind(this.state) this.onAttached(this.state, this.viewHolder) + this.onBind(this.state, this.viewHolder) } abstract onAttached(state: M, vh: V): void + + abstract onBind(state: M, vh: V): void } -export type ViewModelClass> = new (m: M, v: V) => ViewModel +export type ViewModelClass = new (m: M, v: V) => ViewModel export type ViewHolderClass = new () => V -export abstract class VMPanel> extends Panel { +export abstract class VMPanel extends Panel { private vm?: ViewModel private vh?: V diff --git a/doric-js/src/runtime/global.ts b/doric-js/src/runtime/global.ts index ab78396a..356b1261 100644 --- a/doric-js/src/runtime/global.ts +++ b/doric-js/src/runtime/global.ts @@ -19,6 +19,22 @@ export type BridgeContext = { [index: string]: { [index: string]: (args?: any) = declare global { const context: BridgeContext + const Environment: { + platform: "Android" | "iOS" | "Qt", + + platformVersion: string, + + appName: string, + + appVersion: string, + + libVersion: string, + + screenWidth: number, + + screenHeight: number, + + } function Entry(constructor: { new(...args: any[]): {} }): any } export { } \ No newline at end of file diff --git a/doric-js/src/runtime/sandbox.ts b/doric-js/src/runtime/sandbox.ts index f86b9ed8..d59a1a01 100644 --- a/doric-js/src/runtime/sandbox.ts +++ b/doric-js/src/runtime/sandbox.ts @@ -194,11 +194,12 @@ export function jsObtainContext(id: string) { export function jsReleaseContext(id: string) { const context = gContexts.get(id) + const args = arguments if (context) { timerInfos.forEach((v, k) => { if (v.context === context) { if (global.nativeClearTimer === undefined) { - return Reflect.apply(_clearTimeout, undefined, arguments) + return Reflect.apply(_clearTimeout, undefined, args) } timerInfos.delete(k) nativeClearTimer(k) @@ -275,7 +276,7 @@ const _clearTimeout = global.clearTimeout const _clearInterval = global.clearInterval -global.setTimeout = function (handler: Function, timeout?: number | undefined, ...args: any[]) { +const doricSetTimeout = function (handler: Function, timeout?: number | undefined, ...args: any[]) { if (global.nativeSetTimer === undefined) { return Reflect.apply(_setTimeout, undefined, arguments) } @@ -290,7 +291,7 @@ global.setTimeout = function (handler: Function, timeout?: number | undefined, . nativeSetTimer(id, timeout || 0, false) return id } -global.setInterval = function (handler: Function, timeout?: number | undefined, ...args: any[]) { +const doricSetInterval = function (handler: Function, timeout?: number | undefined, ...args: any[]) { if (global.nativeSetTimer === undefined) { return Reflect.apply(_setInterval, undefined, arguments) } @@ -305,7 +306,7 @@ global.setInterval = function (handler: Function, timeout?: number | undefined, return id } -global.clearTimeout = function (timerId: number) { +const doricClearTimeout = function (timerId: number) { if (global.nativeClearTimer === undefined) { return Reflect.apply(_clearTimeout, undefined, arguments) } @@ -313,7 +314,7 @@ global.clearTimeout = function (timerId: number) { nativeClearTimer(timerId) } -global.clearInterval = function (timerId: number) { +const doricClearInterval = function (timerId: number) { if (global.nativeClearTimer === undefined) { return Reflect.apply(_clearInterval, undefined, arguments) } @@ -321,6 +322,30 @@ global.clearInterval = function (timerId: number) { nativeClearTimer(timerId) } +if (!global.setTimeout) { + global.setTimeout = doricSetTimeout +} else { + global.doricSetTimeout = doricSetTimeout +} + +if (!global.setInterval) { + global.setInterval = doricSetInterval +} else { + global.doricSetInterval = doricSetInterval +} + +if (!global.clearTimeout) { + global.clearTimeout = doricClearTimeout +} else { + global.doricClearTimeout = doricClearTimeout +} + +if (!global.clearInterval) { + global.clearInterval = doricClearInterval +} else { + global.doricClearInterval = doricClearInterval +} + export function jsCallbackTimer(timerId: number) { const timerInfo = timerInfos.get(timerId) if (timerInfo === undefined) { diff --git a/doric-js/src/ui/animation.ts b/doric-js/src/ui/animation.ts index 37dc79d2..b1c49de3 100644 --- a/doric-js/src/ui/animation.ts +++ b/doric-js/src/ui/animation.ts @@ -1,5 +1,3 @@ -import { Modeling, Model } from "../util/types" - /* * Copyright [2019] [Doric.Pub] * @@ -16,6 +14,7 @@ import { Modeling, Model } from "../util/types" * limitations under the License. */ +import { Modeling, Model } from "../util/types" export type AnimatedKey = "translationX" | "translationY" | "scaleX" | "scaleY" | "rotation" | "pivotX" | "pivotY" diff --git a/doric-js/src/ui/panel.ts b/doric-js/src/ui/panel.ts index b8c3d98e..da919a1a 100644 --- a/doric-js/src/ui/panel.ts +++ b/doric-js/src/ui/panel.ts @@ -42,7 +42,7 @@ export abstract class Panel { abstract build(rootView: Group): void - private __data__: any + private __data__?: object private __root__ = new Root private headviews: Map = new Map @@ -73,8 +73,10 @@ export abstract class Panel { } @NativeCall - private __init__(frame: Frame, data: any) { - this.__data__ = data + private __init__(frame: Frame, data?: string) { + if (data) { + this.__data__ = JSON.parse(data) + } this.__root__.width = frame.width this.__root__.height = frame.height this.__root__.children.length = 0 diff --git a/doric-js/src/ui/view.ts b/doric-js/src/ui/view.ts index b524773a..4f70088b 100644 --- a/doric-js/src/ui/view.ts +++ b/doric-js/src/ui/view.ts @@ -297,6 +297,10 @@ export abstract class View implements Modeling, IView { return this.nativeChannel(context, 'getHeight')() as Promise } + getLocationOnScreen(context: BridgeContext) { + return this.nativeChannel(context, "getLocationOnScreen")() as Promise<{ x: number, y: number }> + } + /**++++++++++transform++++++++++*/ @Property translationX?: number @@ -363,9 +367,11 @@ export abstract class Superview extends View { toModel() { const subviews = [] for (let v of this.allSubviews()) { - v.superview = this - if (v.isDirty()) { - subviews.push(v.toModel()) + if (v != undefined) { + v.superview = this + if (v.isDirty()) { + subviews.push(v.toModel()) + } } } this.dirtyProps.subviews = subviews diff --git a/doric-js/src/util/color.ts b/doric-js/src/util/color.ts index bac1f9c3..3e0e698c 100644 --- a/doric-js/src/util/color.ts +++ b/doric-js/src/util/color.ts @@ -63,6 +63,7 @@ export class Color implements Modeling { } alpha(v: number) { + v = v * 255 return new Color((this._value & 0xffffff) | ((v & 0xff) << 24)) } diff --git a/doric-js/src/util/layoutconfig.ts b/doric-js/src/util/layoutconfig.ts index b074056f..9576bb9a 100644 --- a/doric-js/src/util/layoutconfig.ts +++ b/doric-js/src/util/layoutconfig.ts @@ -17,9 +17,18 @@ import { Gravity } from "./gravity"; import { Modeling } from "./types"; export enum LayoutSpec { - EXACTLY = 0, - WRAP_CONTENT = 1, - AT_MOST = 2, + /** + * Depends on what's been set on width or height. + */ + JUST = 0, + /** + * Depends on it's content. + */ + FIT = 1, + /** + * Extend as much as parent let it take. + */ + MOST = 2, } export interface LayoutConfig { @@ -49,35 +58,35 @@ export class LayoutConfigImpl implements LayoutConfig, Modeling { //Only affective in VLayout or HLayout weight?: number - wrap() { - this.widthSpec = LayoutSpec.WRAP_CONTENT - this.heightSpec = LayoutSpec.WRAP_CONTENT + fit() { + this.widthSpec = LayoutSpec.FIT + this.heightSpec = LayoutSpec.FIT return this } - atmost() { - this.widthSpec = LayoutSpec.AT_MOST - this.heightSpec = LayoutSpec.AT_MOST + most() { + this.widthSpec = LayoutSpec.MOST + this.heightSpec = LayoutSpec.MOST return this } - exactly() { - this.widthSpec = LayoutSpec.EXACTLY - this.heightSpec = LayoutSpec.EXACTLY + just() { + this.widthSpec = LayoutSpec.JUST + this.heightSpec = LayoutSpec.JUST return this } - w(w: LayoutSpec) { + configWidth(w: LayoutSpec) { this.widthSpec = w return this } - h(h: LayoutSpec) { + configHeight(h: LayoutSpec) { this.heightSpec = h return this } - m(m: { + configMargin(m: { left?: number, right?: number, top?: number, @@ -87,12 +96,12 @@ export class LayoutConfigImpl implements LayoutConfig, Modeling { return this } - a(a: Gravity) { + configAligmnet(a: Gravity) { this.alignment = a return this } - wg(w: number) { + configWeight(w: number) { this.weight = w return this } diff --git a/doric-js/src/widget/flowlayout.ts b/doric-js/src/widget/flowlayout.ts index fe0655a5..16915649 100644 --- a/doric-js/src/widget/flowlayout.ts +++ b/doric-js/src/widget/flowlayout.ts @@ -43,7 +43,11 @@ export class FlowLayout extends Superview implements IFlowLayout { private ignoreDirtyCallOnce = false allSubviews() { - return this.cachedViews.values() + if (this.loadMoreView) { + return [...this.cachedViews.values(), this.loadMoreView] + } else { + return this.cachedViews.values() + } } @Property @@ -64,17 +68,23 @@ export class FlowLayout extends Superview implements IFlowLayout { @Property batchCount = 15 + @Property + onLoadMore?: () => void + + @Property + loadMore?: boolean + + @Property + loadMoreView?: FlowLayoutItem + reset() { this.cachedViews.clear() this.itemCount = 0 } private getItem(itemIdx: number) { - let view = this.cachedViews.get(`${itemIdx}`) - if (view === undefined) { - view = this.renderItem(itemIdx) - view.superview = this - this.cachedViews.set(`${itemIdx}`, view) - } + let view = this.renderItem(itemIdx) + view.superview = this + this.cachedViews.set(`${itemIdx}`, view) return view } @@ -94,6 +104,13 @@ export class FlowLayout extends Superview implements IFlowLayout { return listItem.toModel() }) } + + toModel() { + if (this.loadMoreView) { + this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId + } + return super.toModel() + } } export function flowlayout(config: IFlowLayout) { @@ -106,7 +123,7 @@ export function flowlayout(config: IFlowLayout) { export function flowItem(item: View) { return (new FlowLayoutItem).also((it) => { - it.layoutConfig = layoutConfig().wrap() + it.layoutConfig = layoutConfig().fit() it.addChild(item) }) } diff --git a/doric-js/src/widget/image.ts b/doric-js/src/widget/image.ts index 90a8a1ba..c713ea93 100644 --- a/doric-js/src/widget/image.ts +++ b/doric-js/src/widget/image.ts @@ -26,6 +26,7 @@ export interface IImage extends IView { imageUrl?: string imageBase64?: string scaleType?: ScaleType + isBlur?: boolean loadCallback?: (image: { width: number; height: number } | undefined) => void } @@ -36,6 +37,8 @@ export class Image extends View implements IImage { imageBase64?: string @Property scaleType?: ScaleType + @Property + isBlur?: boolean @Property loadCallback?: (image: { width: number; height: number } | undefined) => void @@ -43,7 +46,7 @@ export class Image extends View implements IImage { export function image(config: IImage) { const ret = new Image - ret.layoutConfig = layoutConfig().wrap() + ret.layoutConfig = layoutConfig().fit() for (let key in config) { Reflect.set(ret, key, Reflect.get(config, key, config), ret) } diff --git a/doric-js/src/widget/index.widget.ts b/doric-js/src/widget/index.widget.ts index 14449949..11f5bd97 100644 --- a/doric-js/src/widget/index.widget.ts +++ b/doric-js/src/widget/index.widget.ts @@ -20,4 +20,6 @@ export * from './list' export * from './slider' export * from './scroller' export * from './refreshable' -export * from './flowlayout' \ No newline at end of file +export * from './flowlayout' +export * from './input' +export * from './nestedSlider' \ No newline at end of file diff --git a/doric-js/src/widget/input.ts b/doric-js/src/widget/input.ts new file mode 100644 index 00000000..f03080e4 --- /dev/null +++ b/doric-js/src/widget/input.ts @@ -0,0 +1,80 @@ +/* + * 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. + */ +import { View, IView, Property } from "../ui/view"; +import { Color } from "../util/color"; +import { Gravity } from "../util/gravity"; +import { BridgeContext } from "../runtime/global"; + +export interface IInput extends IView { + text?: string + textColor?: Color + textSize?: number + hintText?: string + hintTextColor?: Color + multilines?: boolean + textAlignment?: Gravity + onTextChange?: (text: string) => void + onFocusChange?: (focused: boolean) => void +} + +export class Input extends View implements IInput { + + @Property + text?: string + + @Property + textColor?: Color + + @Property + textSize?: number + + @Property + hintText?: string + + @Property + hintTextColor?: Color + + @Property + multiline?: boolean + + @Property + textAlignment?: Gravity + + @Property + onTextChange?: (text: string) => void + + @Property + onFocusChange?: (focused: boolean) => void + + getText(context: BridgeContext) { + return this.nativeChannel(context, 'getText')() as Promise + } + + setSelection(context: BridgeContext, start: number, end: number = start) { + return this.nativeChannel(context, 'setSelection')({ + start, + end, + }) as Promise + } + + requestFocus(context: BridgeContext) { + return this.nativeChannel(context, 'requestFocus')() + } + + releaseFocus(context: BridgeContext) { + return this.nativeChannel(context, 'releaseFocus')() + } +} \ No newline at end of file diff --git a/doric-js/src/widget/layouts.ts b/doric-js/src/widget/layouts.ts index 9162af66..b0c8fa66 100644 --- a/doric-js/src/widget/layouts.ts +++ b/doric-js/src/widget/layouts.ts @@ -53,7 +53,7 @@ export class HLayout extends LinearLayout implements IHLayout { export function stack(views: View[]) { const ret = new Stack - ret.layoutConfig = layoutConfig().wrap() + ret.layoutConfig = layoutConfig().fit() for (let v of views) { ret.addChild(v) } @@ -62,7 +62,7 @@ export function stack(views: View[]) { export function hlayout(views: View[]) { const ret = new HLayout - ret.layoutConfig = layoutConfig().wrap() + ret.layoutConfig = layoutConfig().fit() for (let v of views) { ret.addChild(v) } @@ -71,7 +71,7 @@ export function hlayout(views: View[]) { export function vlayout(views: View[]) { const ret = new VLayout - ret.layoutConfig = layoutConfig().wrap() + ret.layoutConfig = layoutConfig().fit() for (let v of views) { ret.addChild(v) } diff --git a/doric-js/src/widget/list.ts b/doric-js/src/widget/list.ts index 7c59a7cf..99e3dde6 100644 --- a/doric-js/src/widget/list.ts +++ b/doric-js/src/widget/list.ts @@ -16,7 +16,7 @@ import { View, Property, Superview, IView } from "../ui/view"; import { Stack } from "./layouts"; -import { layoutConfig } from "../util/layoutconfig"; +import { layoutConfig, LayoutSpec } from "../util/layoutconfig"; export class ListItem extends Stack { /** @@ -35,8 +35,13 @@ export interface IList extends IView { export class List extends Superview implements IList { private cachedViews: Map = new Map private ignoreDirtyCallOnce = false + allSubviews() { - return this.cachedViews.values() + if (this.loadMoreView) { + return [...this.cachedViews.values(), this.loadMoreView] + } else { + return this.cachedViews.values() + } } @Property @@ -48,6 +53,15 @@ export class List extends Superview implements IList { @Property batchCount = 15 + @Property + onLoadMore?: () => void + + @Property + loadMore?: boolean + + @Property + loadMoreView?: ListItem + reset() { this.cachedViews.clear() this.itemCount = 0 @@ -78,6 +92,13 @@ export class List extends Superview implements IList { return listItem.toModel() }) } + + toModel() { + if (this.loadMoreView) { + this.dirtyProps['loadMoreView'] = this.loadMoreView.viewId + } + return super.toModel() + } } export function list(config: IList) { @@ -90,7 +111,7 @@ export function list(config: IList) { export function listItem(item: View) { return (new ListItem).also((it) => { - it.layoutConfig = layoutConfig().wrap() + it.layoutConfig = layoutConfig().most().configHeight(LayoutSpec.FIT) it.addChild(item) }) } diff --git a/doric-js/src/widget/nestedSlider.ts b/doric-js/src/widget/nestedSlider.ts new file mode 100644 index 00000000..dab3f755 --- /dev/null +++ b/doric-js/src/widget/nestedSlider.ts @@ -0,0 +1,35 @@ +/* + * 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. + */ +import { Group, View, Property } from '../ui/view' +import { BridgeContext } from '../runtime/global' + + +export class NestedSlider extends Group { + @Property + onPageSlided?: (index: number) => void + + addSlideItem(view: View) { + this.addChild(view) + } + + slidePage(context: BridgeContext, page: number, smooth = false) { + return this.nativeChannel(context, "slidePage")({ page, smooth }) + } + + getSlidedPage(context: BridgeContext) { + return this.nativeChannel(context, "getSlidedPage")() as Promise + } +} \ No newline at end of file diff --git a/doric-js/src/widget/refreshable.ts b/doric-js/src/widget/refreshable.ts index 41746ec4..7b78e31a 100644 --- a/doric-js/src/widget/refreshable.ts +++ b/doric-js/src/widget/refreshable.ts @@ -52,7 +52,7 @@ export class Refreshable extends Superview implements IRefreshable { export function refreshable(config: IRefreshable) { const ret = new Refreshable - ret.layoutConfig = layoutConfig().wrap() + ret.layoutConfig = layoutConfig().fit() for (let key in config) { Reflect.set(ret, key, Reflect.get(config, key, config), ret) } @@ -66,7 +66,7 @@ export interface IPullable { } -export function pullable(context: BridgeContext, v: View, config: IPullable) { +export function pullable(v: View, config: IPullable) { Reflect.set(v, 'startAnimation', config.startAnimation) Reflect.set(v, 'stopAnimation', config.stopAnimation) Reflect.set(v, 'setPullingDistance', config.setPullingDistance) diff --git a/doric-js/src/widget/scroller.ts b/doric-js/src/widget/scroller.ts index c0155cd0..965a0225 100644 --- a/doric-js/src/widget/scroller.ts +++ b/doric-js/src/widget/scroller.ts @@ -18,7 +18,7 @@ import { layoutConfig } from '../util/layoutconfig' export function scroller(content: View) { return (new Scroller).also(v => { - v.layoutConfig = layoutConfig().wrap() + v.layoutConfig = layoutConfig().fit() v.content = content }) } diff --git a/doric-js/src/widget/slider.ts b/doric-js/src/widget/slider.ts index e1ee3f20..733faad2 100644 --- a/doric-js/src/widget/slider.ts +++ b/doric-js/src/widget/slider.ts @@ -1,6 +1,7 @@ import { Superview, View, Property, IView } from "../ui/view"; import { Stack } from "./layouts"; import { layoutConfig } from "../util/layoutconfig"; +import { BridgeContext } from "../runtime/global"; export class SlideItem extends Stack { /** @@ -14,6 +15,7 @@ export interface ISlider extends IView { renderPage: (index: number) => SlideItem itemCount: number batchCount?: number + onPageSlided?: (index: number) => void } export class Slider extends Superview implements ISlider { @@ -33,6 +35,8 @@ export class Slider extends Superview implements ISlider { @Property batchCount = 3 + @Property + onPageSlided?: (index: number) => void private getItem(itemIdx: number) { let view = this.cachedViews.get(`${itemIdx}`) @@ -60,11 +64,20 @@ export class Slider extends Superview implements ISlider { return slideItem.toModel() }) } + + slidePage(context: BridgeContext, page: number, smooth = false) { + return this.nativeChannel(context, "slidePage")({ page, smooth }) + } + + getSlidedPage(context: BridgeContext) { + return this.nativeChannel(context, "getSlidedPage")() as Promise + } + } export function slideItem(item: View) { return (new SlideItem).also((it) => { - it.layoutConfig = layoutConfig().wrap() + it.layoutConfig = layoutConfig().fit() it.addChild(item) }) } diff --git a/doric-js/src/widget/text.ts b/doric-js/src/widget/text.ts index d3663a72..527a4463 100644 --- a/doric-js/src/widget/text.ts +++ b/doric-js/src/widget/text.ts @@ -45,7 +45,7 @@ export class Text extends View implements IText { export function text(config: IText) { const ret = new Text - ret.layoutConfig = layoutConfig().wrap() + ret.layoutConfig = layoutConfig().fit() for (let key in config) { Reflect.set(ret, key, Reflect.get(config, key, config), ret) }