From a07395855a05e5e6a3cdd19d691c39d6435bdf3f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaros=C5=82aw=20Sadzi=C5=84ski?= Date: Thu, 22 Jul 2021 11:14:35 +0200 Subject: [PATCH] (core) Fixing anchor link navigation. Summary: Last document position was overwritting anchor link navigation. Test Plan: Browser tests Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D2934 --- app/client/components/CursorMonitor.ts | 16 +++++++++++----- app/client/components/GristDoc.ts | 10 ++++++++-- app/common/gutil.ts | 21 +++++++++++++++++++-- 3 files changed, 38 insertions(+), 9 deletions(-) diff --git a/app/client/components/CursorMonitor.ts b/app/client/components/CursorMonitor.ts index 3ed1eed9..33d4e468 100644 --- a/app/client/components/CursorMonitor.ts +++ b/app/client/components/CursorMonitor.ts @@ -1,8 +1,8 @@ -import { CursorPos } from "app/client/components/Cursor"; -import { getStorage } from "app/client/lib/localStorageObs"; -import { IDocPage } from "app/common/gristUrls"; -import { Disposable } from "grainjs"; -import { GristDoc } from "app/client/components/GristDoc"; +import {CursorPos} from 'app/client/components/Cursor'; +import {GristDoc} from 'app/client/components/GristDoc'; +import {getStorage} from 'app/client/lib/localStorageObs'; +import {IDocPage} from 'app/common/gristUrls'; +import {Disposable} from 'grainjs'; /** * Enriched cursor position with a view id @@ -54,6 +54,12 @@ export class CursorMonitor extends Disposable { } private _whenDocumentLoadsRestorePosition(doc: GristDoc) { + // if doc was opened with a hash link, don't restore last position + if (doc.hasCustomNav.get()) { + this._restored = true; + return; + } + // on view shown this.autoDispose(doc.currentView.addListener(async view => { // if the position was restored for this document do nothing diff --git a/app/client/components/GristDoc.ts b/app/client/components/GristDoc.ts index 94eaca55..adafeae1 100644 --- a/app/client/components/GristDoc.ts +++ b/app/client/components/GristDoc.ts @@ -43,7 +43,7 @@ import {isSchemaAction} from 'app/common/DocActions'; import {OpenLocalDocResult} from 'app/common/DocListAPI'; import {HashLink, IDocPage} from 'app/common/gristUrls'; import {RecalcWhen} from 'app/common/gristTypes'; -import {encodeQueryParams, waitObs} from 'app/common/gutil'; +import {encodeQueryParams, undef, waitObs} from 'app/common/gutil'; import {StringUnion} from 'app/common/StringUnion'; import {TableData} from 'app/common/TableData'; import {DocStateComparison} from 'app/common/UserAPI'; @@ -106,7 +106,8 @@ export class GristDoc extends DisposableWithEvents { public editorMonitor: EditorMonitor; // component for keeping track of a cell that is being edited public draftMonitor: Drafts; - + // will document perform its own navigation (from anchor link) + public hasCustomNav: Observable; // Emitter triggered when the main doc area is resized. public readonly resizeEmitter = this.autoDispose(new Emitter()); @@ -297,6 +298,11 @@ export class GristDoc extends DisposableWithEvents { return undefined; }); + this.hasCustomNav = Computed.create(this, urlState().state, (_, state) => { + const hash = state.hash; + return !!(hash && (undef(hash.colRef, hash.rowId, hash.sectionId) !== undefined)); + }); + this.draftMonitor = Drafts.create(this, this); this.cursorMonitor = CursorMonitor.create(this, this); this.editorMonitor = EditorMonitor.create(this, this); diff --git a/app/common/gutil.ts b/app/common/gutil.ts index a788b8bf..e4d2f346 100644 --- a/app/common/gutil.ts +++ b/app/common/gutil.ts @@ -105,8 +105,7 @@ export function undefDefault(x: T|undefined, y: T): T { // for typescript 4 // type Undef = T extends [infer A, ...infer B] ? undefined extends A ? NonNullable | Undef : A : unknown; -type Undef1 = T extends [infer A] ? - undefined extends A ? NonNullable : A : unknown; +type Undef1 = T extends [infer A] ? A : unknown; type Undef2 = T extends [infer A, infer B] ? undefined extends A ? NonNullable | Undef1<[B]> : A : Undef1; @@ -117,6 +116,23 @@ type Undef3 = T extends [infer A, infer B, infer C] ? type Undef = T extends [infer A, infer B, infer C, infer D] ? undefined extends A ? NonNullable | Undef3<[B, C, D]> : A : Undef3; +/* + +Undef can detect correct type that will be returned as a first defined value: + +const t1: number = undef(1, 1 as number | undefined); +const t1: number | undefined = undef(2 as number | undefined, 3 as number | undefined); +const t3: number = undef(3 as number | undefined, undefined, 4); +const t4: number = undef(1, ''); +const t5: number = undef(1 as number | undefined, 4); +const t6: string = undef('1', 2); +const t7: string | number = undef(undefined, 2 as number | undefined, '3'); +const t8: string = undef(undefined, undefined, '3'); +const t9: string = undef(undefined, '2' as string | undefined, '3'); +const ta: string | number | undefined = undef(undefined, '2' as string | undefined, 3 as number | undefined); +const tb: string | number = undef(undefined, '2' as string | undefined, 3 as number | undefined, 5); +*/ + /** * Returns the first defined value from the list or unknown. * Use with typed result, so the typescript type checker can provide correct type. @@ -128,6 +144,7 @@ export function undef>(...list: T): Undef { return undefined as any; } + /** * Parses json and returns the result, or returns defaultVal if parsing fails. */