From fc50079e0320ecb131ca291bd797c848e6e59e30 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaros=C5=82aw=20Sadzi=C5=84ski?= Date: Thu, 18 Nov 2021 23:54:37 +0100 Subject: [PATCH] (core) Storing last position for doc and user Summary: Last position should be stored for document and user. Test Plan: Updated tests Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3143 --- app/client/components/CursorMonitor.ts | 15 +++++++++------ app/client/components/EditorMonitor.ts | 21 ++++++++++++--------- test/nbrowser/gristUtils.ts | 14 ++++++++++++++ 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/app/client/components/CursorMonitor.ts b/app/client/components/CursorMonitor.ts index 33d4e468..7eaa3937 100644 --- a/app/client/components/CursorMonitor.ts +++ b/app/client/components/CursorMonitor.ts @@ -18,8 +18,8 @@ export class CursorMonitor extends Disposable { // abstraction to work with local storage private _store: StorageWrapper; - // document id that this monitor is attached - private _docId: string; + // key for storing position in the memory (docId + userId) + private _key: string; // flag that tells if the position was already restored // we track document's view change event, so we only want // to react to that event once @@ -31,7 +31,10 @@ export class CursorMonitor extends Disposable { super(); this._store = new StorageWrapper(store); - this._docId = doc.docId(); + + // Use document id and user id as a key for storage. + const userId = doc.app.topAppModel.appObs.get()?.currentUser?.id ?? null; + this._key = doc.docId() + userId; /** * When document loads last cursor position should be restored from local storage. @@ -77,12 +80,12 @@ export class CursorMonitor extends Disposable { } private _storePosition(pos: ViewCursorPos) { - this._store.update(this._docId, pos); + this._store.update(this._key, pos); } private _restoreLastPosition(view: IDocPage) { - const lastPosition = this._store.read(this._docId); - this._store.clear(this._docId); + const lastPosition = this._store.read(this._key); + this._store.clear(this._key); if (lastPosition && lastPosition.position.viewId == view) { return lastPosition.position; } diff --git a/app/client/components/EditorMonitor.ts b/app/client/components/EditorMonitor.ts index dd1062f4..6d78c732 100644 --- a/app/client/components/EditorMonitor.ts +++ b/app/client/components/EditorMonitor.ts @@ -22,7 +22,10 @@ export class EditorMonitor extends Disposable { super(); // create store - this._store = new EditMemoryStorage(doc.docId(), store); + const userId = doc.app.topAppModel.appObs.get()?.currentUser?.id ?? null; + // use document id and user id as a key for storage + const key = doc.docId() + userId; + this._store = new EditMemoryStorage(key, store); // listen to document events to handle view load event this._listenToReload(doc); @@ -58,8 +61,8 @@ export class EditorMonitor extends Disposable { // will be invoked only once let executed = false; - // don't restore on readonly mode - if (doc.isReadonly.get()) { return; } + // don't restore on readonly mode or when there is custom nav + if (doc.isReadonly.get() || doc.hasCustomNav.get()) { return; } // on view shown this._currentViewListener.autoDispose(doc.currentView.addListener(async view => { @@ -114,7 +117,7 @@ class EditMemoryStorage { private _entry: LastEditData | null = null; private _timestamp = 0; - constructor(private _docId: string, private _storage = getStorage()) { + constructor(private _key: string, private _storage = getStorage()) { } public updateValue(pos: CellPosition, value: EditorState): void { @@ -136,13 +139,13 @@ class EditMemoryStorage { return this._timestamp; } - protected _key() { - return `grist-last-edit-${this._docId}`; + protected _storageKey() { + return `grist-last-edit-${this._key}`; } protected load() { const storage = this._storage; - const data = storage.getItem(this._key()); + const data = storage.getItem(this._storageKey()); this._entry = null; this._timestamp = 0; @@ -166,14 +169,14 @@ class EditMemoryStorage { // if entry was removed - clear the storage if (!this._entry) { - storage.removeItem(this._key()); + storage.removeItem(this._storageKey()); return; } try { this._timestamp = Date.now(); const data = { timestamp: this._timestamp, entry: this._entry }; - storage.setItem(this._key(), JSON.stringify(data)); + storage.setItem(this._storageKey(), JSON.stringify(data)); } catch (ex) { console.error("Can't save current edited cell state. Error message: " + ex?.message); } diff --git a/test/nbrowser/gristUtils.ts b/test/nbrowser/gristUtils.ts index 99c7e4c3..16f76a54 100644 --- a/test/nbrowser/gristUtils.ts +++ b/test/nbrowser/gristUtils.ts @@ -1838,6 +1838,20 @@ export async function getEnabledOptions(): Promise { return options; } +/** + * Runs action in a separate tab, closing the tab after. + * In case of an error tab is not closed, consider using cleanupExtraWindows + * on whole test suit if needed. + */ +export async function onNewTab(action: () => Promise) { + await driver.executeScript("return window.open('about:blank', '_blank')"); + const tabs = await driver.getAllWindowHandles(); + await driver.switchTo().window(tabs[tabs.length - 1]); + await action(); + await driver.close(); + await driver.switchTo().window(tabs[tabs.length - 2]); +} + } // end of namespace gristUtils stackWrapOwnMethods(gristUtils);