(core) Cursor position observable on a GristDoc wasn't triggered when a view was changed.

Summary: Cursor position observable was created using GrainJS, but the fields it was using were created using knockout observables. In a result the cursor position wasn't recomputed when a view was changed or an active section was deleted.

Test Plan: Browser tests

Reviewers: dsagal

Reviewed By: dsagal

Differential Revision: https://phab.getgrist.com/D2850
This commit is contained in:
Jarosław Sadziński 2021-06-09 17:07:16 +02:00
parent 8138cc3123
commit af76c11be6

View File

@ -248,16 +248,25 @@ export class GristDoc extends DisposableWithEvents {
// create current view observer // create current view observer
this.currentView = Observable.create<BaseView | null>(this, null); this.currentView = Observable.create<BaseView | null>(this, null);
// first create a computed observable for current view
// create computed observable for viewInstance - if it is loaded or not
// Add an artificial intermediary computed only to delay the evaluation of currentView, so
// that it happens after section.viewInstance is set. If it happens before, then
// section.viewInstance is seen as null, and as it gets updated, GrainJS refuses to
// recalculate this computed since it was already calculated in the same tick.
const activeViewId = Computed.create(this, (use) => use(this.activeViewId));
const viewInstance = Computed.create(this, (use) => { const viewInstance = Computed.create(this, (use) => {
const section = use(this.viewModel.activeSection); const section = use(this.viewModel.activeSection);
const viewId = use(activeViewId);
const view = use(section.viewInstance); const view = use(section.viewInstance);
return view; return (typeof viewId === 'number') ? view : null;
}); });
// then listen if the view is present, because we still need to wait for it load properly // then listen if the view is present, because we still need to wait for it load properly
this.autoDispose(viewInstance.addListener(async (view) => { this.autoDispose(viewInstance.addListener(async (view) => {
if (!view) { return; } if (!view) { return; }
await view.getLoadingDonePromise(); await view.getLoadingDonePromise();
// finally set the current view as fully loaded
this.currentView.set(view); this.currentView.set(view);
})); }));