Improves(?) save / load
This commit is contained in:
parent
e08f8f0116
commit
a689422576
4 changed files with 49 additions and 26 deletions
|
@ -20,6 +20,7 @@
|
||||||
"@stitches/react": "^0.1.9",
|
"@stitches/react": "^0.1.9",
|
||||||
"browser-fs-access": "^0.17.3",
|
"browser-fs-access": "^0.17.3",
|
||||||
"framer-motion": "^4.1.16",
|
"framer-motion": "^4.1.16",
|
||||||
|
"idb-keyval": "^5.0.6",
|
||||||
"ismobilejs": "^1.1.1",
|
"ismobilejs": "^1.1.1",
|
||||||
"next": "10.2.0",
|
"next": "10.2.0",
|
||||||
"next-pwa": "^5.2.21",
|
"next-pwa": "^5.2.21",
|
||||||
|
|
|
@ -5,9 +5,6 @@ import { getShapeUtils } from 'lib/shape-utils'
|
||||||
import { getPage, getShape, isMobile, updateParents } from 'utils/utils'
|
import { getPage, getShape, isMobile, updateParents } from 'utils/utils'
|
||||||
import * as vec from 'utils/vec'
|
import * as vec from 'utils/vec'
|
||||||
import commands from 'state/commands'
|
import commands from 'state/commands'
|
||||||
|
|
||||||
let prevEndPoint: number[]
|
|
||||||
|
|
||||||
export default class BrushSession extends BaseSession {
|
export default class BrushSession extends BaseSession {
|
||||||
origin: number[]
|
origin: number[]
|
||||||
previous: number[]
|
previous: number[]
|
||||||
|
|
|
@ -2,23 +2,33 @@ import * as fa from 'browser-fs-access'
|
||||||
import { Data, Page, PageState, TLDocument } from 'types'
|
import { Data, Page, PageState, TLDocument } from 'types'
|
||||||
import { setToArray } from 'utils/utils'
|
import { setToArray } from 'utils/utils'
|
||||||
import state from './state'
|
import state from './state'
|
||||||
|
import { current } from 'immer'
|
||||||
import { v4 as uuid } from 'uuid'
|
import { v4 as uuid } from 'uuid'
|
||||||
|
import * as idb from 'idb-keyval'
|
||||||
|
|
||||||
const CURRENT_VERSION = 'code_slate_0.0.5'
|
const CURRENT_VERSION = 'code_slate_0.0.5'
|
||||||
const DOCUMENT_ID = '0001'
|
const DOCUMENT_ID = '0001'
|
||||||
|
|
||||||
function storageId(fileId: string, label: string, id: string) {
|
function storageId(fileId: string, label: string, id?: string) {
|
||||||
return `${CURRENT_VERSION}_doc_${fileId}_${label}_${id}`
|
return [CURRENT_VERSION, fileId, label, id].filter(Boolean).join('_')
|
||||||
}
|
}
|
||||||
|
|
||||||
class Storage {
|
class Storage {
|
||||||
previousSaveHandle?: fa.FileSystemHandle
|
previousSaveHandle?: fa.FileSystemHandle
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
// this.loadPreviousHandle() // Still needs debugging
|
||||||
|
}
|
||||||
|
|
||||||
firstLoad(data: Data) {
|
firstLoad(data: Data) {
|
||||||
const lastOpened = localStorage.getItem(`${CURRENT_VERSION}_lastOpened`)
|
const lastOpened = localStorage.getItem(`${CURRENT_VERSION}_lastOpened`)
|
||||||
|
|
||||||
this.loadDocumentFromLocalStorage(data, lastOpened || DOCUMENT_ID)
|
this.loadDocumentFromLocalStorage(data, lastOpened || DOCUMENT_ID)
|
||||||
|
|
||||||
this.loadPage(data, data.currentPageId)
|
this.loadPage(data, data.currentPageId)
|
||||||
|
|
||||||
this.saveToLocalStorage(data, data.document.id)
|
this.saveToLocalStorage(data, data.document.id)
|
||||||
|
|
||||||
localStorage.setItem(`${CURRENT_VERSION}_lastOpened`, data.document.id)
|
localStorage.setItem(`${CURRENT_VERSION}_lastOpened`, data.document.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,18 +38,14 @@ class Storage {
|
||||||
this.savePage(restoredData, restoredData.document.id, key)
|
this.savePage(restoredData, restoredData.document.id, key)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Empty shapes in state for each page
|
// Empty current state.
|
||||||
for (let key in restoredData.document.pages) {
|
|
||||||
// restoredData.document.pages[key].shapes = {}
|
|
||||||
}
|
|
||||||
|
|
||||||
data.document = {} as TLDocument
|
data.document = {} as TLDocument
|
||||||
data.pageStates = {}
|
data.pageStates = {}
|
||||||
|
|
||||||
// Merge restored data into state
|
// Merge restored data into state.
|
||||||
Object.assign(data, restoredData)
|
Object.assign(data, restoredData)
|
||||||
|
|
||||||
// Minor migrtation: add id and name to document
|
// Add id and name to document, just in case.
|
||||||
data.document = {
|
data.document = {
|
||||||
id: 'document0',
|
id: 'document0',
|
||||||
name: 'My Document',
|
name: 'My Document',
|
||||||
|
@ -63,16 +69,20 @@ class Storage {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
const restoredData = JSON.parse(savedData)
|
const restoredData: any = JSON.parse(savedData)
|
||||||
|
|
||||||
|
for (let pageId in restoredData.document.pages) {
|
||||||
|
const selectedIds = restoredData.pageStates[pageId].selectedIds
|
||||||
|
restoredData.pageStates[pageId].selectedIds = new Set(selectedIds)
|
||||||
|
}
|
||||||
|
|
||||||
this.load(data, restoredData)
|
this.load(data, restoredData)
|
||||||
}
|
}
|
||||||
|
|
||||||
getDataToSave = (data: Data) => {
|
getDataToSave = (data: Data) => {
|
||||||
const dataToSave: any = { ...data }
|
const dataToSave = current(data) as any
|
||||||
|
|
||||||
for (let pageId in data.document.pages) {
|
for (let pageId in data.document.pages) {
|
||||||
// Page
|
|
||||||
const savedPage = localStorage.getItem(
|
const savedPage = localStorage.getItem(
|
||||||
storageId(data.document.id, 'page', pageId)
|
storageId(data.document.id, 'page', pageId)
|
||||||
)
|
)
|
||||||
|
@ -82,20 +92,21 @@ class Storage {
|
||||||
dataToSave.document.pages[pageId] = restored
|
dataToSave.document.pages[pageId] = restored
|
||||||
}
|
}
|
||||||
|
|
||||||
dataToSave.pageStates = {}
|
const pageState = dataToSave.pageStates[pageId]
|
||||||
|
pageState.selectedIds = setToArray(pageState.selectedIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
return JSON.stringify(dataToSave, null, 2)
|
return JSON.stringify(dataToSave, null, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveToLocalStorage = (data: Data, id = data.document.id) => {
|
saveToLocalStorage = (data: Data, fileId = data.document.id) => {
|
||||||
if (typeof window === 'undefined') return
|
if (typeof window === 'undefined') return
|
||||||
if (typeof localStorage === 'undefined') return
|
if (typeof localStorage === 'undefined') return
|
||||||
|
|
||||||
const dataToSave = this.getDataToSave(data)
|
const dataToSave = this.getDataToSave(data)
|
||||||
|
|
||||||
// Save current data to local storage
|
// Save current data to local storage
|
||||||
localStorage.setItem(storageId(id, 'document', id), dataToSave)
|
localStorage.setItem(storageId(fileId, 'document', fileId), dataToSave)
|
||||||
}
|
}
|
||||||
|
|
||||||
loadDocumentFromJson(data: Data, restoredData: any) {
|
loadDocumentFromJson(data: Data, restoredData: any) {
|
||||||
|
@ -106,6 +117,15 @@ class Storage {
|
||||||
}
|
}
|
||||||
/* ---------------------- Pages --------------------- */
|
/* ---------------------- Pages --------------------- */
|
||||||
|
|
||||||
|
async loadPreviousHandle() {
|
||||||
|
const handle: fa.FileSystemHandle | undefined = await idb.get(
|
||||||
|
'previous_handle'
|
||||||
|
)
|
||||||
|
if (handle !== undefined) {
|
||||||
|
this.previousSaveHandle = handle
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
savePage(data: Data, fileId = data.document.id, pageId = data.currentPageId) {
|
savePage(data: Data, fileId = data.document.id, pageId = data.currentPageId) {
|
||||||
if (typeof window === 'undefined') return
|
if (typeof window === 'undefined') return
|
||||||
if (typeof localStorage === 'undefined') return
|
if (typeof localStorage === 'undefined') return
|
||||||
|
@ -127,14 +147,12 @@ class Storage {
|
||||||
...data.pageStates[pageId],
|
...data.pageStates[pageId],
|
||||||
}
|
}
|
||||||
|
|
||||||
const pageState = {
|
|
||||||
...currentPageState,
|
|
||||||
selectedIds: setToArray(currentPageState.selectedIds),
|
|
||||||
}
|
|
||||||
|
|
||||||
localStorage.setItem(
|
localStorage.setItem(
|
||||||
storageId(fileId, 'pageState', pageId),
|
storageId(fileId, 'pageState', pageId),
|
||||||
JSON.stringify(pageState)
|
JSON.stringify({
|
||||||
|
...currentPageState,
|
||||||
|
selectedIds: setToArray(currentPageState.selectedIds),
|
||||||
|
})
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -204,10 +222,10 @@ class Storage {
|
||||||
this.saveDataToFileSystem(data, uuid(), true)
|
this.saveDataToFileSystem(data, uuid(), true)
|
||||||
}
|
}
|
||||||
|
|
||||||
saveDataToFileSystem = (data: Data, id: string, saveAs: boolean) => {
|
saveDataToFileSystem = (data: Data, fileId: string, saveAs: boolean) => {
|
||||||
const json = this.getDataToSave(data)
|
const json = this.getDataToSave(data)
|
||||||
|
|
||||||
this.saveToLocalStorage(data, id)
|
this.saveToLocalStorage(data, fileId)
|
||||||
|
|
||||||
const blob = new Blob([json], {
|
const blob = new Blob([json], {
|
||||||
type: 'application/vnd.tldraw+json',
|
type: 'application/vnd.tldraw+json',
|
||||||
|
@ -230,6 +248,7 @@ class Storage {
|
||||||
.then((handle) => {
|
.then((handle) => {
|
||||||
this.previousSaveHandle = handle
|
this.previousSaveHandle = handle
|
||||||
state.send('SAVED_FILE_TO_FILE_SYSTEM')
|
state.send('SAVED_FILE_TO_FILE_SYSTEM')
|
||||||
|
idb.set('previous_handle', handle)
|
||||||
})
|
})
|
||||||
.catch((e) => {
|
.catch((e) => {
|
||||||
state.send('CANCELLED_SAVE', { reason: e.message })
|
state.send('CANCELLED_SAVE', { reason: e.message })
|
||||||
|
@ -237,6 +256,7 @@ class Storage {
|
||||||
}
|
}
|
||||||
|
|
||||||
loadDocumentFromFilesystem() {
|
loadDocumentFromFilesystem() {
|
||||||
|
console.warn('Loading file from file system.')
|
||||||
fa.fileOpen({
|
fa.fileOpen({
|
||||||
description: 'tldraw files',
|
description: 'tldraw files',
|
||||||
})
|
})
|
||||||
|
|
|
@ -4979,6 +4979,11 @@ iconv-lite@^0.6.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
safer-buffer ">= 2.1.2 < 3.0.0"
|
safer-buffer ">= 2.1.2 < 3.0.0"
|
||||||
|
|
||||||
|
idb-keyval@^5.0.6:
|
||||||
|
version "5.0.6"
|
||||||
|
resolved "https://registry.yarnpkg.com/idb-keyval/-/idb-keyval-5.0.6.tgz#62fe4a6703fb5ec86661f41330c94fda65e6d0e6"
|
||||||
|
integrity sha512-6lJuVbwyo82mKSH6Wq2eHkt9LcbwHAelMIcMe0tP4p20Pod7tTxq9zf0ge2n/YDfMOpDryerfmmYyuQiaFaKOg==
|
||||||
|
|
||||||
ieee754@^1.1.4:
|
ieee754@^1.1.4:
|
||||||
version "1.2.1"
|
version "1.2.1"
|
||||||
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
resolved "https://registry.yarnpkg.com/ieee754/-/ieee754-1.2.1.tgz#8eb7a10a63fff25d15a57b001586d177d1b0d352"
|
||||||
|
|
Loading…
Reference in a new issue