Skip to content

Commit 30a9534

Browse files
Merge pull request #1895 from NullVoxPopuli/save-last-format-and-doc-in-localstorage
Save last format and document in localStorage
2 parents 9d0ea3d + 7a42ada commit 30a9534

File tree

5 files changed

+89
-13
lines changed

5 files changed

+89
-13
lines changed

apps/repl/app/routes/edit.ts

+17
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import Route from '@ember/routing/route';
22
import { service } from '@ember/service';
33

44
import { DEFAULT_SNIPPET } from 'limber/snippets';
5+
import { formatFrom } from 'limber/utils/messaging';
56

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

3738
if (!hasCode) {
39+
/**
40+
* Default starting doc is
41+
* user-configurable.
42+
* (whatever they did last)
43+
*/
44+
let format = localStorage.getItem('format');
45+
let doc = localStorage.getItem('document');
46+
47+
if (format && doc) {
48+
console.info(`Found format and document in localStorage. Using those.`);
49+
transition.abort();
50+
this.editor.fileURIComponent.set(doc, formatFrom(format));
51+
52+
return;
53+
}
54+
3855
console.warn(
3956
'URL contained no document information in the SearchParams. ' +
4057
'Assuming glimdown and using the default sample snippet.'

apps/repl/app/utils/editor-text.ts

+35-9
Original file line numberDiff line numberDiff line change
@@ -158,12 +158,22 @@ export class FileURIComponent {
158158
return base ?? window.location.toString();
159159
};
160160

161-
#updateWaiter: unknown;
162161
#frame?: number;
163162
#qps: URLSearchParams | undefined;
163+
#tokens: unknown[] = [];
164164
#updateQPs = async (rawText: string, format: Format) => {
165+
this.#tokens.push(queueWaiter.beginAsync());
166+
this.#_updateQPs(rawText, format);
167+
};
168+
169+
#cleanup = () => {
170+
this.#tokens.forEach((token) => {
171+
queueWaiter.endAsync(token);
172+
});
173+
};
174+
175+
#_updateQPs = async (rawText: string, format: Format) => {
165176
if (this.#frame) cancelAnimationFrame(this.#frame);
166-
if (!this.#updateWaiter) this.#updateWaiter = queueWaiter.beginAsync();
167177

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

185+
// @ts-expect-error this works
186+
if (this.#qps?.c === qps.get('c') && this.#qps?.format === qps.get('format')) {
187+
// no-op, we should not have gotten here
188+
// it's a mistake to have tried to have update QPs.
189+
// Someone should debug this.
190+
this.#cleanup();
191+
192+
return;
193+
}
194+
195+
localStorage.setItem('format', formatFrom(format));
196+
localStorage.setItem('document', rawText);
197+
175198
this.#qps = {
176199
...this.#qps,
177200
...qps,
178201
};
179202

180203
this.#frame = requestAnimationFrame(async () => {
181204
if (isDestroyed(this) || isDestroying(this)) {
182-
queueWaiter.endAsync(this.#updateWaiter);
183-
this.#updateWaiter = null;
205+
this.#cleanup();
184206

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

193215
if (isDestroyed(this) || isDestroying(this)) {
194-
queueWaiter.endAsync(this.#updateWaiter);
195-
this.#updateWaiter = null;
216+
this.#cleanup();
196217

197218
return;
198219
}
199220

200-
queueWaiter.endAsync(this.#updateWaiter);
201-
this.#updateWaiter = null;
202-
203221
// On initial load, if we call #updateQPs,
204222
// we may not have a currentURL, because the first transition has yet to complete
205223
let base = this.router.currentURL?.split('?')[0];
206224

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

234+
/**
235+
* At some point this added qps
236+
* we don't want them though, so we'll strip them
237+
*/
238+
214239
let next = `${base}?${qps}`;
215240

216241
this.router.replaceWith(next);
217242
this.#text = rawText;
243+
this.#cleanup();
218244
});
219245
};
220246
}

apps/repl/tests/application/-page/index.ts

+18-4
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,19 @@ export class Page extends PageObject {
2222

2323
async expectRedirectToContent(
2424
to: string,
25-
{ c, t, format }: { t?: string; c?: string; format?: string } = {}
25+
{
26+
c,
27+
t,
28+
format,
29+
checks,
30+
}: { t?: string; c?: string; format?: string; checks?: { aborted?: boolean } } = {}
2631
) {
2732
let sawExpectedError = false;
2833

34+
let _checks = {
35+
aborted: checks?.aborted ?? true,
36+
};
37+
2938
try {
3039
await visit(to);
3140
} catch (e) {
@@ -45,14 +54,19 @@ export class Page extends PageObject {
4554
sawExpectedError = true;
4655
}
4756

48-
assert(`Expected to see a TransitionAborted error, but it did not occur.`, sawExpectedError);
57+
if (_checks.aborted) {
58+
assert(
59+
`Expected to see a TransitionAborted error, but it did not occur. currentURL: ${currentURL()}`,
60+
sawExpectedError
61+
);
62+
}
4963

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

5367
let url = currentURL();
5468

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

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

69-
assert(`Missing c query param`, lzString);
83+
assert(`Missing c query param. currentURL: ${url}`, lzString);
7084

7185
let value = decompressFromEncodedURIComponent(lzString);
7286

apps/repl/tests/application/editor-format-test.gts

+16
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,22 @@ module('Editor > Format', function (hooks) {
5454
assert.true(page.editor.hasText('hi'), 'has passed text as well');
5555
});
5656

57+
test('after selecting text, it loads again when visiting /', async function (assert) {
58+
await visit(`/edit?format=gjs&t=${defaultText}`);
59+
await page.editor.load();
60+
61+
assert.strictEqual(page.editor.format, 'gjs');
62+
assert.true(page.editor.hasText('hi'), 'has passed text as well');
63+
64+
await page.expectRedirectToContent(`application`, {
65+
format: 'gjs',
66+
t: defaultText,
67+
checks: { aborted: false },
68+
});
69+
assert.strictEqual(page.editor.format, 'gjs');
70+
assert.true(page.editor.hasText('hi'), 'has passed text as well');
71+
});
72+
5773
test('can start with glimdown, and change to gjs', async function (assert) {
5874
await page.expectRedirectToContent(`/edit`, {
5975
format: 'glimdown',

apps/repl/tests/test-helper.ts

+3
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Object.assign(window, { getSettledState, getPendingWaiterState, currentURL, curr
2222

2323
setup(QUnit.assert);
2424

25+
QUnit.testStart(() => {
26+
localStorage.clear();
27+
});
2528
QUnit.testDone(resetOnerror);
2629

2730
start();

0 commit comments

Comments
 (0)