Skip to content

Commit

Permalink
Merge pull request #1895 from NullVoxPopuli/save-last-format-and-doc-…
Browse files Browse the repository at this point in the history
…in-localstorage

Save last format and document in localStorage
  • Loading branch information
NullVoxPopuli authored Jan 16, 2025
2 parents 9d0ea3d + 7a42ada commit 30a9534
Show file tree
Hide file tree
Showing 5 changed files with 89 additions and 13 deletions.
17 changes: 17 additions & 0 deletions apps/repl/app/routes/edit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import Route from '@ember/routing/route';
import { service } from '@ember/service';

import { DEFAULT_SNIPPET } from 'limber/snippets';
import { formatFrom } from 'limber/utils/messaging';

import type RouterService from '@ember/routing/router-service';
import type Transition from '@ember/routing/transition';
Expand Down Expand Up @@ -35,6 +36,22 @@ export default class EditRoute extends Route {
let hasFormat = qps.format !== undefined;

if (!hasCode) {
/**
* Default starting doc is
* user-configurable.
* (whatever they did last)
*/
let format = localStorage.getItem('format');
let doc = localStorage.getItem('document');

if (format && doc) {
console.info(`Found format and document in localStorage. Using those.`);
transition.abort();
this.editor.fileURIComponent.set(doc, formatFrom(format));

return;
}

console.warn(
'URL contained no document information in the SearchParams. ' +
'Assuming glimdown and using the default sample snippet.'
Expand Down
44 changes: 35 additions & 9 deletions apps/repl/app/utils/editor-text.ts
Original file line number Diff line number Diff line change
Expand Up @@ -158,12 +158,22 @@ export class FileURIComponent {
return base ?? window.location.toString();
};

#updateWaiter: unknown;
#frame?: number;
#qps: URLSearchParams | undefined;
#tokens: unknown[] = [];
#updateQPs = async (rawText: string, format: Format) => {
this.#tokens.push(queueWaiter.beginAsync());
this.#_updateQPs(rawText, format);
};

#cleanup = () => {
this.#tokens.forEach((token) => {
queueWaiter.endAsync(token);
});
};

#_updateQPs = async (rawText: string, format: Format) => {
if (this.#frame) cancelAnimationFrame(this.#frame);
if (!this.#updateWaiter) this.#updateWaiter = queueWaiter.beginAsync();

let encoded = compressToEncodedURIComponent(rawText);
let qps = new URLSearchParams(location.search);
Expand All @@ -172,15 +182,27 @@ export class FileURIComponent {
qps.delete('t');
qps.set('format', formatFrom(format));

// @ts-expect-error this works
if (this.#qps?.c === qps.get('c') && this.#qps?.format === qps.get('format')) {
// no-op, we should not have gotten here
// it's a mistake to have tried to have update QPs.
// Someone should debug this.
this.#cleanup();

return;
}

localStorage.setItem('format', formatFrom(format));
localStorage.setItem('document', rawText);

this.#qps = {
...this.#qps,
...qps,
};

this.#frame = requestAnimationFrame(async () => {
if (isDestroyed(this) || isDestroying(this)) {
queueWaiter.endAsync(this.#updateWaiter);
this.#updateWaiter = null;
this.#cleanup();

return;
}
Expand All @@ -191,30 +213,34 @@ export class FileURIComponent {
await new Promise((resolve) => setTimeout(resolve, DEBOUNCE_MS));

if (isDestroyed(this) || isDestroying(this)) {
queueWaiter.endAsync(this.#updateWaiter);
this.#updateWaiter = null;
this.#cleanup();

return;
}

queueWaiter.endAsync(this.#updateWaiter);
this.#updateWaiter = null;

// On initial load, if we call #updateQPs,
// we may not have a currentURL, because the first transition has yet to complete
let base = this.router.currentURL?.split('?')[0];

if (macroCondition(isTesting())) {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
base ??= (this.router as any) /* private API? */?.location?.path;
// @ts-expect-error private api
base = base.split('?')[0];
} else {
base ??= window.location.pathname;
}

/**
* At some point this added qps
* we don't want them though, so we'll strip them
*/

let next = `${base}?${qps}`;

this.router.replaceWith(next);
this.#text = rawText;
this.#cleanup();
});
};
}
22 changes: 18 additions & 4 deletions apps/repl/tests/application/-page/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,19 @@ export class Page extends PageObject {

async expectRedirectToContent(
to: string,
{ c, t, format }: { t?: string; c?: string; format?: string } = {}
{
c,
t,
format,
checks,
}: { t?: string; c?: string; format?: string; checks?: { aborted?: boolean } } = {}
) {
let sawExpectedError = false;

let _checks = {
aborted: checks?.aborted ?? true,
};

try {
await visit(to);
} catch (e) {
Expand All @@ -45,14 +54,19 @@ export class Page extends PageObject {
sawExpectedError = true;
}

assert(`Expected to see a TransitionAborted error, but it did not occur.`, sawExpectedError);
if (_checks.aborted) {
assert(
`Expected to see a TransitionAborted error, but it did not occur. currentURL: ${currentURL()}`,
sawExpectedError
);
}

// Allow time for transitions to settle
await settled();

let url = currentURL();

assert(`Expected an URL, got ${url}`, url);
assert(`Expected an URL -- via currentURL(), got ${url}`, url);

let [, search] = url.split('?');
let query = new URLSearchParams(search);
Expand All @@ -66,7 +80,7 @@ export class Page extends PageObject {
if (c) {
let lzString = query.get('c');

assert(`Missing c query param`, lzString);
assert(`Missing c query param. currentURL: ${url}`, lzString);

let value = decompressFromEncodedURIComponent(lzString);

Expand Down
16 changes: 16 additions & 0 deletions apps/repl/tests/application/editor-format-test.gts
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,22 @@ module('Editor > Format', function (hooks) {
assert.true(page.editor.hasText('hi'), 'has passed text as well');
});

test('after selecting text, it loads again when visiting /', async function (assert) {
await visit(`/edit?format=gjs&t=${defaultText}`);
await page.editor.load();

assert.strictEqual(page.editor.format, 'gjs');
assert.true(page.editor.hasText('hi'), 'has passed text as well');

await page.expectRedirectToContent(`application`, {
format: 'gjs',
t: defaultText,
checks: { aborted: false },
});
assert.strictEqual(page.editor.format, 'gjs');
assert.true(page.editor.hasText('hi'), 'has passed text as well');
});

test('can start with glimdown, and change to gjs', async function (assert) {
await page.expectRedirectToContent(`/edit`, {
format: 'glimdown',
Expand Down
3 changes: 3 additions & 0 deletions apps/repl/tests/test-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ Object.assign(window, { getSettledState, getPendingWaiterState, currentURL, curr

setup(QUnit.assert);

QUnit.testStart(() => {
localStorage.clear();
});
QUnit.testDone(resetOnerror);

start();

0 comments on commit 30a9534

Please sign in to comment.