Skip to content

Commit 1f18301

Browse files
committed
Migrate localStorage
1 parent d2a7600 commit 1f18301

File tree

2 files changed

+51
-3
lines changed

2 files changed

+51
-3
lines changed

.eslintrc.cjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ module.exports = {
1818
'no-constant-condition': ['error', {checkLoops: false}],
1919
'no-control-regex': ['off'],
2020
'no-empty': ['error', {allowEmptyCatch: true}],
21+
'prefer-const': ['error', {destructuring: 'all'}],
2122
quotes: ['error', 'single'],
2223
semi: ['error', 'never'],
2324
'@typescript-eslint/no-empty-function': ['off'],

src/dialog/browser/storage.ts

Lines changed: 50 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,12 @@ https://github.com/curiousdannii/asyncglk
1212
import {decode as base32768_decode, encode as base32768_encode} from 'base32768'
1313

1414
import {DirBrowser, NullProvider} from './common.js'
15-
import type {Provider} from './interface.js'
15+
import type {FilesMetadata, Provider} from './interface.js'
1616

1717
//type WebStorageFileMetadata = Pick<FileData, 'atime' | 'mtime'>
1818

1919
const METADATA_KEY = 'dialog_metadata'
20+
const STORAGE_VERSION_KEY = 'dialog_storage_version'
2021

2122
const enum MetadataUpdateOperation {
2223
DELETE = 1,
@@ -35,7 +36,9 @@ export class WebStorageProvider implements Provider {
3536
this.prefix = prefix
3637
this.store = store
3738

38-
// TODO: upgrade storage
39+
if (store === localStorage) {
40+
migrate_localStorage()
41+
}
3942
}
4043

4144
async browse(): Promise<DirBrowser> {
@@ -99,7 +102,7 @@ export class WebStorageProvider implements Provider {
99102

100103
private update_metadata(path: string, op: MetadataUpdateOperation) {
101104
const now = Date.now()
102-
const metadata = this.metadata()
105+
const metadata: FilesMetadata = this.metadata()
103106
switch (op) {
104107
case MetadataUpdateOperation.DELETE:
105108
delete metadata[path]
@@ -118,4 +121,48 @@ export class WebStorageProvider implements Provider {
118121
}
119122
this.store.setItem(METADATA_KEY, JSON.stringify(metadata))
120123
}
124+
}
125+
126+
const DIALOG_V1_TYPES_TO_EXTS: Record<string, string> = {
127+
data: 'glkdata',
128+
save: 'glksave',
129+
transcript: 'txt',
130+
}
131+
export function migrate_localStorage() {
132+
const now = Date.now()
133+
const version = parseInt(localStorage.getItem(STORAGE_VERSION_KEY) || '', 10)
134+
if (version < 2) {
135+
console.log('Dialog: updating localStorage to version 2')
136+
const metadata: FilesMetadata = {}
137+
for (let [key, data] of Object.entries<string>(localStorage)) {
138+
if (key.startsWith('autosave:')) {
139+
// We're not keeping any old autosaves
140+
localStorage.removeItem(key)
141+
}
142+
if (key.startsWith('content:')) {
143+
const key_data = /^content:(\w+):(\w*):(.+)$/.exec(key)
144+
if (key_data) {
145+
const path = `/usr/${key_data[3]}.${DIALOG_V1_TYPES_TO_EXTS[key_data[1]] || key_data[1]}`
146+
if (data !== '' && version < 1) {
147+
data = base32768_encode(/\[[,\d]*\]/.test(data) ? JSON.parse(data) : Uint8Array.from(data, ch => ch.charCodeAt(0)))
148+
}
149+
localStorage.setItem(path, data)
150+
const dirent_key = 'dirent' + key.substring(7)
151+
const dirent = localStorage.getItem(dirent_key) || ''
152+
const dirent_data = /^created:\d+,modified:(\d+)$/.exec(dirent)
153+
metadata[path] = {
154+
atime: parseInt(dirent_data?.[1] || '', 10) || now,
155+
mtime: parseInt(dirent_data?.[1] || '', 10) || now,
156+
}
157+
localStorage.removeItem(dirent_key)
158+
}
159+
localStorage.removeItem(key)
160+
}
161+
}
162+
localStorage.setItem(METADATA_KEY, JSON.stringify(metadata))
163+
localStorage.setItem(STORAGE_VERSION_KEY, '2')
164+
}
165+
if (version > 2) {
166+
throw new Error('dialog_storage_version is newer than this library supports')
167+
}
121168
}

0 commit comments

Comments
 (0)