From 724c1c1228aa601fdbbed93dde68a5a9fa9c5ae9 Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 20 Jul 2022 09:12:11 -0400
Subject: added a 'guest' login mode.  added ability for mainView to be any
 doc, not just a docking collection.

---
 src/client/views/collections/TabDocView.tsx | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index b8aaea622..2d08b1c09 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -302,6 +302,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
             });
         if (
+            CollectionDockingView.Instance &&
             !Array.from(CollectionDockingView.Instance.tabMap)
                 .map(d => d.DashDoc)
                 .includes(curPres)
@@ -420,7 +421,7 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     ScreenToLocalTransform = () => {
         this._forceInvalidateScreenToLocal;
         const { translateX, translateY } = Utils.GetScreenTransform(this._mainCont?.children?.[0] as HTMLElement);
-        return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY);
+        return CollectionDockingView.Instance?.props.ScreenToLocalTransform().translate(-translateX, -translateY) ?? Transform.Identity();
     };
     PanelWidth = () => this._panelWidth;
     PanelHeight = () => this._panelHeight;
@@ -449,9 +450,9 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     PanelWidth={this.PanelWidth}
                     PanelHeight={this.PanelHeight}
                     styleProvider={DefaultStyleProvider}
-                    docFilters={CollectionDockingView.Instance.childDocFilters}
-                    docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
-                    searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
+                    docFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
+                    docRangeFilters={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
+                    searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
                     addDocument={undefined}
                     removeDocument={this.remDocTab}
                     addDocTab={this.addDocTab}
@@ -624,9 +625,9 @@ export class TabMinimapView extends React.Component<TabMinimapViewProps> {
                     styleProvider={TabMinimapView.miniStyleProvider}
                     addDocTab={this.props.addDocTab}
                     pinToPres={TabDocView.PinDoc}
-                    docFilters={CollectionDockingView.Instance.childDocFilters}
-                    docRangeFilters={CollectionDockingView.Instance.childDocRangeFilters}
-                    searchFilterDocs={CollectionDockingView.Instance.searchFilterDocs}
+                    docFilters={CollectionDockingView.Instance?.childDocFilters ?? returnEmptyDoclist}
+                    docRangeFilters={CollectionDockingView.Instance?.childDocRangeFilters ?? returnEmptyDoclist}
+                    searchFilterDocs={CollectionDockingView.Instance?.searchFilterDocs ?? returnEmptyDoclist}
                     fitContentsToBox={returnTrue}
                 />
                 <div className="miniOverlay" onPointerDown={this.miniDown}>
-- 
cgit v1.2.3-70-g09d2


From 1f42bac078fc96d2d63c54f62281941d19abf1be Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Tue, 9 Aug 2022 09:33:43 -0400
Subject: fixed presbox pinning from crashing/failing by making it a
 prefetchproxy.  update user cache when switching active page.

---
 .vscode/launch.json                                | 188 +++++++++------------
 .../views/collections/CollectionDockingView.tsx    |   2 +-
 src/client/views/collections/TabDocView.tsx        |  27 +--
 src/fields/Doc.ts                                  |   3 +-
 webpack.config.js                                  | 162 +++++++++---------
 5 files changed, 183 insertions(+), 199 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/.vscode/launch.json b/.vscode/launch.json
index 9692c79d9..ce9f50f67 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -4,110 +4,86 @@
     // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
     "version": "0.2.0",
     "configurations": [
-      {
-        "type": "chrome",
-        "request": "launch",
-        "name": "Launch Chrome against localhost",
-        "sourceMaps": true,
-        "breakOnLoad": true,
-        "url": "http://localhost:1050/login",
-        "webRoot": "${workspaceFolder}",
-        "runtimeArgs": [
-          "--experimental-modules"
-        ]
-      },
-      {
-        "type": "chrome",
-        "request": "launch",
-        "name": "Launch Chromium against localhost",
-        "sourceMaps": true,
-        "breakOnLoad": true,
-        "url": "http://localhost:1050/login",
-        "webRoot": "${workspaceFolder}",
-        "runtimeExecutable": "/usr/bin/chromium",
-        "runtimeArgs": [
-          "--experimental-modules"
-        ]
-      },
-      {
-        "type": "firefox",
-        "request": "launch",
-        "name": "Launch Firefox against localhost",
-        "reAttach": true,
-        "url": "http://localhost:1050/login",
-        "webRoot": "${workspaceFolder}",
-        "pathMappings": [
-          {
-            "url": "webpack://dash/src",
-            "path": "${workspaceFolder}/src"
-          }
-        ]
-      },
-      {
-        "type": "chrome",
-        "request": "launch",
-        "name": "Launch Chrome against Dash server",
-        "sourceMaps": true,
-        "breakOnLoad": true,
-        "url": "https://browndash.com/login",
-        "webRoot": "${workspaceFolder}"
-      },
-      {
-        "type": "node",
-        "request": "attach",
-        "name": "Typescript Server",
-        "protocol": "inspector",
-        "port": 9229,
-        "localRoot": "${workspaceFolder}",
-        "remoteRoot": "${workspaceFolder}"
-      },
-      {
-        "type": "node",
-        "request": "launch",
-        "name": "Current TS File",
-        "runtimeExecutable": "npx",
-        "runtimeArgs": [
-          "ts-node-dev",
-          "--nolazy",
-          "--inspect",
-          "--",
-          "${relativeFile}"
-        ],
-        "port": 9229
-      },
-      {
-        "type": "node",
-        "request": "launch",
-        "name": "Mocha Tests",
-        "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
-        "args": [
-          "-r",
-          "ts-node/register",
-          "--timeout",
-          "999999",
-          "--colors",
-          "${workspaceFolder}/test/**/*.ts"
-        ],
-        "console": "integratedTerminal",
-        "internalConsoleOptions": "openOnSessionStart",
-        "protocol": "inspector"
-      },
-      {
-        "type": "node",
-        "request": "launch",
-        "name": "Mocha Current File",
-        "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
-        "args": [
-          "-r",
-          "ts-node/register",
-          "--timeout",
-          "999999",
-          "--colors",
-          "${file}"
-        ],
-        "console": "integratedTerminal",
-        "internalConsoleOptions": "openOnSessionStart",
-        "protocol": "inspector"
-      }
+        {
+            "type": "chrome",
+            "request": "launch",
+            "name": "Launch Chrome against localhost",
+            "sourceMaps": true,
+            "breakOnLoad": true,
+            "url": "http://localhost:1050/login",
+            "webRoot": "${workspaceFolder}",
+            "runtimeArgs": ["--experimental-modules"]
+        },
+        {
+            "type": "chrome",
+            "request": "launch",
+            "name": "Launch Chromium against localhost",
+            "sourceMaps": true,
+            "breakOnLoad": true,
+            "url": "http://localhost:1050/login",
+            "webRoot": "${workspaceFolder}",
+            "runtimeExecutable": "/usr/bin/chromium",
+            "runtimeArgs": ["--experimental-modules"]
+        },
+        {
+            "type": "firefox",
+            "request": "launch",
+            "name": "Launch Firefox against localhost",
+            "reAttach": true,
+            "url": "http://localhost:1050/login",
+            "webRoot": "${workspaceFolder}",
+            "pathMappings": [
+                {
+                    "url": "webpack://dash/src",
+                    "path": "${workspaceFolder}/src"
+                }
+            ]
+        },
+        {
+            "type": "chrome",
+            "request": "launch",
+            "name": "Launch Chrome against Dash server",
+            "sourceMaps": true,
+            "breakOnLoad": true,
+            "url": "https://browndash.com/login",
+            "webRoot": "${workspaceFolder}"
+        },
+        {
+            "type": "node",
+            "request": "attach",
+            "name": "Typescript Server",
+            "protocol": "inspector",
+            "port": 9229,
+            "localRoot": "${workspaceFolder}",
+            "remoteRoot": "${workspaceFolder}"
+        },
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Current TS File",
+            "runtimeExecutable": "npx",
+            "runtimeArgs": ["ts-node-dev", "--nolazy", "--inspect", "--", "${relativeFile}"],
+            "port": 9229
+        },
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Mocha Tests",
+            "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
+            "args": ["-r", "ts-node/register", "--timeout", "999999", "--colors", "${workspaceFolder}/test/**/*.ts"],
+            "console": "integratedTerminal",
+            "internalConsoleOptions": "openOnSessionStart",
+            "protocol": "inspector"
+        },
+        {
+            "type": "node",
+            "request": "launch",
+            "name": "Mocha Current File",
+            "program": "${workspaceFolder}/node_modules/mocha/bin/_mocha",
+            "args": ["-r", "ts-node/register", "--timeout", "999999", "--colors", "${file}"],
+            "console": "integratedTerminal",
+            "internalConsoleOptions": "openOnSessionStart",
+            "protocol": "inspector"
+        }
     ]
-}
\ No newline at end of file
+}
diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx
index 39e2cc17d..6d70cc0d2 100644
--- a/src/client/views/collections/CollectionDockingView.tsx
+++ b/src/client/views/collections/CollectionDockingView.tsx
@@ -175,7 +175,7 @@ export class CollectionDockingView extends CollectionSubView() {
     @undoBatch
     @action
     public static AddSplit(document: Doc, pullSide: string, stack?: any, panelName?: string) {
-        if (document._viewType === CollectionViewType.Docking) return DashboardView.openDashboard(document);
+        if (document?._viewType === CollectionViewType.Docking) return DashboardView.openDashboard(document);
         if (!CollectionDockingView.Instance) return false;
         const tab = Array.from(CollectionDockingView.Instance.tabMap).find(tab => tab.DashDoc === document);
         if (tab) {
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index 2d08b1c09..ec291e72c 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -212,11 +212,11 @@ export class TabDocView extends React.Component<TabDocViewProps> {
     @action
     public static PinDoc(docs: Doc | Doc[], pinProps?: PinProps) {
         const docList = docs instanceof Doc ? [docs] : docs;
-        const batch = UndoManager.StartBatch('pinning doc');
 
         // all docs will be added to the ActivePresentation as stored on CurrentUserUtils
         const curPres = Doc.ActivePresentation;
-        curPres &&
+        if (curPres) {
+            const batch = UndoManager.StartBatch('pinning doc');
             docList.forEach(doc => {
                 // Edge Case 1: Cannot pin document to itself
                 if (doc === curPres) {
@@ -301,18 +301,19 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                 PresBox.Instance?._selectedArray.clear();
                 pinDoc && PresBox.Instance?._selectedArray.set(pinDoc, undefined); //Update selected array
             });
-        if (
-            CollectionDockingView.Instance &&
-            !Array.from(CollectionDockingView.Instance.tabMap)
-                .map(d => d.DashDoc)
-                .includes(curPres)
-        ) {
-            const docs = Cast(Doc.MyOverlayDocs.data, listSpec(Doc), []);
-            if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
-            CollectionDockingView.AddSplit(curPres, 'right');
-            setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
+            if (
+                CollectionDockingView.Instance &&
+                !Array.from(CollectionDockingView.Instance.tabMap)
+                    .map(d => d.DashDoc)
+                    .includes(curPres)
+            ) {
+                const docs = Cast(Doc.MyOverlayDocs.data, listSpec(Doc), []);
+                if (docs.includes(curPres)) docs.splice(docs.indexOf(curPres), 1);
+                CollectionDockingView.AddSplit(curPres, 'right');
+                setTimeout(() => DocumentManager.Instance.jumpToDocument(docList.lastElement(), false, undefined, []), 100); // keeps the pinned doc in view since the sidebar shifts things
+            }
+            setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
         }
-        setTimeout(batch.end, 500); // need to wait until dockingview (goldenlayout) updates all its structurs
     }
 
     componentDidMount() {
diff --git a/src/fields/Doc.ts b/src/fields/Doc.ts
index 0c7504913..8d56ebf8c 100644
--- a/src/fields/Doc.ts
+++ b/src/fields/Doc.ts
@@ -211,6 +211,7 @@ export class Doc extends RefField {
     }
     public static set ActivePage(val) {
         Doc.UserDoc().activePage = val;
+        DocServer.UPDATE_SERVER_CACHE();
     }
     public static get ActiveDashboard() {
         return DocCast(Doc.UserDoc().activeDashboard);
@@ -228,7 +229,7 @@ export class Doc extends RefField {
         return DocCast(Doc.UserDoc().activePresentation);
     }
     public static set ActivePresentation(val) {
-        Doc.UserDoc().activePresentation = val;
+        Doc.UserDoc().activePresentation = new PrefetchProxy(val);
     }
     constructor(id?: FieldId, forceSave?: boolean) {
         super(id);
diff --git a/webpack.config.js b/webpack.config.js
index 5a954db19..01625988c 100644
--- a/webpack.config.js
+++ b/webpack.config.js
@@ -1,38 +1,38 @@
-var path = require('path');
-var webpack = require('webpack');
-const CopyWebpackPlugin = require("copy-webpack-plugin");
+const path = require('path');
+const webpack = require('webpack');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
 const HtmlWebpackPlugin = require('html-webpack-plugin');
-const ForkTsCheckerWebpackPlugin = require("fork-ts-checker-webpack-plugin");
+const ForkTsCheckerWebpackPlugin = require('fork-ts-checker-webpack-plugin');
 
 const plugins = [
-    new CopyWebpackPlugin([{
-        from: "deploy",
-        to: path.join(__dirname, "build")
-    }]),
+    new CopyWebpackPlugin([
+        {
+            from: 'deploy',
+            to: path.join(__dirname, 'build'),
+        },
+    ]),
     new HtmlWebpackPlugin({
         title: 'Caching',
     }),
     new ForkTsCheckerWebpackPlugin({
         tslint: true,
         //  memoryLimit: 4096,
-        useTypescriptIncrementalApi: true
+        useTypescriptIncrementalApi: true,
     }),
-    new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'], }),
-    new webpack.ProvidePlugin({ process: 'process/browser', }),
+    new webpack.ProvidePlugin({ Buffer: ['buffer', 'Buffer'] }),
+    new webpack.ProvidePlugin({ process: 'process/browser' }),
     new webpack.HotModuleReplacementPlugin(),
 ];
 
 function transferEnvironmentVariables() {
-    const prefix = "_CLIENT_";
-    const {
-        parsed
-    } = require('dotenv').config();
+    const prefix = '_CLIENT_';
+    const { parsed } = require('dotenv').config();
     if (!parsed) {
         return;
     }
     const resolvedClientSide = Object.keys(parsed).reduce((mapping, envKey) => {
         if (envKey.startsWith(prefix)) {
-            mapping[`process.env.${envKey.replace(prefix, "")}`] = JSON.stringify(parsed[envKey]);
+            mapping[`process.env.${envKey.replace(prefix, '')}`] = JSON.stringify(parsed[envKey]);
         }
         return mapping;
     }, {});
@@ -44,18 +44,18 @@ transferEnvironmentVariables();
 module.exports = {
     mode: 'development',
     entry: {
-        bundle: ["./src/client/views/Main.tsx", 'webpack-hot-middleware/client?reload=true'],
-        viewer: ["./src/debug/Viewer.tsx", 'webpack-hot-middleware/client?reload=true'],
-        repl: ["./src/debug/Repl.tsx", 'webpack-hot-middleware/client?reload=true'],
-        test: ["./src/debug/Test.tsx", 'webpack-hot-middleware/client?reload=true'],
-        inkControls: ["./src/mobile/InkControls.tsx", 'webpack-hot-middleware/client?reload=true'],
-        mobileInterface: ["./src/client/views/Main.tsx", 'webpack-hot-middleware/client?reload=true'],
+        bundle: ['./src/client/views/Main.tsx', 'webpack-hot-middleware/client?reload=true'],
+        viewer: ['./src/debug/Viewer.tsx', 'webpack-hot-middleware/client?reload=true'],
+        repl: ['./src/debug/Repl.tsx', 'webpack-hot-middleware/client?reload=true'],
+        test: ['./src/debug/Test.tsx', 'webpack-hot-middleware/client?reload=true'],
+        inkControls: ['./src/mobile/InkControls.tsx', 'webpack-hot-middleware/client?reload=true'],
+        mobileInterface: ['./src/client/views/Main.tsx', 'webpack-hot-middleware/client?reload=true'],
     },
-    devtool: "source-map",
+    devtool: 'source-map',
     output: {
-        filename: "[name].js",
-        path: path.resolve(__dirname, "build"),
-        publicPath: "/",
+        filename: '[name].js',
+        path: path.resolve(__dirname, 'build'),
+        publicPath: '/',
     },
     resolve: {
         extensions: ['.js', '.ts', '.tsx'],
@@ -68,67 +68,73 @@ module.exports = {
             crypto: false,
             assert: false,
             os: false,
-            path: require.resolve("path-browserify"),
-            http: require.resolve("http-browserify"),
-            https: require.resolve("https-browserify"),
-            stream: require.resolve("stream-browserify"),
-            buffer: require.resolve("buffer")
-        }
+            path: require.resolve('path-browserify'),
+            http: require.resolve('http-browserify'),
+            https: require.resolve('https-browserify'),
+            stream: require.resolve('stream-browserify'),
+            buffer: require.resolve('buffer'),
+        },
     },
     module: {
-        rules: [{
-            test: [/\.tsx?$/],
-            use: [{
-                loader: 'ts-loader',
-                options: {
-                    transpileOnly: true
-                }
-            }]
-        },
-        {
-            test: /\.m?js/,
-            resolve: {
-                fullySpecified: false
-            }
-        },
-        {
-            test: /\.(woff|woff2|ttf|eot|otf|svg)$/,
-            use: 'file-loader?name=fonts/[name].[ext]!static'
-        },
-        {
-            test: /\.scss|css$/,
-            use: [{
-                loader: "style-loader"
+        rules: [
+            {
+                test: [/\.tsx?$/],
+                use: [
+                    {
+                        loader: 'ts-loader',
+                        options: {
+                            transpileOnly: true,
+                        },
+                    },
+                ],
             },
             {
-                loader: "css-loader"
+                test: /\.m?js/,
+                resolve: {
+                    fullySpecified: false,
+                },
             },
             {
-                loader: "sass-loader"
+                test: /\.(woff|woff2|ttf|eot|otf|svg)$/,
+                use: 'file-loader?name=fonts/[name].[ext]!static',
+            },
+            {
+                test: /\.scss|css$/,
+                use: [
+                    {
+                        loader: 'style-loader',
+                    },
+                    {
+                        loader: 'css-loader',
+                    },
+                    {
+                        loader: 'sass-loader',
+                    },
+                ],
+            },
+            {
+                test: /\.(jpg|png|pdf)$/,
+                use: [
+                    {
+                        loader: 'file-loader',
+                    },
+                ],
+            },
+            {
+                test: /\.(png|jpg|gif)$/i,
+                use: [
+                    {
+                        loader: 'url-loader',
+                        options: {
+                            limit: 8192,
+                        },
+                    },
+                ],
             },
-            ]
-        },
-        {
-            test: /\.(jpg|png|pdf)$/,
-            use: [{
-                loader: 'file-loader'
-            }]
-        },
-        {
-            test: /\.(png|jpg|gif)$/i,
-            use: [{
-                loader: 'url-loader',
-                options: {
-                    limit: 8192
-                }
-            }]
-        }
         ],
 
         noParse: [require.resolve('typescript/lib/typescript.js')],
     },
     plugins,
-    externals: [
-        'child_process'
-    ],
-};
\ No newline at end of file
+    externals: ['child_process'],
+};
-- 
cgit v1.2.3-70-g09d2


From 513dcaa2d8c86f1cb5236ce89062cace6f418d1b Mon Sep 17 00:00:00 2001
From: bobzel <zzzman@gmail.com>
Date: Wed, 10 Aug 2022 14:52:04 -0400
Subject: cleaned up pinning documents with an activeFrame index (and special
 case of isInkMask).  removed text-color from pres boxes which was breaking
 opacity when docs had an appearFrame > 0.

---
 src/client/views/DocumentButtonBar.tsx             |  18 +-
 src/client/views/collections/CollectionMenu.tsx    |  25 ++-
 src/client/views/collections/TabDocView.tsx        |  15 +-
 .../views/nodes/CollectionFreeFormDocumentView.tsx | 208 ++++++++++++---------
 src/client/views/nodes/DocumentView.tsx            |   4 +-
 src/client/views/nodes/trails/PresBox.tsx          |  23 +--
 6 files changed, 163 insertions(+), 130 deletions(-)

(limited to 'src/client/views/collections/TabDocView.tsx')

diff --git a/src/client/views/DocumentButtonBar.tsx b/src/client/views/DocumentButtonBar.tsx
index 1f8550ad6..40fc8dae6 100644
--- a/src/client/views/DocumentButtonBar.tsx
+++ b/src/client/views/DocumentButtonBar.tsx
@@ -5,7 +5,7 @@ import { action, computed, observable, runInAction } from 'mobx';
 import { observer } from 'mobx-react';
 import { Doc } from '../../fields/Doc';
 import { RichTextField } from '../../fields/RichTextField';
-import { Cast, NumCast } from '../../fields/Types';
+import { Cast, DocCast, NumCast } from '../../fields/Types';
 import { emptyFunction, returnFalse, setupMoveUpEvents, simulateMouseClick } from '../../Utils';
 import { GoogleAuthenticationManager } from '../apis/GoogleAuthenticationManager';
 import { Pulls, Pushes } from '../apis/google_docs/GoogleApiClientUtils';
@@ -238,15 +238,13 @@ export class DocumentButtonBar extends React.Component<{ views: () => (DocumentV
                 <div
                     className="documentButtonBar-icon"
                     style={{ color: 'white' }}
-                    onClick={e =>
-                        TabDocView.PinDoc(
-                            this.props
-                                .views()
-                                .filter(v => v)
-                                .map(dv => dv!.rootDoc),
-                            { pinDocView: true }
-                        )
-                    }>
+                    onClick={e => {
+                        const docs = this.props
+                            .views()
+                            .filter(v => v)
+                            .map(dv => dv!.rootDoc);
+                        TabDocView.PinDoc(docs, { pinDocView: true, activeFrame: Cast(docs.lastElement()?.activeFrame, 'number', null) });
+                    }}>
                     <FontAwesomeIcon className="documentdecorations-icon" size="sm" icon="map-pin" />
                 </div>
             </Tooltip>
diff --git a/src/client/views/collections/CollectionMenu.tsx b/src/client/views/collections/CollectionMenu.tsx
index cfbcec2d6..8432619de 100644
--- a/src/client/views/collections/CollectionMenu.tsx
+++ b/src/client/views/collections/CollectionMenu.tsx
@@ -769,6 +769,21 @@ export class CollectionFreeFormViewChrome extends React.Component<CollectionView
         return this.selectedDoc?.type === DocumentType.RTF || (RichTextMenu.Instance?.view as any) ? true : false;
     }
 
+    public static gotoKeyFrame(doc: Doc, newFrame: number) {
+        if (!doc) {
+            return;
+        }
+        const dataField = doc[Doc.LayoutFieldKey(doc)];
+        const childDocs = DocListCast(dataField);
+        const currentFrame = Cast(doc._currentFrame, 'number', null);
+        if (currentFrame === undefined) {
+            doc._currentFrame = 0;
+            CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
+        }
+        CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0);
+        doc._currentFrame = newFrame === undefined ? 0 : Math.max(0, newFrame);
+    }
+
     @undoBatch
     @action
     nextKeyframe = (): void => {
@@ -1569,13 +1584,5 @@ export class CollectionGridViewChrome extends React.Component<CollectionViewMenu
     }
 }
 ScriptingGlobals.add(function gotoFrame(doc: any, newFrame: any) {
-    const dataField = doc[Doc.LayoutFieldKey(doc)];
-    const childDocs = DocListCast(dataField);
-    const currentFrame = Cast(doc._currentFrame, 'number', null);
-    if (currentFrame === undefined) {
-        doc._currentFrame = 0;
-        CollectionFreeFormDocumentView.setupKeyframes(childDocs, 0);
-    }
-    CollectionFreeFormDocumentView.updateKeyframe(childDocs, currentFrame || 0);
-    doc._currentFrame = newFrame === undefined ? 0 : Math.max(0, newFrame);
+    CollectionFreeFormViewChrome.gotoKeyFrame(doc, newFrame);
 });
diff --git a/src/client/views/collections/TabDocView.tsx b/src/client/views/collections/TabDocView.tsx
index ec291e72c..f30faab79 100644
--- a/src/client/views/collections/TabDocView.tsx
+++ b/src/client/views/collections/TabDocView.tsx
@@ -288,14 +288,15 @@ export class TabDocView extends React.Component<TabDocViewProps> {
                     pinDoc.presEndTime = NumCast(doc.clipEnd, duration);
                 }
                 //save position
-                if (pinProps?.setPosition || pinDoc.isInkMask) {
-                    pinDoc.setPosition = true;
-                    pinDoc.y = doc.y;
-                    pinDoc.x = doc.x;
-                    pinDoc.presHideAfter = true;
-                    pinDoc.presHideBefore = true;
+                if (pinProps?.activeFrame !== undefined) {
+                    pinDoc.presActiveFrame = pinProps?.activeFrame;
                     pinDoc.title = doc.title + ' (move)';
-                    pinDoc.presMovement = PresMovement.None;
+                    pinDoc.presMovement = PresMovement.Pan;
+                    if (pinDoc.isInkMask) {
+                        pinDoc.presHideAfter = true;
+                        pinDoc.presHideBefore = true;
+                        pinDoc.presMovement = PresMovement.None;
+                    }
                 }
                 if (curPres.expandBoolean) pinDoc.presExpandInlineButton = true;
                 PresBox.Instance?._selectedArray.clear();
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 284584a3d..e154e8445 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -1,26 +1,26 @@
-import { action, computed, observable, trace } from "mobx";
-import { observer } from "mobx-react";
-import { Doc, Opt } from "../../../fields/Doc";
-import { List } from "../../../fields/List";
-import { listSpec } from "../../../fields/Schema";
-import { ComputedField } from "../../../fields/ScriptField";
-import { Cast, NumCast, StrCast } from "../../../fields/Types";
-import { TraceMobx } from "../../../fields/util";
-import { DashColor, numberRange, OmitKeys } from "../../../Utils";
-import { DocumentManager } from "../../util/DocumentManager";
-import { SelectionManager } from "../../util/SelectionManager";
-import { Transform } from "../../util/Transform";
-import { CollectionFreeFormView } from "../collections/collectionFreeForm/CollectionFreeFormView";
-import { DocComponent } from "../DocComponent";
-import { InkingStroke } from "../InkingStroke";
-import { StyleProp } from "../StyleProvider";
-import "./CollectionFreeFormDocumentView.scss";
-import { DocumentView, DocumentViewProps } from "./DocumentView";
-import React = require("react");
+import { action, computed, observable, trace } from 'mobx';
+import { observer } from 'mobx-react';
+import { Doc, Opt } from '../../../fields/Doc';
+import { List } from '../../../fields/List';
+import { listSpec } from '../../../fields/Schema';
+import { ComputedField } from '../../../fields/ScriptField';
+import { Cast, NumCast, StrCast } from '../../../fields/Types';
+import { TraceMobx } from '../../../fields/util';
+import { DashColor, numberRange, OmitKeys } from '../../../Utils';
+import { DocumentManager } from '../../util/DocumentManager';
+import { SelectionManager } from '../../util/SelectionManager';
+import { Transform } from '../../util/Transform';
+import { CollectionFreeFormView } from '../collections/collectionFreeForm/CollectionFreeFormView';
+import { DocComponent } from '../DocComponent';
+import { InkingStroke } from '../InkingStroke';
+import { StyleProp } from '../StyleProvider';
+import './CollectionFreeFormDocumentView.scss';
+import { DocumentView, DocumentViewProps } from './DocumentView';
+import React = require('react');
 
 export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
-    dataProvider?: (doc: Doc, replica: string) => { x: number, y: number, zIndex?: number, opacity?: number, highlight?: boolean, z: number, transition?: string } | undefined;
-    sizeProvider?: (doc: Doc, replica: string) => { width: number, height: number } | undefined;
+    dataProvider?: (doc: Doc, replica: string) => { x: number; y: number; zIndex?: number; opacity?: number; highlight?: boolean; z: number; transition?: string } | undefined;
+    sizeProvider?: (doc: Doc, replica: string) => { width: number; height: number } | undefined;
     renderCutoffProvider: (doc: Doc) => boolean;
     zIndex?: number;
     highlight?: boolean;
@@ -32,29 +32,51 @@ export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
 
 @observer
 export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps>() {
-    public static animFields = ["_height", "_width", "x", "y", "_scrollTop", "opacity"];  // fields that are configured to be animatable using animation frames
+    public static animFields = ['_height', '_width', 'x', 'y', '_scrollTop', 'opacity']; // fields that are configured to be animatable using animation frames
     @observable _animPos: number[] | undefined = undefined;
     @observable _contentView: DocumentView | undefined | null;
-    get displayName() { return "CollectionFreeFormDocumentView(" + this.rootDoc.title + ")"; } // this makes mobx trace() statements more descriptive
-    get maskCentering() { return this.props.Document.isInkMask ? InkingStroke.MaskDim / 2 : 0; }
-    get transform() { return `translate(${this.X - this.maskCentering}px, ${this.Y - this.maskCentering}px) rotate(${NumCast(this.Document.jitterRotation, this.props.jitterRotation)}deg)`; }
-    get X() { return this.dataProvider ? this.dataProvider.x : NumCast(this.Document.x); }
-    get Y() { return this.dataProvider ? this.dataProvider.y : NumCast(this.Document.y); }
-    get ZInd() { return this.dataProvider ? this.dataProvider.zIndex : NumCast(this.Document.zIndex); }
-    get Opacity() { return this.dataProvider ? this.dataProvider.opacity : undefined; }
-    get Highlight() { return this.dataProvider?.highlight; }
-    @computed get ShowTitle() { return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as (Opt<string>); }
-    @computed get dataProvider() { return this.props.dataProvider?.(this.props.Document, this.props.replica); }
-    @computed get sizeProvider() { return this.props.sizeProvider?.(this.props.Document, this.props.replica); }
+    get displayName() {
+        return 'CollectionFreeFormDocumentView(' + this.rootDoc.title + ')';
+    } // this makes mobx trace() statements more descriptive
+    get maskCentering() {
+        return this.props.Document.isInkMask ? InkingStroke.MaskDim / 2 : 0;
+    }
+    get transform() {
+        return `translate(${this.X - this.maskCentering}px, ${this.Y - this.maskCentering}px) rotate(${NumCast(this.Document.jitterRotation, this.props.jitterRotation)}deg)`;
+    }
+    get X() {
+        return this.dataProvider ? this.dataProvider.x : NumCast(this.Document.x);
+    }
+    get Y() {
+        return this.dataProvider ? this.dataProvider.y : NumCast(this.Document.y);
+    }
+    get ZInd() {
+        return this.dataProvider ? this.dataProvider.zIndex : NumCast(this.Document.zIndex);
+    }
+    get Opacity() {
+        return this.dataProvider ? this.dataProvider.opacity : undefined;
+    }
+    get Highlight() {
+        return this.dataProvider?.highlight;
+    }
+    @computed get ShowTitle() {
+        return this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.ShowTitle) as Opt<string>;
+    }
+    @computed get dataProvider() {
+        return this.props.dataProvider?.(this.props.Document, this.props.replica);
+    }
+    @computed get sizeProvider() {
+        return this.props.sizeProvider?.(this.props.Document, this.props.replica);
+    }
 
     styleProvider = (doc: Doc | undefined, props: Opt<DocumentViewProps>, property: string) => {
         if (property === StyleProp.Opacity && doc === this.layoutDoc) return this.Opacity; // only change the opacity for this specific document, not its children
         return this.props.styleProvider?.(doc, props, property);
-    }
+    };
 
     public static getValues(doc: Doc, time: number) {
         return CollectionFreeFormDocumentView.animFields.reduce((p, val) => {
-            p[val] = Cast(`${val}-indexed`, listSpec("number"), [NumCast(doc[val])]).reduce((p, v, i) => (i <= Math.round(time) && v !== undefined) || p === undefined ? v : p, undefined as any as number);
+            p[val] = Cast(`${val}-indexed`, listSpec('number'), [NumCast(doc[val])]).reduce((p, v, i) => ((i <= Math.round(time) && v !== undefined) || p === undefined ? v : p), undefined as any as number);
             return p;
         }, {} as { [val: string]: Opt<number> });
     }
@@ -62,35 +84,43 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
     public static setValues(time: number, d: Doc, vals: { [val: string]: Opt<number> }) {
         const timecode = Math.round(time);
         Object.keys(vals).forEach(val => {
-            const findexed = Cast(d[`${val}-indexed`], listSpec("number"), []).slice();
+            const findexed = Cast(d[`${val}-indexed`], listSpec('number'), []).slice();
             findexed[timecode] = vals[val] as any as number;
             d[`${val}-indexed`] = new List<number>(findexed);
         });
-        d.appearFrame && (d["text-color"] =
-            d.appearFrame === timecode + 1 ? "red" :
-                d.appearFrame < timecode + 1 ? "grey" : "black");
     }
 
     public static updateKeyframe(docs: Doc[], time: number, targetDoc?: Doc) {
         const timecode = Math.round(time);
-        docs.forEach(action(doc => {
-            doc._viewTransition = doc.dataTransition = "all 1s";
-            doc["text-color"] =
-                !doc.appearFrame || !targetDoc ? "black" :
-                    doc.appearFrame === timecode + 1 ? StrCast(targetDoc["pres-text-color"]) :
-                        doc.appearFrame < timecode + 1 ? StrCast(targetDoc["pres-text-viewed-color"]) :
-                            "black";
-            CollectionFreeFormDocumentView.animFields.forEach(val => {
-                const findexed = Cast(doc[`${val}-indexed`], listSpec("number"), null);
-                findexed?.length <= timecode + 1 && findexed.push(undefined as any as number);
-            });
-        }));
-        setTimeout(() => docs.forEach(doc => { doc._viewTransition = undefined; doc.dataTransition = "inherit"; }), 1010);
+        docs.forEach(
+            action(doc => {
+                doc._viewTransition = doc.dataTransition = 'all 1s';
+                CollectionFreeFormDocumentView.animFields.forEach(val => {
+                    const findexed = Cast(doc[`${val}-indexed`], listSpec('number'), null);
+                    findexed?.length <= timecode + 1 && findexed.push(undefined as any as number);
+                });
+            })
+        );
+        setTimeout(
+            () =>
+                docs.forEach(doc => {
+                    doc._viewTransition = undefined;
+                    doc.dataTransition = 'inherit';
+                }),
+            1010
+        );
     }
 
     public static gotoKeyframe(docs: Doc[]) {
-        docs.forEach(doc => doc._viewTransition = doc.dataTransition = "all 1s");
-        setTimeout(() => docs.forEach(doc => { doc._viewTransition = undefined; doc.dataTransition = "inherit"; }), 1010);
+        docs.forEach(doc => (doc._viewTransition = doc.dataTransition = 'all 1s'));
+        setTimeout(
+            () =>
+                docs.forEach(doc => {
+                    doc._viewTransition = undefined;
+                    doc.dataTransition = 'inherit';
+                }),
+            1010
+        );
     }
 
     public static setupZoom(doc: Doc, targDoc: Doc) {
@@ -102,21 +132,22 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
         height.push(NumCast(targDoc._height));
         top.push(NumCast(targDoc._height) / -2);
         left.push(NumCast(targDoc._width) / -2);
-        doc["viewfinder-width-indexed"] = width;
-        doc["viewfinder-height-indexed"] = height;
-        doc["viewfinder-top-indexed"] = top;
-        doc["viewfinder-left-indexed"] = left;
+        doc['viewfinder-width-indexed'] = width;
+        doc['viewfinder-height-indexed'] = height;
+        doc['viewfinder-top-indexed'] = top;
+        doc['viewfinder-left-indexed'] = left;
     }
 
     public static setupKeyframes(docs: Doc[], currTimecode: number, makeAppear: boolean = false) {
         docs.forEach(doc => {
             if (doc.appearFrame === undefined) doc.appearFrame = currTimecode;
-            if (!doc["opacity-indexed"]) { // opacity is unlike other fields because it's value should not be undefined before it appears to enable it to fade-in
-                doc["opacity-indexed"] = new List<number>(numberRange(currTimecode + 1).map(t => !doc.z && makeAppear && t < NumCast(doc.appearFrame) ? 0 : 1));
+            if (!doc['opacity-indexed']) {
+                // opacity is unlike other fields because it's value should not be undefined before it appears to enable it to fade-in
+                doc['opacity-indexed'] = new List<number>(numberRange(currTimecode + 1).map(t => (!doc.z && makeAppear && t < NumCast(doc.appearFrame) ? 0 : 1)));
             }
-            CollectionFreeFormDocumentView.animFields.forEach(val => doc[val] = ComputedField.MakeInterpolated(val, "activeFrame", doc, currTimecode));
-            doc.activeFrame = ComputedField.MakeFunction("self.context?._currentFrame||0");
-            doc.dataTransition = "inherit";
+            CollectionFreeFormDocumentView.animFields.forEach(val => (doc[val] = ComputedField.MakeInterpolated(val, 'activeFrame', doc, currTimecode)));
+            doc.activeFrame = ComputedField.MakeFunction('self.context?._currentFrame||0');
+            doc.dataTransition = 'inherit';
         });
     }
 
@@ -131,7 +162,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
                 topDoc.x = spt[0];
                 topDoc.y = spt[1];
                 this.props.removeDocument?.(topDoc);
-                this.props.addDocTab(topDoc, "inParent");
+                this.props.addDocTab(topDoc, 'inParent');
             } else {
                 const spt = this.screenToLocalTransform().inverse().transformPoint(0, 0);
                 const fpt = screenXf.transformPoint(spt[0], spt[1]);
@@ -141,14 +172,14 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             }
             setTimeout(() => SelectionManager.SelectView(DocumentManager.Instance.getDocumentView(topDoc, container)!, false), 0);
         }
-    }
+    };
 
     nudge = (x: number, y: number) => {
         this.props.Document.x = NumCast(this.props.Document.x) + x;
         this.props.Document.y = NumCast(this.props.Document.y) + y;
-    }
-    panelWidth = () => (this.sizeProvider?.width || this.props.PanelWidth?.());
-    panelHeight = () => (this.sizeProvider?.height || this.props.PanelHeight?.());
+    };
+    panelWidth = () => this.sizeProvider?.width || this.props.PanelWidth?.();
+    panelHeight = () => this.sizeProvider?.height || this.props.PanelHeight?.();
     screenToLocalTransform = (): Transform => this.props.ScreenToLocalTransform().translate(-this.X, -this.Y);
     focusDoc = (doc: Doc) => this.props.focus(doc);
     returnThis = () => this;
@@ -163,24 +194,27 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
             PanelHeight: this.panelHeight,
         };
         const background = this.props.styleProvider?.(this.rootDoc, this.props, StyleProp.BackgroundColor);
-        const mixBlendMode = StrCast(this.layoutDoc.mixBlendMode) as any || (typeof background === "string" && background && (!background.startsWith("linear") && DashColor(background).alpha() !== 1) ? "multiply" : undefined);
-        return <div className={"collectionFreeFormDocumentView-container"}
-            style={{
-                outline: this.Highlight ? "orange solid 2px" : "",
-                width: this.panelWidth(),
-                height: this.panelHeight(),
-                transform: this.transform,
-                transformOrigin: '50% 50%',
-                transition: this.dataProvider?.transition ?? (this.props.dataTransition ? this.props.dataTransition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition)),
-                zIndex: this.ZInd,
-                mixBlendMode: mixBlendMode,
-                display: this.ZInd === -99 ? "none" : undefined
-            }} >
-            {this.props.renderCutoffProvider(this.props.Document) ?
-                <div style={{ position: "absolute", width: this.panelWidth(), height: this.panelHeight(), background: "lightGreen" }} />
-                :
-                <DocumentView {...divProps} ref={action((r: DocumentView | null) => this._contentView = r)} />
-            }
-        </div>;
+        const mixBlendMode = (StrCast(this.layoutDoc.mixBlendMode) as any) || (typeof background === 'string' && background && !background.startsWith('linear') && DashColor(background).alpha() !== 1 ? 'multiply' : undefined);
+        return (
+            <div
+                className={'collectionFreeFormDocumentView-container'}
+                style={{
+                    outline: this.Highlight ? 'orange solid 2px' : '',
+                    width: this.panelWidth(),
+                    height: this.panelHeight(),
+                    transform: this.transform,
+                    transformOrigin: '50% 50%',
+                    transition: this.dataProvider?.transition ?? (this.props.dataTransition ? this.props.dataTransition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.dataTransition)),
+                    zIndex: this.ZInd,
+                    mixBlendMode: mixBlendMode,
+                    display: this.ZInd === -99 ? 'none' : undefined,
+                }}>
+                {this.props.renderCutoffProvider(this.props.Document) ? (
+                    <div style={{ position: 'absolute', width: this.panelWidth(), height: this.panelHeight(), background: 'lightGreen' }} />
+                ) : (
+                    <DocumentView {...divProps} ref={action((r: DocumentView | null) => (this._contentView = r))} />
+                )}
+            </div>
+        );
     }
 }
diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx
index f87581875..f9ef85595 100644
--- a/src/client/views/nodes/DocumentView.tsx
+++ b/src/client/views/nodes/DocumentView.tsx
@@ -1640,8 +1640,8 @@ export class DocumentView extends React.Component<DocumentViewProps> {
 
     render() {
         TraceMobx();
-        const xshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);
-        const yshift = () => (this.props.Document.isInkMask ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined);
+        const xshift = () => (this.props.Document.isInkMask && !this.props.LayoutTemplateString && !this.props.LayoutTemplate?.() ? InkingStroke.MaskDim : Math.abs(this.Xshift) <= 0.001 ? this.props.PanelWidth() : undefined);
+        const yshift = () => (this.props.Document.isInkMask && !this.props.LayoutTemplateString && !this.props.LayoutTemplate?.() ? InkingStroke.MaskDim : Math.abs(this.Yshift) <= 0.001 ? this.props.PanelHeight() : undefined);
         const isPresTreeElement: boolean = this.props.treeViewDoc?.type === DocumentType.PRES;
         const isButton: boolean = this.props.Document.type === DocumentType.FONTICON || this.props.Document._viewType === CollectionViewType.Linear;
         return (
diff --git a/src/client/views/nodes/trails/PresBox.tsx b/src/client/views/nodes/trails/PresBox.tsx
index 6e5eb3300..3bbdce1e4 100644
--- a/src/client/views/nodes/trails/PresBox.tsx
+++ b/src/client/views/nodes/trails/PresBox.tsx
@@ -29,10 +29,11 @@ import { CollectionFreeFormDocumentView } from '../CollectionFreeFormDocumentVie
 import { FieldView, FieldViewProps } from '../FieldView';
 import './PresBox.scss';
 import { PresEffect, PresMovement, PresStatus } from './PresEnums';
+import { CollectionFreeFormViewChrome } from '../../collections/CollectionMenu';
 
 export interface PinProps {
     audioRange?: boolean;
-    setPosition?: boolean;
+    activeFrame?: number;
     hidePresBox?: boolean;
     pinWithView?: PinViewProps;
     pinDocView?: boolean; // whether the current view specs of the document should be saved the pinned document
@@ -509,7 +510,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         this.childDocs.forEach((doc, index) => {
             const curDoc = Cast(doc, Doc, null);
             const tagDoc = Cast(curDoc.presentationTargetDoc, Doc, null);
-            if (tagDoc) tagDoc.opacity = 1;
+            //if (tagDoc) tagDoc.opacity = 1;
             const itemIndexes: number[] = this.getAllIndexes(this.tagDocs, tagDoc);
             const curInd: number = itemIndexes.indexOf(index);
             if (tagDoc === this.layoutDoc.presCollection) {
@@ -519,7 +520,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 } else if (curDoc.presHideBefore) {
                     if (index > this.itemIndex) {
                         tagDoc.opacity = 0;
-                    } else if (!curDoc.presHideAfter) {
+                    } else if (index === this.itemIndex || !curDoc.presHideAfter) {
                         tagDoc.opacity = 1;
                     }
                 }
@@ -527,7 +528,7 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
                 } else if (curDoc.presHideAfter) {
                     if (index < this.itemIndex) {
                         tagDoc.opacity = 0;
-                    } else if (!curDoc.presHideBefore) {
+                    } else if (index === this.itemIndex || !curDoc.presHideBefore) {
                         tagDoc.opacity = 1;
                     }
                 }
@@ -821,17 +822,9 @@ export class PresBox extends ViewBoxBaseComponent<FieldViewProps>() {
         if (doc.presPinView || doc.presentationTargetDoc === this.layoutDoc.presCollection) setTimeout(() => this.updateCurrentPresentation(context), 0);
         else this.updateCurrentPresentation(context);
 
-        if (this.activeItem.setPosition && this.activeItem.y !== undefined && this.activeItem.x !== undefined && this.targetDoc.x !== undefined && this.targetDoc.y !== undefined) {
-            const timer = (ms: number) => new Promise(res => (this._presTimer = setTimeout(res, ms)));
-            const time = 10;
-            const ydiff = NumCast(this.activeItem.y) - NumCast(this.targetDoc.y);
-            const xdiff = NumCast(this.activeItem.x) - NumCast(this.targetDoc.x);
-
-            for (let i = 0; i < time; i++) {
-                this.targetDoc.x = NumCast(this.targetDoc.x) + xdiff / time;
-                this.targetDoc.y = NumCast(this.targetDoc.y) + ydiff / time;
-                await timer(0.1);
-            }
+        if (this.activeItem.presActiveFrame !== undefined) {
+            const context = DocCast(DocCast(this.activeItem.presentationTargetDoc).context);
+            context && CollectionFreeFormViewChrome.gotoKeyFrame(context, NumCast(this.activeItem.presActiveFrame));
         }
     };
 
-- 
cgit v1.2.3-70-g09d2

