From c5a14d8e29e7c5cd4e18d7f4175e5d3938dacde7 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 21 May 2020 13:56:00 -0400
Subject: fixed pres box progressivize to force progressivization

---
 src/client/views/presentationview/PresElementBox.tsx | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

(limited to 'src/client/views/presentationview/PresElementBox.tsx')

diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index a2a6882b9..f364b40fd 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -100,13 +100,14 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         e.stopPropagation();
         this.rootDoc.presProgressivize = !this.rootDoc.presProgressivize;
         const rootTarget = Cast(this.rootDoc.presentationTargetDoc, Doc, null);
+        const docs = DocListCast(rootTarget[Doc.LayoutFieldKey(rootTarget)]);
         if (this.rootDoc.presProgressivize && !rootTarget?.lastTimecode) {
-            const docs = DocListCast(rootTarget[Doc.LayoutFieldKey(rootTarget)]);
             rootTarget.currentTimecode = 0;
             CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, this.presBox);
             docs.forEach((d, i) => numberRange(docs.length - i).forEach(f => Cast(d["opacity-indexed"], listSpec("number"), [])[f + i] = 1));
             rootTarget.lastTimecode = docs.length - 1;
         }
+        docs.forEach((d, i) => i && numberRange(i).forEach(f => Cast(d["opacity-indexed"], listSpec("number"), [])[f] = 0));
     }
 
     /**
@@ -216,7 +217,10 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
                     <strong className="presElementBox-name">
                         {`${this.indexInPres + 1}. ${this.targetDoc?.title}`}
                     </strong>
-                    <button className="presElementBox-closeIcon" onPointerDown={e => e.stopPropagation()} onClick={e => this.props.removeDocument?.(this.rootDoc)}>X</button>
+                    <button className="presElementBox-closeIcon" onPointerDown={e => e.stopPropagation()} onClick={e => {
+                        this.props.removeDocument?.(this.rootDoc);
+                        e.stopPropagation();
+                    }}>X</button>
                     <br />
                 </>}
                 <div className="presElementBox-buttons">
-- 
cgit v1.2.3-70-g09d2


From a3506d7a8964a113f10bdce672a86678b992b653 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Thu, 21 May 2020 19:25:56 -0400
Subject: more fixes to progressivizing.   tweaks to comparison box's clear
 button.

---
 package-lock.json                                  | 372 ++++++++++++++++++++-
 package.json                                       |   1 +
 src/client/views/MainView.tsx                      |   4 +-
 .../collectionFreeForm/CollectionFreeFormView.tsx  |   3 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx |  15 +-
 src/client/views/nodes/ComparisonBox.tsx           |  44 +--
 .../views/presentationview/PresElementBox.tsx      |   1 -
 7 files changed, 400 insertions(+), 40 deletions(-)

(limited to 'src/client/views/presentationview/PresElementBox.tsx')

diff --git a/package-lock.json b/package-lock.json
index 2e83c295c..21e4c4e27 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -356,6 +356,19 @@
             "integrity": "sha512-bWBbC7VG2jdjbgZMX0qpds8U/3h3anfIqE81L8jmVrgFZw/urEDnBA78ymGGKTTK6ciBXmmJ/xlok+Re41S8ww==",
             "dev": true
         },
+        "@types/babel-types": {
+            "version": "7.0.7",
+            "resolved": "https://registry.npmjs.org/@types/babel-types/-/babel-types-7.0.7.tgz",
+            "integrity": "sha512-dBtBbrc+qTHy1WdfHYjBwRln4+LWqASWakLHsWHR2NWHIFkv4W3O070IGoGLEBrJBvct3r0L1BUPuvURi7kYUQ=="
+        },
+        "@types/babylon": {
+            "version": "6.16.5",
+            "resolved": "https://registry.npmjs.org/@types/babylon/-/babylon-6.16.5.tgz",
+            "integrity": "sha512-xH2e58elpj1X4ynnKp9qSnWlsRTIs6n3tgLGNfwAGHwePw0mulHQllV34n0T25uYSu1k0hRKkWXF890B1yS47w==",
+            "requires": {
+                "@types/babel-types": "*"
+            }
+        },
         "@types/bcrypt-nodejs": {
             "version": "0.0.30",
             "resolved": "https://registry.npmjs.org/@types/bcrypt-nodejs/-/bcrypt-nodejs-0.0.30.tgz",
@@ -1388,6 +1401,26 @@
                 "negotiator": "0.6.2"
             }
         },
+        "acorn": {
+            "version": "3.3.0",
+            "resolved": "https://registry.npmjs.org/acorn/-/acorn-3.3.0.tgz",
+            "integrity": "sha1-ReN/s56No/JbruP/U2niu18iAXo="
+        },
+        "acorn-globals": {
+            "version": "3.1.0",
+            "resolved": "https://registry.npmjs.org/acorn-globals/-/acorn-globals-3.1.0.tgz",
+            "integrity": "sha1-/YJw9x+7SZawBPqIDuXUZXOnMb8=",
+            "requires": {
+                "acorn": "^4.0.4"
+            },
+            "dependencies": {
+                "acorn": {
+                    "version": "4.0.13",
+                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
+                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+                }
+            }
+        },
         "acorn-jsx": {
             "version": "5.2.0",
             "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.2.0.tgz",
@@ -1448,6 +1481,31 @@
             "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.4.1.tgz",
             "integrity": "sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ=="
         },
+        "align-text": {
+            "version": "0.1.4",
+            "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz",
+            "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=",
+            "requires": {
+                "kind-of": "^3.0.2",
+                "longest": "^1.0.1",
+                "repeat-string": "^1.5.2"
+            },
+            "dependencies": {
+                "is-buffer": {
+                    "version": "1.1.6",
+                    "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+                    "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+                },
+                "kind-of": {
+                    "version": "3.2.2",
+                    "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
+                    "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=",
+                    "requires": {
+                        "is-buffer": "^1.1.5"
+                    }
+                }
+            }
+        },
         "amdefine": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz",
@@ -1985,6 +2043,29 @@
                 }
             }
         },
+        "babel-types": {
+            "version": "6.26.0",
+            "resolved": "https://registry.npmjs.org/babel-types/-/babel-types-6.26.0.tgz",
+            "integrity": "sha1-o7Bz+Uq0nrb6Vc1lInozQ4BjJJc=",
+            "requires": {
+                "babel-runtime": "^6.26.0",
+                "esutils": "^2.0.2",
+                "lodash": "^4.17.4",
+                "to-fast-properties": "^1.0.3"
+            },
+            "dependencies": {
+                "to-fast-properties": {
+                    "version": "1.0.3",
+                    "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-1.0.3.tgz",
+                    "integrity": "sha1-uDVx+k2MJbguIxsG46MFXeTKGkc="
+                }
+            }
+        },
+        "babylon": {
+            "version": "6.18.0",
+            "resolved": "https://registry.npmjs.org/babylon/-/babylon-6.18.0.tgz",
+            "integrity": "sha512-q/UEjfGJ2Cm3oKV71DJz9d25TPnq5rhBVL2Q4fA5wcC3jcrdn7+SssEybFIxwAvvP+YCsCYNKughoF33GxgycQ=="
+        },
         "backo2": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz",
@@ -2599,6 +2680,15 @@
             "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
             "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw="
         },
+        "center-align": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz",
+            "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=",
+            "requires": {
+                "align-text": "^0.1.3",
+                "lazy-cache": "^1.0.3"
+            }
+        },
         "chai": {
             "version": "4.2.0",
             "resolved": "https://registry.npmjs.org/chai/-/chai-4.2.0.tgz",
@@ -2622,6 +2712,14 @@
                 "supports-color": "^5.3.0"
             }
         },
+        "character-parser": {
+            "version": "2.2.0",
+            "resolved": "https://registry.npmjs.org/character-parser/-/character-parser-2.2.0.tgz",
+            "integrity": "sha1-x84o821LzZdE5f/CxfzeHHMmH8A=",
+            "requires": {
+                "is-regex": "^1.0.3"
+            }
+        },
         "check-error": {
             "version": "1.0.2",
             "resolved": "https://registry.npmjs.org/check-error/-/check-error-1.0.2.tgz",
@@ -3210,6 +3308,21 @@
             "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.2.6.tgz",
             "integrity": "sha512-JR/iSQOSt+LQIWwrwEzJ9uk0xfN3mTVYMwt1Ir5mUcSN6pU+V4zQFFaJsclJbPuAUQH+yfWef6tm7l1quW3C8Q=="
         },
+        "clean-css": {
+            "version": "4.2.3",
+            "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.3.tgz",
+            "integrity": "sha512-VcMWDN54ZN/DS+g58HYL5/n4Zrqe8vHJpGA8KdgUXFU4fuP/aHNw8eld9SyEIyabIMJX/0RaY/fplOo5hYLSFA==",
+            "requires": {
+                "source-map": "~0.6.0"
+            },
+            "dependencies": {
+                "source-map": {
+                    "version": "0.6.1",
+                    "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+                    "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
+                }
+            }
+        },
         "cli-boxes": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/cli-boxes/-/cli-boxes-1.0.0.tgz",
@@ -3581,6 +3694,17 @@
             "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
             "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4="
         },
+        "constantinople": {
+            "version": "3.1.2",
+            "resolved": "https://registry.npmjs.org/constantinople/-/constantinople-3.1.2.tgz",
+            "integrity": "sha512-yePcBqEFhLOqSBtwYOGGS1exHo/s1xjekXiinh4itpNQGCu4KA1euPh1fg07N2wMITZXQkBz75Ntdt1ctGZouw==",
+            "requires": {
+                "@types/babel-types": "^7.0.0",
+                "@types/babylon": "^6.16.2",
+                "babel-types": "^6.26.0",
+                "babylon": "^6.18.0"
+            }
+        },
         "constants-browserify": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
@@ -4635,6 +4759,11 @@
                 "buffer-indexof": "^1.0.0"
             }
         },
+        "doctypes": {
+            "version": "1.1.0",
+            "resolved": "https://registry.npmjs.org/doctypes/-/doctypes-1.1.0.tgz",
+            "integrity": "sha1-6oCxBqh1OHdOijpKWv4pPeSJ4Kk="
+        },
         "dom-helpers": {
             "version": "3.4.0",
             "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-3.4.0.tgz",
@@ -5079,8 +5208,7 @@
         "esutils": {
             "version": "2.0.3",
             "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
-            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
-            "dev": true
+            "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="
         },
         "etag": {
             "version": "1.8.1",
@@ -7173,6 +7301,22 @@
             "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
             "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE="
         },
+        "is-expression": {
+            "version": "3.0.0",
+            "resolved": "https://registry.npmjs.org/is-expression/-/is-expression-3.0.0.tgz",
+            "integrity": "sha1-Oayqa+f9HzRx3ELHQW5hwkMXrJ8=",
+            "requires": {
+                "acorn": "~4.0.2",
+                "object-assign": "^4.0.1"
+            },
+            "dependencies": {
+                "acorn": {
+                    "version": "4.0.13",
+                    "resolved": "https://registry.npmjs.org/acorn/-/acorn-4.0.13.tgz",
+                    "integrity": "sha1-EFSVrlNh1pe9GVyCUZLhrX8lN4c="
+                }
+            }
+        },
         "is-extendable": {
             "version": "1.0.1",
             "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
@@ -7288,6 +7432,11 @@
                 "isobject": "^3.0.1"
             }
         },
+        "is-promise": {
+            "version": "2.2.2",
+            "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz",
+            "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
+        },
         "is-redirect": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz",
@@ -7393,6 +7542,11 @@
             "resolved": "https://registry.npmjs.org/js-datepicker/-/js-datepicker-4.6.6.tgz",
             "integrity": "sha512-kLsE2oHfQM6pzdWNA7Y8HwCHaZIVURItPds7YVJnbe1z1OmQFzN7lfg6yFbDDWOyNjdHZGzWDy3jSDN2W0pNZQ=="
         },
+        "js-stringify": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/js-stringify/-/js-stringify-1.0.2.tgz",
+            "integrity": "sha1-Fzb939lyTyijaCrcYjCufk6Weds="
+        },
         "js-tokens": {
             "version": "4.0.0",
             "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
@@ -7552,6 +7706,15 @@
                 "verror": "1.10.0"
             }
         },
+        "jstransformer": {
+            "version": "1.0.0",
+            "resolved": "https://registry.npmjs.org/jstransformer/-/jstransformer-1.0.0.tgz",
+            "integrity": "sha1-7Yvwkh4vPx7U1cGkT2hwntJHIsM=",
+            "requires": {
+                "is-promise": "^2.0.0",
+                "promise": "^7.0.1"
+            }
+        },
         "jwa": {
             "version": "1.4.1",
             "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz",
@@ -7611,6 +7774,11 @@
                 "package-json": "^4.0.0"
             }
         },
+        "lazy-cache": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz",
+            "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4="
+        },
         "lazystream": {
             "version": "1.0.0",
             "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz",
@@ -7829,6 +7997,11 @@
                 "object.assign": "^4.1.0"
             }
         },
+        "longest": {
+            "version": "1.0.1",
+            "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz",
+            "integrity": "sha1-MKCy2jj3N3DoKUoNIuZiXtd9AJc="
+        },
         "loose-envify": {
             "version": "1.4.0",
             "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
@@ -13423,6 +13596,120 @@
                 "safe-buffer": "^5.1.2"
             }
         },
+        "pug": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/pug/-/pug-2.0.4.tgz",
+            "integrity": "sha512-XhoaDlvi6NIzL49nu094R2NA6P37ijtgMDuWE+ofekDChvfKnzFal60bhSdiy8y2PBO6fmz3oMEIcfpBVRUdvw==",
+            "requires": {
+                "pug-code-gen": "^2.0.2",
+                "pug-filters": "^3.1.1",
+                "pug-lexer": "^4.1.0",
+                "pug-linker": "^3.0.6",
+                "pug-load": "^2.0.12",
+                "pug-parser": "^5.0.1",
+                "pug-runtime": "^2.0.5",
+                "pug-strip-comments": "^1.0.4"
+            }
+        },
+        "pug-attrs": {
+            "version": "2.0.4",
+            "resolved": "https://registry.npmjs.org/pug-attrs/-/pug-attrs-2.0.4.tgz",
+            "integrity": "sha512-TaZ4Z2TWUPDJcV3wjU3RtUXMrd3kM4Wzjbe3EWnSsZPsJ3LDI0F3yCnf2/W7PPFF+edUFQ0HgDL1IoxSz5K8EQ==",
+            "requires": {
+                "constantinople": "^3.0.1",
+                "js-stringify": "^1.0.1",
+                "pug-runtime": "^2.0.5"
+            }
+        },
+        "pug-code-gen": {
+            "version": "2.0.2",
+            "resolved": "https://registry.npmjs.org/pug-code-gen/-/pug-code-gen-2.0.2.tgz",
+            "integrity": "sha512-kROFWv/AHx/9CRgoGJeRSm+4mLWchbgpRzTEn8XCiwwOy6Vh0gAClS8Vh5TEJ9DBjaP8wCjS3J6HKsEsYdvaCw==",
+            "requires": {
+                "constantinople": "^3.1.2",
+                "doctypes": "^1.1.0",
+                "js-stringify": "^1.0.1",
+                "pug-attrs": "^2.0.4",
+                "pug-error": "^1.3.3",
+                "pug-runtime": "^2.0.5",
+                "void-elements": "^2.0.1",
+                "with": "^5.0.0"
+            }
+        },
+        "pug-error": {
+            "version": "1.3.3",
+            "resolved": "https://registry.npmjs.org/pug-error/-/pug-error-1.3.3.tgz",
+            "integrity": "sha512-qE3YhESP2mRAWMFJgKdtT5D7ckThRScXRwkfo+Erqga7dyJdY3ZquspprMCj/9sJ2ijm5hXFWQE/A3l4poMWiQ=="
+        },
+        "pug-filters": {
+            "version": "3.1.1",
+            "resolved": "https://registry.npmjs.org/pug-filters/-/pug-filters-3.1.1.tgz",
+            "integrity": "sha512-lFfjNyGEyVWC4BwX0WyvkoWLapI5xHSM3xZJFUhx4JM4XyyRdO8Aucc6pCygnqV2uSgJFaJWW3Ft1wCWSoQkQg==",
+            "requires": {
+                "clean-css": "^4.1.11",
+                "constantinople": "^3.0.1",
+                "jstransformer": "1.0.0",
+                "pug-error": "^1.3.3",
+                "pug-walk": "^1.1.8",
+                "resolve": "^1.1.6",
+                "uglify-js": "^2.6.1"
+            }
+        },
+        "pug-lexer": {
+            "version": "4.1.0",
+            "resolved": "https://registry.npmjs.org/pug-lexer/-/pug-lexer-4.1.0.tgz",
+            "integrity": "sha512-i55yzEBtjm0mlplW4LoANq7k3S8gDdfC6+LThGEvsK4FuobcKfDAwt6V4jKPH9RtiE3a2Akfg5UpafZ1OksaPA==",
+            "requires": {
+                "character-parser": "^2.1.1",
+                "is-expression": "^3.0.0",
+                "pug-error": "^1.3.3"
+            }
+        },
+        "pug-linker": {
+            "version": "3.0.6",
+            "resolved": "https://registry.npmjs.org/pug-linker/-/pug-linker-3.0.6.tgz",
+            "integrity": "sha512-bagfuHttfQOpANGy1Y6NJ+0mNb7dD2MswFG2ZKj22s8g0wVsojpRlqveEQHmgXXcfROB2RT6oqbPYr9EN2ZWzg==",
+            "requires": {
+                "pug-error": "^1.3.3",
+                "pug-walk": "^1.1.8"
+            }
+        },
+        "pug-load": {
+            "version": "2.0.12",
+            "resolved": "https://registry.npmjs.org/pug-load/-/pug-load-2.0.12.tgz",
+            "integrity": "sha512-UqpgGpyyXRYgJs/X60sE6SIf8UBsmcHYKNaOccyVLEuT6OPBIMo6xMPhoJnqtB3Q3BbO4Z3Bjz5qDsUWh4rXsg==",
+            "requires": {
+                "object-assign": "^4.1.0",
+                "pug-walk": "^1.1.8"
+            }
+        },
+        "pug-parser": {
+            "version": "5.0.1",
+            "resolved": "https://registry.npmjs.org/pug-parser/-/pug-parser-5.0.1.tgz",
+            "integrity": "sha512-nGHqK+w07p5/PsPIyzkTQfzlYfuqoiGjaoqHv1LjOv2ZLXmGX1O+4Vcvps+P4LhxZ3drYSljjq4b+Naid126wA==",
+            "requires": {
+                "pug-error": "^1.3.3",
+                "token-stream": "0.0.1"
+            }
+        },
+        "pug-runtime": {
+            "version": "2.0.5",
+            "resolved": "https://registry.npmjs.org/pug-runtime/-/pug-runtime-2.0.5.tgz",
+            "integrity": "sha512-P+rXKn9un4fQY77wtpcuFyvFaBww7/91f3jHa154qU26qFAnOe6SW1CbIDcxiG5lLK9HazYrMCCuDvNgDQNptw=="
+        },
+        "pug-strip-comments": {
+            "version": "1.0.4",
+            "resolved": "https://registry.npmjs.org/pug-strip-comments/-/pug-strip-comments-1.0.4.tgz",
+            "integrity": "sha512-i5j/9CS4yFhSxHp5iKPHwigaig/VV9g+FgReLJWWHEHbvKsbqL0oP/K5ubuLco6Wu3Kan5p7u7qk8A4oLLh6vw==",
+            "requires": {
+                "pug-error": "^1.3.3"
+            }
+        },
+        "pug-walk": {
+            "version": "1.1.8",
+            "resolved": "https://registry.npmjs.org/pug-walk/-/pug-walk-1.1.8.tgz",
+            "integrity": "sha512-GMu3M5nUL3fju4/egXwZO0XLi6fW/K3T3VTgFQ14GxNi8btlxgT5qZL//JwZFm/2Fa64J/PNS8AZeys3wiMkVA=="
+        },
         "pump": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
@@ -14170,6 +14457,14 @@
             "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs=",
             "dev": true
         },
+        "right-align": {
+            "version": "0.1.3",
+            "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz",
+            "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=",
+            "requires": {
+                "align-text": "^0.1.1"
+            }
+        },
         "rimraf": {
             "version": "3.0.2",
             "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
@@ -15835,6 +16130,11 @@
             "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
             "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
         },
+        "token-stream": {
+            "version": "0.0.1",
+            "resolved": "https://registry.npmjs.org/token-stream/-/token-stream-0.0.1.tgz",
+            "integrity": "sha1-zu78cXp2xDFvEm0LnbqlXX598Bo="
+        },
         "touch": {
             "version": "3.1.0",
             "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz",
@@ -16136,6 +16436,50 @@
             "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.21.tgz",
             "integrity": "sha512-+O8/qh/Qj8CgC6eYBVBykMrNtp5Gebn4dlGD/kKXVkJNDwyrAwSIqwz8CDf+tsAIWVycKcku6gIXJ0qwx/ZXaQ=="
         },
+        "uglify-js": {
+            "version": "2.8.29",
+            "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.8.29.tgz",
+            "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=",
+            "requires": {
+                "source-map": "~0.5.1",
+                "uglify-to-browserify": "~1.0.0",
+                "yargs": "~3.10.0"
+            },
+            "dependencies": {
+                "camelcase": {
+                    "version": "1.2.1",
+                    "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz",
+                    "integrity": "sha1-m7UwTS4LVmmLLHWLCKPqqdqlijk="
+                },
+                "cliui": {
+                    "version": "2.1.0",
+                    "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
+                    "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=",
+                    "requires": {
+                        "center-align": "^0.1.1",
+                        "right-align": "^0.1.1",
+                        "wordwrap": "0.0.2"
+                    }
+                },
+                "yargs": {
+                    "version": "3.10.0",
+                    "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz",
+                    "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=",
+                    "requires": {
+                        "camelcase": "^1.0.2",
+                        "cliui": "^2.1.0",
+                        "decamelize": "^1.0.0",
+                        "window-size": "0.1.0"
+                    }
+                }
+            }
+        },
+        "uglify-to-browserify": {
+            "version": "1.0.2",
+            "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz",
+            "integrity": "sha1-bgkk1r2mta/jSeOabWMoUKD4grc=",
+            "optional": true
+        },
         "uid-safe": {
             "version": "2.1.5",
             "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz",
@@ -16473,6 +16817,11 @@
             "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
             "dev": true
         },
+        "void-elements": {
+            "version": "2.0.1",
+            "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-2.0.1.tgz",
+            "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w="
+        },
         "vue-template-compiler": {
             "version": "2.6.11",
             "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.6.11.tgz",
@@ -17330,6 +17679,20 @@
                 "infobox-parser": "3.3.1"
             }
         },
+        "window-size": {
+            "version": "0.1.0",
+            "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz",
+            "integrity": "sha1-VDjNLqk7IC76Ohn+iIeu58lPnJ0="
+        },
+        "with": {
+            "version": "5.1.1",
+            "resolved": "https://registry.npmjs.org/with/-/with-5.1.1.tgz",
+            "integrity": "sha1-+k2qktrzLE6pTtRTyB8EaGtXXf4=",
+            "requires": {
+                "acorn": "^3.1.0",
+                "acorn-globals": "^3.0.0"
+            }
+        },
         "word-wrap": {
             "version": "1.2.3",
             "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
@@ -17346,6 +17709,11 @@
                 "its-set": "^1.1.5"
             }
         },
+        "wordwrap": {
+            "version": "0.0.2",
+            "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz",
+            "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8="
+        },
         "wordwrapjs": {
             "version": "3.0.0",
             "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz",
diff --git a/package.json b/package.json
index 1a92656bf..ca82d523d 100644
--- a/package.json
+++ b/package.json
@@ -192,6 +192,7 @@
         "prosemirror-state": "^1.3.2",
         "prosemirror-transform": "^1.2.3",
         "prosemirror-view": "^1.13.8",
+        "pug": "^2.0.4",
         "puppeteer": "^3.1.0",
         "query-string": "^6.10.1",
         "raw-loader": "^1.0.0",
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index 8841f7307..b7a75dfb9 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -5,7 +5,7 @@ import {
     faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
     faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
     faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote,
-    faThumbtack, faTree, faTv, faUndoAlt, faVideo
+    faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye
 } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, configure, observable, reaction, runInAction } from 'mobx';
@@ -118,7 +118,7 @@ export class MainView extends React.Component {
             faQuestionCircle, faArrowLeft, faArrowRight, faArrowDown, faArrowUp, faBolt, faBullseye, faCaretUp, faCat, faCheck, faChevronRight, faClipboard, faClone, faCloudUploadAlt,
             faCommentAlt, faCompressArrowsAlt, faCut, faEllipsisV, faEraser, faExclamation, faFileAlt, faFileAudio, faFilePdf, faFilm, faFilter, faFont, faGlobeAsia, faHighlighter,
             faLongArrowAltRight, faMicrophone, faMousePointer, faMusic, faObjectGroup, faPause, faPen, faPenNib, faPhone, faPlay, faPortrait, faRedoAlt, faStamp, faStickyNote, faTrashAlt, faAngleRight, faBell,
-            faThumbtack, faTree, faTv, faUndoAlt, faVideo);
+            faThumbtack, faTree, faTv, faUndoAlt, faVideo, faAsterisk, faBrain, faImage, faPaintBrush, faTimes, faEye);
         this.initEventListeners();
         this.initAuthenticationRouters();
     }
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 972c09484..9d880d294 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -207,7 +207,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                             const d = droppedDocs[i];
                             const layoutDoc = Doc.Layout(d);
                             if (this.Document.currentTimecode !== undefined && !this.props.isAnnotationOverlay) {
-                                CollectionFreeFormDocumentView.setValues(this.Document.currentTimecode, d, x + NumCast(d.x) - dropX, y + NumCast(d.y) - dropY, Cast(d.opacity, "number", null));
+                                const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.displayTimecode, 1000));
+                                CollectionFreeFormDocumentView.setValues(this.Document.currentTimecode, d, x + vals.x - dropX, y + vals.y - dropY, vals.opacity);
                             } else {
                                 d.x = x + NumCast(d.x) - dropX;
                                 d.y = y + NumCast(d.y) - dropY;
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 57f484214..a4120f958 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -100,13 +100,14 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
 
     public static setupKeyframes(docs: Doc[], timecode: number, collection: Doc) {
-        docs.forEach(doc => {
-            doc["x-indexed"] = new List<number>(numberRange(timecode).map(i => undefined) as any as number[]);
-            doc["y-indexed"] = new List<number>(numberRange(timecode).map(i => undefined) as any as number[]);
-            doc["opacity-indexed"] = new List<number>(numberRange(timecode).map(i => 0));
-            (doc["x-indexed"] as any).push(NumCast(doc.x));
-            (doc["y-indexed"] as any).push(NumCast(doc.y));
-            (doc["opacity-indexed"] as any).push(NumCast(doc.opacity, 1));
+        docs.forEach((doc, i) => {
+            const xlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
+            const ylist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
+            xlist[Math.max(i - 1)] = xlist[timecode + 1] = NumCast(doc.x);
+            ylist[Math.max(i - 1)] = ylist[timecode + 1] = NumCast(doc.y);
+            doc["x-indexed"] = xlist;
+            doc["y-indexed"] = ylist;
+            doc["opacity-indexed"] = new List<number>(numberRange(timecode).map(i => 1));
             doc.displayTimecode = ComputedField.MakeFunction("collection ? collection.currentTimecode : 0", {}, { collection });
             doc.x = ComputedField.MakeInterpolated("x", "displayTimecode");
             doc.y = ComputedField.MakeInterpolated("y", "displayTimecode");
diff --git a/src/client/views/nodes/ComparisonBox.tsx b/src/client/views/nodes/ComparisonBox.tsx
index a14e39bd6..d61934380 100644
--- a/src/client/views/nodes/ComparisonBox.tsx
+++ b/src/client/views/nodes/ComparisonBox.tsx
@@ -1,6 +1,3 @@
-import { library } from '@fortawesome/fontawesome-svg-core';
-import { faEye } from '@fortawesome/free-regular-svg-icons';
-import { faAsterisk, faBrain, faFileAudio, faImage, faPaintBrush, faTimes, faCloudUploadAlt } from '@fortawesome/free-solid-svg-icons';
 import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
 import { action, computed, observable, runInAction, Lambda, IReactionDisposer } from 'mobx';
 import { observer } from "mobx-react";
@@ -19,9 +16,6 @@ import { setupMoveUpEvents, emptyFunction } from '../../../Utils';
 import { SnappingManager } from '../../util/SnappingManager';
 import { DocumentViewProps } from './DocumentView';
 
-library.add(faImage, faEye as any, faPaintBrush, faBrain);
-library.add(faFileAudio, faAsterisk);
-
 export const comparisonSchema = createSchema({});
 
 type ComparisonDocument = makeInterface<[typeof comparisonSchema, typeof documentSchema]>;
@@ -29,18 +23,16 @@ const ComparisonDocument = makeInterface(comparisonSchema, documentSchema);
 
 @observer
 export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, ComparisonDocument>(ComparisonDocument) {
-    protected multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined;
-
     public static LayoutString(fieldKey: string) { return FieldView.LayoutString(ComparisonBox, fieldKey); }
+    protected multiTouchDisposer?: import("../../util/InteractionUtils").InteractionUtils.MultiTouchEventDisposer | undefined;
+    private _disposers: (DragManager.DragDropDisposer | undefined)[] = [undefined, undefined];
 
     @observable _animating = "";
-    private _beforeDropDisposer?: DragManager.DragDropDisposer;
-    private _afterDropDisposer?: DragManager.DragDropDisposer;
 
-    protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposer: Opt<DragManager.DragDropDisposer>) => {
-        disposer?.();
+    protected createDropTarget = (ele: HTMLDivElement | null, fieldKey: string, disposerId: number) => {
+        this._disposers[disposerId]?.();
         if (ele) {
-            return DragManager.MakeDropTarget(ele, (event, dropEvent) => this.dropHandler(event, dropEvent, fieldKey), this.layoutDoc);
+            this._disposers[disposerId] = DragManager.MakeDropTarget(ele, (e, dropEvent) => this.dropHandler(e, dropEvent, fieldKey), this.layoutDoc);
         }
     }
 
@@ -74,7 +66,6 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
     @undoBatch
     clearDoc = (e: React.MouseEvent, fieldKey: string) => {
         e.stopPropagation;
-        e.preventDefault;
         delete this.dataDoc[fieldKey];
     }
 
@@ -82,8 +73,8 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
         const clipWidth = NumCast(this.dataDoc.clipWidth) + "%";
         const childProps: DocumentViewProps = { ...this.props, pointerEvents: false, parentActive: this.props.active };
         const clearButton = (which: string) => {
-            return <div className={`clear-button ${which}`} onClick={e => this.clearDoc(e, `${which}Doc`)}>
-                <FontAwesomeIcon className={`clear-button ${which}`} icon={faTimes} size="sm" />
+            return <div className={`clear-button ${which}`} onPointerDown={e => e.stopPropagation()} onClick={e => this.clearDoc(e, `${which}Doc`)}>
+                <FontAwesomeIcon className={`clear-button ${which}`} icon={"times"} size="sm" />
             </div>
         }
         const displayDoc = (which: string) => {
@@ -93,23 +84,22 @@ export class ComparisonBox extends ViewBoxAnnotatableComponent<FieldViewProps, C
                 {clearButton(which)}
             </> :  // placeholder image if doc is missing
                 <div className="placeholder">
-                    <FontAwesomeIcon className="upload-icon" icon={faCloudUploadAlt} size="lg" />
+                    <FontAwesomeIcon className="upload-icon" icon={"cloud-upload-alt"} size="lg" />
                 </div>
         }
+        const displayBox = (which: string, index: number, cover: number) => {
+            return <div className={`${which}Box-cont`} key={which} style={{ width: this.props.PanelWidth() }}
+                onPointerDown={e => this.registerSliding(e, cover)}
+                ref={ele => this.createDropTarget(ele, `${which}Doc`, index)} >
+                {displayDoc(which)}
+            </div>;
+        }
 
         return (
             <div className={`comparisonBox${this.active() || SnappingManager.GetIsDragging() ? "-interactive" : ""}`}>
-                <div className="afterBox-cont" key={"after"} style={{ width: this.props.PanelWidth() }}
-                    onPointerDown={e => this.registerSliding(e, this.props.PanelWidth() - 5)}
-                    ref={ele => this._afterDropDisposer = this.createDropTarget(ele, "afterDoc", this._afterDropDisposer)} >
-                    {displayDoc("after")}
-                </div>
+                {displayBox("after", 1, this.props.PanelWidth() - 5)}
                 <div className="clip-div" style={{ width: clipWidth, transition: this._animating, background: StrCast(this.layoutDoc._backgroundColor, "gray") }}>
-                    <div className="beforeBox-cont" key={"before"} style={{ width: this.props.PanelWidth() }}
-                        onPointerDown={e => this.registerSliding(e, 5)}
-                        ref={ele => this._beforeDropDisposer = this.createDropTarget(ele, "beforeDoc", this._beforeDropDisposer)} >
-                        {displayDoc("before")}
-                    </div>
+                    {displayBox("before", 0, 5)}
                 </div>
 
                 <div className="slide-bar" style={{ left: `calc(${clipWidth} - 0.5px)` }}>
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index f364b40fd..526a3dbf4 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -104,7 +104,6 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         if (this.rootDoc.presProgressivize && !rootTarget?.lastTimecode) {
             rootTarget.currentTimecode = 0;
             CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, this.presBox);
-            docs.forEach((d, i) => numberRange(docs.length - i).forEach(f => Cast(d["opacity-indexed"], listSpec("number"), [])[f + i] = 1));
             rootTarget.lastTimecode = docs.length - 1;
         }
         docs.forEach((d, i) => i && numberRange(i).forEach(f => Cast(d["opacity-indexed"], listSpec("number"), [])[f] = 0));
-- 
cgit v1.2.3-70-g09d2


From 43818b137486f3d4431e1c3b9f4de0b0aefba9ca Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 23 May 2020 14:59:01 -0400
Subject: several fixes to progressivization and added UI for editing by
 suspending transparency

---
 .../collectionFreeForm/CollectionFreeFormView.scss |  9 ++++
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 50 +++++++++++++++-------
 .../collections/collectionFreeForm/MarqueeView.tsx |  4 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 14 +++---
 src/client/views/nodes/KeyValuePair.tsx            |  4 +-
 .../views/presentationview/PresElementBox.tsx      |  5 +--
 src/fields/ScriptField.ts                          | 17 ++++----
 src/fields/util.ts                                 |  2 +-
 8 files changed, 66 insertions(+), 39 deletions(-)

(limited to 'src/client/views/presentationview/PresElementBox.tsx')

diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
index 7a84fcde1..5478a1c4a 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.scss
@@ -51,12 +51,21 @@
     }
     .backKeyframe {
         right:45;
+        svg {
+            display:block;
+            margin:auto;
+        }
     }
     .numKeyframe {
         right:25;
+        text-align:center;
     }
     .fwdKeyframe {
         right:5;
+        svg {
+            display:block;
+            margin:auto;
+        }
     }
 
     .collectionfreeformview-placeholder {
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 4b218bc18..d0415f77d 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -126,21 +126,39 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         FormattedTextBox.SelectOnLoad = newBox[Id];// track the new text box so we can give it a prop that tells it to focus itself when it's displayed
         this.addDocument(newBox);
     }
-    addDocument = (newBox: Doc | Doc[]) => {
-        if (this.Document.currentTimecode !== undefined && !this.props.isAnnotationOverlay) {
-            CollectionFreeFormDocumentView.setupKeyframes((newBox instanceof Doc) ? [newBox] : newBox, this.Document.currentTimecode, this.props.Document);
-        }
-
+    addDocument = action((newBox: Doc | Doc[]) => {
+        let retVal = false;
         if (newBox instanceof Doc) {
-            const added = this.props.addDocument(newBox);
-            added && this.bringToFront(newBox);
-            added && this.updateCluster(newBox);
-            return added;
+            retVal = this.props.addDocument(newBox);
+            retVal && this.bringToFront(newBox);
+            retVal && this.updateCluster(newBox);
         } else {
-            return this.props.addDocument(newBox);
+            retVal = this.props.addDocument(newBox);
             // bcz: deal with clusters
         }
-    }
+        if (retVal) {
+            const newBoxes = (newBox instanceof Doc) ? [newBox] : newBox;
+            for (let i = 0; i < newBoxes.length; i++) {
+                const newBox = newBoxes[i];
+                if (newBox.displayTimecode !== undefined) {
+                    const x = newBox.x;
+                    const y = newBox.y;
+                    delete newBox["x-indexed"];
+                    delete newBox["y-indexed"];
+                    delete newBox["opacity-indexed"];
+                    delete newBox.x;
+                    delete newBox.y;
+                    delete newBox.displayTimecode;
+                    newBox.x = x;
+                    newBox.y = y;
+                }
+            }
+            if (this.Document.currentTimecode !== undefined && !this.props.isAnnotationOverlay) {
+                CollectionFreeFormDocumentView.setupKeyframes(newBoxes, this.Document.currentTimecode);
+            }
+        }
+        return retVal;
+    })
 
     @undoBatch
     @action
@@ -148,7 +166,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const currentTimecode = this.Document.currentTimecode;
         if (currentTimecode === undefined) {
             this.Document.currentTimecode = 0;
-            CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0, this.props.Document);
+            CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
         }
         CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentTimecode || 0);
         this.Document.currentTimecode = Math.max(0, (currentTimecode || 0) + 1);
@@ -160,7 +178,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const currentTimecode = this.Document.currentTimecode;
         if (currentTimecode === undefined) {
             this.Document.currentTimecode = 0;
-            CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0, this.props.Document);
+            CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
         }
         CollectionFreeFormDocumentView.gotoKeyframe(this.childDocs.slice());
         this.Document.currentTimecode = Math.max(0, (currentTimecode || 0) - 1);
@@ -992,7 +1010,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         const { z, color, zIndex } = params.pair.layout;
         return {
             x: NumCast(x), y: NumCast(y), z: Cast(z, "number"), color: StrCast(color), zIndex: Cast(zIndex, "number"),
-            transition: StrCast(layoutDoc.transition), opacity: Cast(opacity, "number", null),
+            transition: StrCast(layoutDoc.transition), opacity: this.Document.editing ? 1 : Cast(opacity, "number", null),
             width: Cast(layoutDoc._width, "number"), height: Cast(layoutDoc._height, "number"), pair: params.pair, replica: ""
         };
     }
@@ -1376,8 +1394,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                     <div key="back" className="backKeyframe" onClick={this.prevKeyframe}>
                         <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
                     </div>
-                    <div key="num" className="numKeyframe" >
-                        {NumCast(this.props.Document.currentTimecode)}
+                    <div key="num" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }} onClick={action(() => this.Document.editing = !this.Document.editing)} >
+                        {NumCast(this.Document.currentTimecode)}
                     </div>
                     <div key="fwd" className="fwdKeyframe" onClick={this.nextKeyframe}>
                         <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
diff --git a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
index c99e74ccd..ed70ac9e8 100644
--- a/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
+++ b/src/client/views/collections/collectionFreeForm/MarqueeView.tsx
@@ -334,9 +334,7 @@ export class MarqueeView extends React.Component<SubCollectionViewProps & Marque
             _LODdisable: true,
             title: "a nested collection",
         });
-        // const dataExtensionField = Doc.CreateDocumentExtensionForField(newCollection, "data");
-        // dataExtensionField.ink = inkData ? new InkField(this.marqueeInkSelect(inkData)) : undefined;
-        // this.marqueeInkDelete(inkData);
+        selected.forEach(d => d.context = newCollection);
         this.hideMarquee();
         return newCollection;
     }
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index a4120f958..88fbdd589 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -77,6 +77,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
 
     public static setValues(timecode: number, d: Doc, x?: number, y?: number, opacity?: number) {
+        Cast(d["x-indexed"], listSpec("number"), [])[Math.max(0, timecode - 1)] = x as any as number;
+        Cast(d["y-indexed"], listSpec("number"), null)[Math.max(0, timecode - 1)] = y as any as number;
         Cast(d["x-indexed"], listSpec("number"), [])[timecode] = x as any as number;
         Cast(d["y-indexed"], listSpec("number"), null)[timecode] = y as any as number;
         Cast(d["opacity-indexed"], listSpec("number"), null)[timecode] = opacity as any as number;
@@ -99,16 +101,18 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         setTimeout(() => docs.forEach(doc => doc.transition = undefined), 1010);
     }
 
-    public static setupKeyframes(docs: Doc[], timecode: number, collection: Doc) {
+    public static setupKeyframes(docs: Doc[], timecode: number, progressivize: boolean = false) {
         docs.forEach((doc, i) => {
+            const curTimecode = progressivize ? i : timecode;
             const xlist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
             const ylist = new List<number>(numberRange(timecode + 1).map(i => undefined) as any as number[]);
-            xlist[Math.max(i - 1)] = xlist[timecode + 1] = NumCast(doc.x);
-            ylist[Math.max(i - 1)] = ylist[timecode + 1] = NumCast(doc.y);
+            const olist = new List<number>(numberRange(timecode + 1).map(t => progressivize && t < i ? 0 : 1));
+            xlist[Math.max(curTimecode - 1, 0)] = xlist[curTimecode] = NumCast(doc.x);
+            ylist[Math.max(curTimecode - 1, 0)] = ylist[curTimecode] = NumCast(doc.y);
             doc["x-indexed"] = xlist;
             doc["y-indexed"] = ylist;
-            doc["opacity-indexed"] = new List<number>(numberRange(timecode).map(i => 1));
-            doc.displayTimecode = ComputedField.MakeFunction("collection ? collection.currentTimecode : 0", {}, { collection });
+            doc["opacity-indexed"] = olist;
+            doc.displayTimecode = ComputedField.MakeFunction("self.context ? (self.context.currentTimecode||0) : 0");
             doc.x = ComputedField.MakeInterpolated("x", "displayTimecode");
             doc.y = ComputedField.MakeInterpolated("y", "displayTimecode");
             doc.opacity = ComputedField.MakeInterpolated("opacity", "displayTimecode");
diff --git a/src/client/views/nodes/KeyValuePair.tsx b/src/client/views/nodes/KeyValuePair.tsx
index 956d6556b..3cbe3e494 100644
--- a/src/client/views/nodes/KeyValuePair.tsx
+++ b/src/client/views/nodes/KeyValuePair.tsx
@@ -99,9 +99,9 @@ export class KeyValuePair extends React.Component<KeyValuePairProps> {
                     <div className="keyValuePair-td-key-container">
                         <button style={hover} className="keyValuePair-td-key-delete" onClick={undoBatch(() => {
                             if (Object.keys(props.Document).indexOf(props.fieldKey) !== -1) {
-                                props.Document[props.fieldKey] = undefined;
+                                delete props.Document[props.fieldKey];
                             }
-                            else props.Document.proto![props.fieldKey] = undefined;
+                            else delete props.Document.proto![props.fieldKey];
                         })}>
                             X
                         </button>
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 526a3dbf4..364c1d060 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -101,12 +101,11 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         this.rootDoc.presProgressivize = !this.rootDoc.presProgressivize;
         const rootTarget = Cast(this.rootDoc.presentationTargetDoc, Doc, null);
         const docs = DocListCast(rootTarget[Doc.LayoutFieldKey(rootTarget)]);
-        if (this.rootDoc.presProgressivize && !rootTarget?.lastTimecode) {
+        if (this.rootDoc.presProgressivize) {
             rootTarget.currentTimecode = 0;
-            CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, this.presBox);
+            CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, true);
             rootTarget.lastTimecode = docs.length - 1;
         }
-        docs.forEach((d, i) => i && numberRange(i).forEach(f => Cast(d["opacity-indexed"], listSpec("number"), [])[f] = 0));
     }
 
     /**
diff --git a/src/fields/ScriptField.ts b/src/fields/ScriptField.ts
index 503c60790..5192af407 100644
--- a/src/fields/ScriptField.ts
+++ b/src/fields/ScriptField.ts
@@ -65,14 +65,14 @@ export class ScriptField extends ObjectField {
     @serializable(autoObject())
     private captures?: ProxyField<Doc>;
 
-    constructor(script: CompiledScript, setterscript?: CompileResult) {
+    constructor(script: CompiledScript, setterscript?: CompiledScript) {
         super();
 
         if (script?.options.capturedVariables) {
             const doc = Doc.assign(new Doc, script.options.capturedVariables);
             this.captures = new ProxyField(doc);
         }
-        this.setterscript = setterscript?.compiled ? setterscript : undefined;
+        this.setterscript = setterscript;
         this.script = script;
     }
 
@@ -98,10 +98,10 @@ export class ScriptField extends ObjectField {
     //     }
 
     [Copy](): ObjectField {
-        return new ScriptField(this.script);
+        return new ScriptField(this.script, this.setterscript);
     }
     toString() {
-        return `${this.script.originalScript}`;
+        return `${this.script.originalScript} + ${this.setterscript?.originalScript}`;
     }
 
     [ToScriptString]() {
@@ -141,22 +141,21 @@ export class ComputedField extends ScriptField {
 
 
     [Copy](): ObjectField {
-        return new ComputedField(this.script);
+        return new ComputedField(this.script, this.setterscript);
     }
 
     public static MakeScript(script: string, params: object = {}) {
         const compiled = ScriptField.CompileScript(script, params, false);
         return compiled.compiled ? new ComputedField(compiled) : undefined;
     }
-    public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Field }, setterScript?: string) {
+    public static MakeFunction(script: string, params: object = {}, capturedVariables?: { [name: string]: Field }) {
         const compiled = ScriptField.CompileScript(script, params, true, capturedVariables);
-        const setCompiled = setterScript ? ScriptField.CompileScript(setterScript, params, true, capturedVariables) : undefined;
-        return compiled.compiled ? new ComputedField(compiled, setCompiled?.compiled ? setCompiled : undefined) : undefined;
+        return compiled.compiled ? new ComputedField(compiled) : undefined;
     }
     public static MakeInterpolated(fieldKey: string, interpolatorKey: string) {
         const getField = ScriptField.CompileScript(`getIndexVal(self['${fieldKey}-indexed'], self.${interpolatorKey})`, {}, true, {});
         const setField = ScriptField.CompileScript(`(self['${fieldKey}-indexed'])[self.${interpolatorKey}] = value`, { value: "any" }, true, {});
-        return getField.compiled ? new ComputedField(getField, setField?.compiled ? setField : undefined) : undefined;
+        return getField.compiled && setField.compiled ? new ComputedField(getField, setField) : undefined;
     }
 }
 
diff --git a/src/fields/util.ts b/src/fields/util.ts
index a287b0210..024c0f80e 100644
--- a/src/fields/util.ts
+++ b/src/fields/util.ts
@@ -116,7 +116,7 @@ export function setter(target: any, in_prop: string | symbol | number, value: an
             return true;
         }
     }
-    if (target.__fields[prop] instanceof ComputedField && target.__fields[prop].setterscript) {
+    if (target.__fields[prop] instanceof ComputedField && target.__fields[prop].setterscript && value !== undefined && !(value instanceof ComputedField)) {
         return ScriptCast(target.__fields[prop])?.setterscript?.run({ self: target[SelfProxy], this: target[SelfProxy], value }).success ? true : false;
     }
     return _setter(target, prop, value, receiver);
-- 
cgit v1.2.3-70-g09d2


From 2ba063ff94a04e89ee1fa1fde7d71a839f5d6856 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 23 May 2020 23:25:22 -0400
Subject: switched frame animations to use currentFrame and activeFrame to fix
 aliasing issue of progressive slides at different frame codes

---
 src/client/documents/Documents.ts                  |  2 ++
 src/client/views/MainView.tsx                      |  6 +---
 .../collectionFreeForm/CollectionFreeFormView.tsx  | 41 +++++++++++-----------
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 25 +++++++------
 src/client/views/nodes/PresBox.tsx                 |  6 ++--
 .../views/presentationview/PresElementBox.tsx      |  2 +-
 src/fields/documentSchemas.ts                      |  6 ++--
 7 files changed, 46 insertions(+), 42 deletions(-)

(limited to 'src/client/views/presentationview/PresElementBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 6b17b4303..2be961108 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -126,6 +126,8 @@ export interface DocumentOptions {
     curPage?: number;
     currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video)  value is in seconds
     displayTimecode?: number; // the time that a document should be displayed (e.g., time an annotation should be displayed on a video)
+    currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide)
+    activeFrame?: number; // the active frame of a document in a frame base collection
     borderRounding?: string;
     boxShadow?: string;
     dontRegisterChildViews?: boolean;
diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx
index b7a75dfb9..358de2333 100644
--- a/src/client/views/MainView.tsx
+++ b/src/client/views/MainView.tsx
@@ -139,10 +139,7 @@ export class MainView extends React.Component {
 
     initEventListeners = () => {
         window.addEventListener("drop", (e) => { e.preventDefault(); }, false); // drop event handler
-        window.addEventListener("dragover", (e) => {
-            console.log("MDRAG");
-            e.preventDefault();
-        }, false); // drag event handler
+        window.addEventListener("dragover", (e) => { e.preventDefault(); }, false); // drag event handler
         // click interactions for the context menu
         document.addEventListener("pointerdown", this.globalPointerDown);
         document.addEventListener("pointerup", this.globalPointerUp);
@@ -246,7 +243,6 @@ export class MainView extends React.Component {
     onDrop = (e: React.DragEvent<HTMLDivElement>) => {
         e.preventDefault();
         e.stopPropagation();
-        console.log("Drop");
     }
 
     @action
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index d0415f77d..91e257f80 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -56,6 +56,7 @@ export const panZoomSchema = createSchema({
     scale: "number",
     currentTimecode: "number",
     displayTimecode: "number",
+    currentFrame: "number",
     arrangeScript: ScriptField,
     arrangeInit: ScriptField,
     useClusters: "boolean",
@@ -140,7 +141,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             const newBoxes = (newBox instanceof Doc) ? [newBox] : newBox;
             for (let i = 0; i < newBoxes.length; i++) {
                 const newBox = newBoxes[i];
-                if (newBox.displayTimecode !== undefined) {
+                if (newBox.activeFrame !== undefined) {
                     const x = newBox.x;
                     const y = newBox.y;
                     delete newBox["x-indexed"];
@@ -148,13 +149,13 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                     delete newBox["opacity-indexed"];
                     delete newBox.x;
                     delete newBox.y;
-                    delete newBox.displayTimecode;
+                    delete newBox.activeFrame;
                     newBox.x = x;
                     newBox.y = y;
                 }
             }
-            if (this.Document.currentTimecode !== undefined && !this.props.isAnnotationOverlay) {
-                CollectionFreeFormDocumentView.setupKeyframes(newBoxes, this.Document.currentTimecode);
+            if (this.Document.currentFrame !== undefined && !this.props.isAnnotationOverlay) {
+                CollectionFreeFormDocumentView.setupKeyframes(newBoxes, this.Document.currentFrame);
             }
         }
         return retVal;
@@ -163,25 +164,25 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
     @undoBatch
     @action
     nextKeyframe = (): void => {
-        const currentTimecode = this.Document.currentTimecode;
-        if (currentTimecode === undefined) {
-            this.Document.currentTimecode = 0;
+        const currentFrame = this.Document.currentFrame;
+        if (currentFrame === undefined) {
+            this.Document.currentFrame = 0;
             CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
         }
-        CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentTimecode || 0);
-        this.Document.currentTimecode = Math.max(0, (currentTimecode || 0) + 1);
-        this.Document.lastTimecode = Math.max(NumCast(this.Document.currentTimecode), NumCast(this.Document.lastTimecode));
+        CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentFrame || 0);
+        this.Document.currentFrame = Math.max(0, (currentFrame || 0) + 1);
+        this.Document.lastTimecode = Math.max(NumCast(this.Document.currentFrame), NumCast(this.Document.lastTimecode));
     }
     @undoBatch
     @action
     prevKeyframe = (): void => {
-        const currentTimecode = this.Document.currentTimecode;
-        if (currentTimecode === undefined) {
-            this.Document.currentTimecode = 0;
+        const currentFrame = this.Document.currentFrame;
+        if (currentFrame === undefined) {
+            this.Document.currentFrame = 0;
             CollectionFreeFormDocumentView.setupKeyframes(this.childDocs, 0);
         }
         CollectionFreeFormDocumentView.gotoKeyframe(this.childDocs.slice());
-        this.Document.currentTimecode = Math.max(0, (currentTimecode || 0) - 1);
+        this.Document.currentFrame = Math.max(0, (currentFrame || 0) - 1);
     }
 
     private selectDocuments = (docs: Doc[]) => {
@@ -232,9 +233,9 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                         for (let i = 0; i < droppedDocs.length; i++) {
                             const d = droppedDocs[i];
                             const layoutDoc = Doc.Layout(d);
-                            if (this.Document.currentTimecode !== undefined && !this.props.isAnnotationOverlay) {
-                                const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.displayTimecode, 1000));
-                                CollectionFreeFormDocumentView.setValues(this.Document.currentTimecode, d, x + vals.x - dropX, y + vals.y - dropY, vals.opacity);
+                            if (this.Document.currentFrame !== undefined && !this.props.isAnnotationOverlay) {
+                                const vals = CollectionFreeFormDocumentView.getValues(d, NumCast(d.activeFrame, 1000));
+                                CollectionFreeFormDocumentView.setValues(this.Document.currentFrame, d, x + vals.x - dropX, y + vals.y - dropY, vals.opacity);
                             } else {
                                 d.x = x + NumCast(d.x) - dropX;
                                 d.y = y + NumCast(d.y) - dropY;
@@ -1005,8 +1006,8 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
             return { x: 0, y: 0, transition: "transform 1s", ...result, pair: params.pair, replica: "" };
         }
         const layoutDoc = Doc.Layout(params.pair.layout);
-        const { x, y, opacity } = this.Document.currentTimecode === undefined ? params.pair.layout :
-            CollectionFreeFormDocumentView.getValues(params.pair.layout, this.Document.currentTimecode || 0);
+        const { x, y, opacity } = this.Document.currentFrame === undefined ? params.pair.layout :
+            CollectionFreeFormDocumentView.getValues(params.pair.layout, this.Document.currentFrame || 0);
         const { z, color, zIndex } = params.pair.layout;
         return {
             x: NumCast(x), y: NumCast(y), z: Cast(z, "number"), color: StrCast(color), zIndex: Cast(zIndex, "number"),
@@ -1395,7 +1396,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
                         <FontAwesomeIcon icon={"caret-left"} size={"lg"} />
                     </div>
                     <div key="num" className="numKeyframe" style={{ backgroundColor: this.Document.editing ? "#759c75" : "#c56565" }} onClick={action(() => this.Document.editing = !this.Document.editing)} >
-                        {NumCast(this.Document.currentTimecode)}
+                        {NumCast(this.Document.currentFrame)}
                     </div>
                     <div key="fwd" className="fwdKeyframe" onClick={this.nextKeyframe}>
                         <FontAwesomeIcon icon={"caret-right"} size={"lg"} />
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 88fbdd589..682aed8f5 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -69,21 +69,24 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     }
 
     public static getValues(doc: Doc, time: number) {
+        const timecode = Math.round(time);
         return ({
-            x: Cast(doc["x-indexed"], listSpec("number"), []).reduce((p, x, i) => (i <= time && x !== undefined) || p === undefined ? x : p, undefined as any as number),
-            y: Cast(doc["y-indexed"], listSpec("number"), []).reduce((p, y, i) => (i <= time && y !== undefined) || p === undefined ? y : p, undefined as any as number),
-            opacity: Cast(doc["opacity-indexed"], listSpec("number"), []).reduce((p, o, i) => i <= time || p === undefined ? o : p, undefined as any as number),
+            x: Cast(doc["x-indexed"], listSpec("number"), []).reduce((p, x, i) => (i <= timecode && x !== undefined) || p === undefined ? x : p, undefined as any as number),
+            y: Cast(doc["y-indexed"], listSpec("number"), []).reduce((p, y, i) => (i <= timecode && y !== undefined) || p === undefined ? y : p, undefined as any as number),
+            opacity: Cast(doc["opacity-indexed"], listSpec("number"), []).reduce((p, o, i) => i <= timecode || p === undefined ? o : p, undefined as any as number),
         });
     }
 
-    public static setValues(timecode: number, d: Doc, x?: number, y?: number, opacity?: number) {
+    public static setValues(time: number, d: Doc, x?: number, y?: number, opacity?: number) {
+        const timecode = Math.round(time);
         Cast(d["x-indexed"], listSpec("number"), [])[Math.max(0, timecode - 1)] = x as any as number;
-        Cast(d["y-indexed"], listSpec("number"), null)[Math.max(0, timecode - 1)] = y as any as number;
+        Cast(d["y-indexed"], listSpec("number"), [])[Math.max(0, timecode - 1)] = y as any as number;
         Cast(d["x-indexed"], listSpec("number"), [])[timecode] = x as any as number;
-        Cast(d["y-indexed"], listSpec("number"), null)[timecode] = y as any as number;
+        Cast(d["y-indexed"], listSpec("number"), [])[timecode] = y as any as number;
         Cast(d["opacity-indexed"], listSpec("number"), null)[timecode] = opacity as any as number;
     }
-    public static updateKeyframe(docs: Doc[], timecode: number) {
+    public static updateKeyframe(docs: Doc[], time: number) {
+        const timecode = Math.round(time);
         docs.forEach(doc => {
             const xindexed = Cast(doc['x-indexed'], listSpec("number"), null);
             const yindexed = Cast(doc['y-indexed'], listSpec("number"), null);
@@ -112,10 +115,10 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             doc["x-indexed"] = xlist;
             doc["y-indexed"] = ylist;
             doc["opacity-indexed"] = olist;
-            doc.displayTimecode = ComputedField.MakeFunction("self.context ? (self.context.currentTimecode||0) : 0");
-            doc.x = ComputedField.MakeInterpolated("x", "displayTimecode");
-            doc.y = ComputedField.MakeInterpolated("y", "displayTimecode");
-            doc.opacity = ComputedField.MakeInterpolated("opacity", "displayTimecode");
+            doc.activeFrame = ComputedField.MakeFunction("self.context ? (self.context.currentFrame||0) : 0");
+            doc.x = ComputedField.MakeInterpolated("x", "activeFrame");
+            doc.y = ComputedField.MakeInterpolated("y", "activeFrame");
+            doc.opacity = ComputedField.MakeInterpolated("opacity", "activeFrame");
         });
     }
 
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index aeb77a894..b76c06e2e 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -60,9 +60,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         this.updateCurrentPresentation();
         const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
         const lastFrame = Cast(presTargetDoc.lastTimecode, "number", null);
-        const curFrame = NumCast(presTargetDoc.currentTimecode);
+        const curFrame = NumCast(presTargetDoc.currentFrame);
         if (lastFrame !== undefined && curFrame < lastFrame) {
-            presTargetDoc.currentTimecode = curFrame + 1;
+            presTargetDoc.currentFrame = curFrame + 1;
         }
         else if (this.childDocs[this.itemIndex + 1] !== undefined) {
             let nextSelected = this.itemIndex + 1;
@@ -200,7 +200,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
             this.rootDoc._itemIndex = index;
             const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
             if (presTargetDoc.lastTimecode !== undefined) {
-                presTargetDoc.currentTimecode = 0;
+                presTargetDoc.currentFrame = 0;
             }
 
             if (!this.layoutDoc.presStatus) {
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 364c1d060..31ffde8af 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -102,7 +102,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         const rootTarget = Cast(this.rootDoc.presentationTargetDoc, Doc, null);
         const docs = DocListCast(rootTarget[Doc.LayoutFieldKey(rootTarget)]);
         if (this.rootDoc.presProgressivize) {
-            rootTarget.currentTimecode = 0;
+            rootTarget.currentFrame = 0;
             CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, true);
             rootTarget.lastTimecode = docs.length - 1;
         }
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index 142f7e079..7e11049ab 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -12,7 +12,9 @@ export const documentSchema = createSchema({
     links: listSpec(Doc),       // computed (readonly) list of links associated with this document
 
     // "Location" properties in a very general sense
-    currentTimecode: "number",  // current play back time of a temporal document (video / audio)
+    currentFrame: "number",     // current frame of a frame based collection (e.g., a progressive slide)
+    activeFrame: "number",      // the active frame of a frame based animated document 
+    urrentTimecode: "number",   // current play back time of a temporal document (video / audio)
     displayTimecode: "number",  // the time that a document should be displayed (e.g., time an annotation should be displayed on a video)
     inOverlay: "boolean",       // whether the document is rendered in an OverlayView which handles selection/dragging differently
     x: "number",                // x coordinate when in a freeform view 
@@ -77,7 +79,7 @@ export const documentSchema = createSchema({
     isBackground: "boolean",    // whether document is a background element and ignores input events (can only select with marquee)
     lockedPosition: "boolean",  // whether the document can be moved (dragged)
     _lockedTransform: "boolean",// whether a freeformview can pan/zoom
-    
+
     // drag drop properties
     dragFactory: Doc,           // the document that serves as the "template" for the onDragStart script.  ie, to drag out copies of the dragFactory document.
     dropAction: "string",       // override specifying what should happen when this document is dropped (can be "alias", "copy", "move")
-- 
cgit v1.2.3-70-g09d2


From 19ababdb6098ac36358c86e43ad63ab3066b4663 Mon Sep 17 00:00:00 2001
From: Bob Zeleznik <zzzman@gmail.com>
Date: Sat, 23 May 2020 23:59:34 -0400
Subject: renamed lastTimecode to lastFrame

---
 src/client/documents/Documents.ts                                     | 1 +
 .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx   | 2 +-
 src/client/views/nodes/PresBox.tsx                                    | 4 ++--
 src/client/views/presentationview/PresElementBox.tsx                  | 2 +-
 src/fields/documentSchemas.ts                                         | 1 +
 5 files changed, 6 insertions(+), 4 deletions(-)

(limited to 'src/client/views/presentationview/PresElementBox.tsx')

diff --git a/src/client/documents/Documents.ts b/src/client/documents/Documents.ts
index 2be961108..7f5b62f22 100644
--- a/src/client/documents/Documents.ts
+++ b/src/client/documents/Documents.ts
@@ -127,6 +127,7 @@ export interface DocumentOptions {
     currentTimecode?: number; // the current timecode of a time-based document (e.g., current time of a video)  value is in seconds
     displayTimecode?: number; // the time that a document should be displayed (e.g., time an annotation should be displayed on a video)
     currentFrame?: number; // the current frame of a frame-based collection (e.g., progressive slide)
+    lastFrame?: number; // the last frame of a frame-based collection (e.g., progressive slide)
     activeFrame?: number; // the active frame of a document in a frame base collection
     borderRounding?: string;
     boxShadow?: string;
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 91e257f80..4840bb7e7 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -171,7 +171,7 @@ export class CollectionFreeFormView extends CollectionSubView<PanZoomDocument, P
         }
         CollectionFreeFormDocumentView.updateKeyframe(this.childDocs, currentFrame || 0);
         this.Document.currentFrame = Math.max(0, (currentFrame || 0) + 1);
-        this.Document.lastTimecode = Math.max(NumCast(this.Document.currentFrame), NumCast(this.Document.lastTimecode));
+        this.Document.lastFrame = Math.max(NumCast(this.Document.currentFrame), NumCast(this.Document.lastFrame));
     }
     @undoBatch
     @action
diff --git a/src/client/views/nodes/PresBox.tsx b/src/client/views/nodes/PresBox.tsx
index b76c06e2e..05306c29f 100644
--- a/src/client/views/nodes/PresBox.tsx
+++ b/src/client/views/nodes/PresBox.tsx
@@ -59,7 +59,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
     next = () => {
         this.updateCurrentPresentation();
         const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
-        const lastFrame = Cast(presTargetDoc.lastTimecode, "number", null);
+        const lastFrame = Cast(presTargetDoc.lastFrame, "number", null);
         const curFrame = NumCast(presTargetDoc.currentFrame);
         if (lastFrame !== undefined && curFrame < lastFrame) {
             presTargetDoc.currentFrame = curFrame + 1;
@@ -199,7 +199,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps, PresBoxSchema>
         if (index >= 0 && index < this.childDocs.length) {
             this.rootDoc._itemIndex = index;
             const presTargetDoc = Cast(this.childDocs[this.itemIndex].presentationTargetDoc, Doc, null);
-            if (presTargetDoc.lastTimecode !== undefined) {
+            if (presTargetDoc.lastFrame !== undefined) {
                 presTargetDoc.currentFrame = 0;
             }
 
diff --git a/src/client/views/presentationview/PresElementBox.tsx b/src/client/views/presentationview/PresElementBox.tsx
index 31ffde8af..475fef5b2 100644
--- a/src/client/views/presentationview/PresElementBox.tsx
+++ b/src/client/views/presentationview/PresElementBox.tsx
@@ -104,7 +104,7 @@ export class PresElementBox extends ViewBoxBaseComponent<FieldViewProps, PresDoc
         if (this.rootDoc.presProgressivize) {
             rootTarget.currentFrame = 0;
             CollectionFreeFormDocumentView.setupKeyframes(docs, docs.length, true);
-            rootTarget.lastTimecode = docs.length - 1;
+            rootTarget.lastFrame = docs.length - 1;
         }
     }
 
diff --git a/src/fields/documentSchemas.ts b/src/fields/documentSchemas.ts
index 7e11049ab..32f1b6e6c 100644
--- a/src/fields/documentSchemas.ts
+++ b/src/fields/documentSchemas.ts
@@ -13,6 +13,7 @@ export const documentSchema = createSchema({
 
     // "Location" properties in a very general sense
     currentFrame: "number",     // current frame of a frame based collection (e.g., a progressive slide)
+    lastFrame: "number",        // last frame of a frame based collection (e.g., a progressive slide)
     activeFrame: "number",      // the active frame of a frame based animated document 
     urrentTimecode: "number",   // current play back time of a temporal document (video / audio)
     displayTimecode: "number",  // the time that a document should be displayed (e.g., time an annotation should be displayed on a video)
-- 
cgit v1.2.3-70-g09d2

