mirror of
https://github.com/philomena-dev/philomena.git
synced 2025-03-17 17:10:03 +01:00
Add autocomplete history store
This commit is contained in:
parent
a77b8dd81c
commit
99e597d94d
1 changed files with 95 additions and 0 deletions
95
assets/js/autocomplete/history/store.ts
Normal file
95
assets/js/autocomplete/history/store.ts
Normal file
|
@ -0,0 +1,95 @@
|
||||||
|
import store from '../../utils/store';
|
||||||
|
/**
|
||||||
|
* The root JSON object that contains the history records and is persisted to disk.
|
||||||
|
*/
|
||||||
|
interface History {
|
||||||
|
/**
|
||||||
|
* Used to track the version of the schema layout just in case we do any
|
||||||
|
* breaking changes to this schema so that we can properly migrate old
|
||||||
|
* search history data. It's also used to prevent older versions of
|
||||||
|
* the frontend code from trying to use the newer incompatible schema they
|
||||||
|
* know nothing about (extremely improbable, but just in case).
|
||||||
|
*/
|
||||||
|
schemaVersion: 1;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The list of history records sorted from the last recently used to the oldest unused.
|
||||||
|
*/
|
||||||
|
records: string[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* History store backend is responsible for parsing and serializing the data
|
||||||
|
* to/from `localStorage`. It handles versioning of the schema, and transparently
|
||||||
|
* disables writing to the storage if the schema version is unknown to prevent
|
||||||
|
* data loss (extremely improbable, but just in case).
|
||||||
|
*/
|
||||||
|
export class HistoryStore {
|
||||||
|
private writable: boolean = true;
|
||||||
|
private readonly key: string;
|
||||||
|
|
||||||
|
constructor(key: string) {
|
||||||
|
this.key = key;
|
||||||
|
}
|
||||||
|
|
||||||
|
read(): string[] {
|
||||||
|
return this.extractRecords(store.get<History>(this.key));
|
||||||
|
}
|
||||||
|
|
||||||
|
write(records: string[]): void {
|
||||||
|
if (!this.writable) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const history: History = {
|
||||||
|
schemaVersion: 1,
|
||||||
|
records,
|
||||||
|
};
|
||||||
|
|
||||||
|
const start = performance.now();
|
||||||
|
store.set(this.key, history);
|
||||||
|
|
||||||
|
const end = performance.now();
|
||||||
|
console.debug(
|
||||||
|
`Writing ${records.length} history records to the localStorage took ${end - start}ms. ` +
|
||||||
|
`Records: ${records.length}`,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the records from the history. To do this, we first need to migrate
|
||||||
|
* the history object to the latest schema version if necessary.
|
||||||
|
*/
|
||||||
|
private extractRecords(history: History | null): string[] {
|
||||||
|
// `null` here means we are starting from the initial state (empty list of records).
|
||||||
|
if (history === null) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
// We have only one version at the time of this writing, so we don't need
|
||||||
|
// to do any migration yet. Hopefully we never need to do a breaking change
|
||||||
|
// and this stays at version `1` forever.
|
||||||
|
const latestSchemaVersion = 1;
|
||||||
|
|
||||||
|
switch (history.schemaVersion) {
|
||||||
|
case latestSchemaVersion:
|
||||||
|
return history.records;
|
||||||
|
default:
|
||||||
|
// It's very unlikely that we ever hit this branch.
|
||||||
|
console.warn(
|
||||||
|
`Unknown search history schema version: '${history.schemaVersion}'. ` +
|
||||||
|
`This frontend code was built with the maximum supported schema version ` +
|
||||||
|
`'${latestSchemaVersion}'. The search history will be disabled for this ` +
|
||||||
|
`session to prevent potential history data loss. The cause of the version ` +
|
||||||
|
`mismatch may be that a newer version of the frontend code is running in a ` +
|
||||||
|
`separate tab, or you were mistakenly served with an older version of the ` +
|
||||||
|
`frontend code.`,
|
||||||
|
);
|
||||||
|
|
||||||
|
// Disallow writing to the storage to prevent data loss.
|
||||||
|
this.writable = false;
|
||||||
|
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Add table
Reference in a new issue