mirror of
https://github.com/gristlabs/grist-core.git
synced 2024-10-27 20:44:07 +00:00
(core) Avoid clashes with rick rowing and tours
Summary: In certain scenarios, it's possible for a Grist tour and a tip that kicks off an easter egg to be shown on screen at the same time. To deconflict, we now check for the presence of one or the other and avoid showing both. Test Plan: Browser tests. Reviewers: paulfitz Reviewed By: paulfitz Differential Revision: https://phab.getgrist.com/D3840
This commit is contained in:
parent
58ef8d59b5
commit
5b2fb62627
@ -197,6 +197,7 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
private _isRickRowing: Observable<boolean> = Observable.create(this, false);
|
private _isRickRowing: Observable<boolean> = Observable.create(this, false);
|
||||||
private _showBackgroundVideoPlayer: Observable<boolean> = Observable.create(this, false);
|
private _showBackgroundVideoPlayer: Observable<boolean> = Observable.create(this, false);
|
||||||
private _backgroundVideoPlayerHolder: Holder<YouTubePlayer> = Holder.create(this);
|
private _backgroundVideoPlayerHolder: Holder<YouTubePlayer> = Holder.create(this);
|
||||||
|
private _disableAutoStartingTours: boolean = false;
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
@ -278,7 +279,8 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
|
|
||||||
// Subscribe to URL state, and navigate to anchor or open a popup if necessary.
|
// Subscribe to URL state, and navigate to anchor or open a popup if necessary.
|
||||||
this.autoDispose(subscribe(urlState().state, async (use, state) => {
|
this.autoDispose(subscribe(urlState().state, async (use, state) => {
|
||||||
if (state.hash) {
|
if (!state.hash) { return; }
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (state.hash.popup) {
|
if (state.hash.popup) {
|
||||||
await this.openPopup(state.hash);
|
await this.openPopup(state.hash);
|
||||||
@ -287,7 +289,9 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
const cursorPos = this._getCursorPosFromHash(state.hash);
|
const cursorPos = this._getCursorPosFromHash(state.hash);
|
||||||
await this.recursiveMoveToCursorPos(cursorPos, true);
|
await this.recursiveMoveToCursorPos(cursorPos, true);
|
||||||
}
|
}
|
||||||
if (state.hash.rickRow && !this._isRickRowing.get()) {
|
|
||||||
|
const isTourOrTutorialActive = isTourActive() || this.docModel.isTutorial();
|
||||||
|
if (state.hash.rickRow && !this._isRickRowing.get() && !isTourOrTutorialActive) {
|
||||||
YouTubePlayer.create(this._backgroundVideoPlayerHolder, RICK_ROLL_YOUTUBE_EMBED_ID, {
|
YouTubePlayer.create(this._backgroundVideoPlayerHolder, RICK_ROLL_YOUTUBE_EMBED_ID, {
|
||||||
height: '100%',
|
height: '100%',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
@ -309,7 +313,8 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
this._waitForView()
|
this._waitForView()
|
||||||
.then(() => {
|
.then(() => {
|
||||||
const cursor = document.querySelector('.selected_cursor.active_cursor');
|
const cursor = document.querySelector('.selected_cursor.active_cursor');
|
||||||
if (cursor) {
|
if (!cursor) { return; }
|
||||||
|
|
||||||
this.behavioralPromptsManager.showTip(cursor, 'rickRow', {
|
this.behavioralPromptsManager.showTip(cursor, 'rickRow', {
|
||||||
forceShow: true,
|
forceShow: true,
|
||||||
hideDontShowTips: true,
|
hideDontShowTips: true,
|
||||||
@ -317,7 +322,6 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
showOnMobile: true,
|
showOnMobile: true,
|
||||||
onDispose: () => this.playRickRollVideo(),
|
onDispose: () => this.playRickRollVideo(),
|
||||||
});
|
});
|
||||||
}
|
|
||||||
})
|
})
|
||||||
.catch(reportError);
|
.catch(reportError);
|
||||||
}
|
}
|
||||||
@ -326,7 +330,6 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
} finally {
|
} finally {
|
||||||
setTimeout(finalizeAnchor, 0);
|
setTimeout(finalizeAnchor, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}));
|
}));
|
||||||
|
|
||||||
let isStartingTourOrTutorial = false;
|
let isStartingTourOrTutorial = false;
|
||||||
@ -337,12 +340,17 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const shouldStartTutorial = this.docModel.isTutorial();
|
const isTutorial = this.docModel.isTutorial();
|
||||||
// Onboarding tours were not designed with mobile support in mind. Disable until fixed.
|
// Onboarding tours were not designed with mobile support in mind. Disable until fixed.
|
||||||
if (isNarrowScreen() && !shouldStartTutorial) {
|
if (isNarrowScreen() && !isTutorial) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Onboarding tours can conflict with rick rowing.
|
||||||
|
if (state.hash?.rickRow) {
|
||||||
|
this._disableAutoStartingTours = true;
|
||||||
|
}
|
||||||
|
|
||||||
// If we have an active tour or tutorial (or are in the process of starting one), don't start
|
// If we have an active tour or tutorial (or are in the process of starting one), don't start
|
||||||
// a new one.
|
// a new one.
|
||||||
const hasActiveTourOrTutorial = isTourActive() || !this._docTutorialHolder.isEmpty();
|
const hasActiveTourOrTutorial = isTourActive() || !this._docTutorialHolder.isEmpty();
|
||||||
@ -350,6 +358,7 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const shouldStartTutorial = isTutorial;
|
||||||
const shouldStartDocTour = state.docTour || this._shouldAutoStartDocTour();
|
const shouldStartDocTour = state.docTour || this._shouldAutoStartDocTour();
|
||||||
const shouldStartWelcomeTour = state.welcomeTour || this._shouldAutoStartWelcomeTour();
|
const shouldStartWelcomeTour = state.welcomeTour || this._shouldAutoStartWelcomeTour();
|
||||||
if (shouldStartTutorial || shouldStartDocTour || shouldStartWelcomeTour) {
|
if (shouldStartTutorial || shouldStartDocTour || shouldStartWelcomeTour) {
|
||||||
@ -1438,7 +1447,7 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
* seen the tour before.
|
* seen the tour before.
|
||||||
*/
|
*/
|
||||||
private _shouldAutoStartDocTour(): boolean {
|
private _shouldAutoStartDocTour(): boolean {
|
||||||
if (this.docModel.isTutorial()) {
|
if (this._disableAutoStartingTours || this.docModel.isTutorial()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1454,7 +1463,7 @@ export class GristDoc extends DisposableWithEvents {
|
|||||||
private _shouldAutoStartWelcomeTour(): boolean {
|
private _shouldAutoStartWelcomeTour(): boolean {
|
||||||
// If a doc tutorial or tour are available, leave the welcome tour for another
|
// If a doc tutorial or tour are available, leave the welcome tour for another
|
||||||
// doc (e.g. a new one).
|
// doc (e.g. a new one).
|
||||||
if (this.docModel.isTutorial() || this.docModel.hasDocTour()) {
|
if (this._disableAutoStartingTours || this.docModel.isTutorial() || this.docModel.hasDocTour()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,6 +224,16 @@ describe('DocTutorial', function () {
|
|||||||
assert.isTrue(await driver.find('.test-doc-tutorial-popup-footer').isDisplayed());
|
assert.isTrue(await driver.find('.test-doc-tutorial-popup-footer').isDisplayed());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('does not play an easter egg when opening an anchor link encoded with rr', async function() {
|
||||||
|
await gu.getCell({rowNum: 1, col: 0}).click();
|
||||||
|
const link = await gu.getAnchor();
|
||||||
|
const easterEggLink = link.replace('r1', 'rr1');
|
||||||
|
await driver.get(easterEggLink);
|
||||||
|
await gu.waitForAnchor();
|
||||||
|
assert.isFalse(await driver.find('.test-behavioral-prompt').isPresent());
|
||||||
|
await gu.assertIsRickRowing(false);
|
||||||
|
});
|
||||||
|
|
||||||
it('remembers the last slide the user had open', async function() {
|
it('remembers the last slide the user had open', async function() {
|
||||||
await driver.find('.test-doc-tutorial-popup-slide-3').click();
|
await driver.find('.test-doc-tutorial-popup-slide-3').click();
|
||||||
// There's a 1000ms debounce in place for updates to the last slide.
|
// There's a 1000ms debounce in place for updates to the last slide.
|
||||||
|
@ -3012,6 +3012,15 @@ export async function skipWelcomeQuestions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Asserts whether a video of Never Gonna Give You Up is playing in the background.
|
||||||
|
*/
|
||||||
|
export async function assertIsRickRowing(expected: boolean) {
|
||||||
|
assert.equal(await driver.find('.test-gristdoc-stop-rick-rowing').isPresent(), expected);
|
||||||
|
assert.equal(await driver.find('.test-gristdoc-background-video').isPresent(), expected);
|
||||||
|
assert.equal(await driver.find('iframe#youtube-player-dQw4w9WgXcQ').isPresent(), expected);
|
||||||
|
}
|
||||||
|
|
||||||
} // end of namespace gristUtils
|
} // end of namespace gristUtils
|
||||||
|
|
||||||
stackWrapOwnMethods(gristUtils);
|
stackWrapOwnMethods(gristUtils);
|
||||||
|
Loading…
Reference in New Issue
Block a user