Skip to content
This repository has been archived by the owner on Jun 14, 2021. It is now read-only.

Serialize project with msgpack #151

Merged
merged 3 commits into from Aug 30, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 4 additions & 0 deletions packages/delir-core/src/project/keyframe.ts
Expand Up @@ -39,6 +39,8 @@ export default class Keyframe<T extends KeyframeValueTypes = KeyframeValueTypes>
realValue = ColorRGBA.fromJSON(jsonValue.value)
} else if (jsonValue.type === 'asset') {
realValue = jsonValue.value
} else if (jsonValue.type === 'expression') {
realValue = Expression.fromJSON(jsonValue.value)
} else {
const __NEVER__: never = jsonValue
throw new Error(`Deserialization failed, unexpected object value on Keyframe#${keyframeJson.id}`)
Expand Down Expand Up @@ -110,6 +112,8 @@ export default class Keyframe<T extends KeyframeValueTypes = KeyframeValueTypes>
value = { type: 'color-rgba', value: this.value.toJSON() }
} else if (_.isObject(this.value) && _.has(this.value as AssetPointerScheme, 'assetId')) {
value = { type: 'asset', value: toJSON(this.value as AssetPointerScheme) }
} else if (_.isObject(this.value) && this.value instanceof Expression) {
value = { type: 'expression', value: this.value.toJSON() }
} else if (_.isObject(this.value)) {
throw new Error(`Serialization failed, unexpected value type on Keyframe#${this.id}`)
} else {
Expand Down
2 changes: 2 additions & 0 deletions packages/delir-core/src/project/scheme/keyframe.ts
Expand Up @@ -4,6 +4,7 @@
// import Size3D from '../../values/size-3d'
import { ColorRgbJSON } from '../../values/color-rgb'
import { ColorRgbaJSON } from '../../values/color-rgba'
import { ExpressionJSON } from '../../values/expression'

export interface AssetPointerScheme {
assetId: string
Expand All @@ -16,6 +17,7 @@ export type JSONKeyframeValueTypes =
| {type: 'color-rgb', value: ColorRgbJSON}
| {type: 'color-rgba', value: ColorRgbaJSON}
| {type: 'asset', value: AssetPointerScheme}
| {type: 'expression', value: ExpressionJSON}
// Point2D|Point3D|Size2D|Size3D

export interface KeyframeConfigScheme {
Expand Down
4 changes: 4 additions & 0 deletions packages/delir-core/src/values/expression.ts
Expand Up @@ -4,6 +4,10 @@ export interface ExpressionJSON {
}

export default class Expression {
public static fromJSON(json: ExpressionJSON) {
return new Expression(json.language, json.code)
}

constructor(
public language: string,
public code: string,
Expand Down
56 changes: 11 additions & 45 deletions packages/delir/actions/App.ts
Expand Up @@ -4,6 +4,7 @@ import { BSON } from 'bson'
import { remote } from 'electron'
import * as fs from 'fs-promise'
import * as _ from 'lodash'
import * as MsgPack from 'msgpack5'
import * as path from 'path'

import EditorStateStore from '../stores/EditorStateStore'
Expand Down Expand Up @@ -155,9 +156,8 @@ export const openProject = operation(async (context) => {

if (!path.length) return

const projectBson = await fs.readFile(path[0])
const projectJson = (new BSON()).deserialize(projectBson)

const projectMpk = await fs.readFile(path[0])
const projectJson = MsgPack().decode(projectMpk).project
const migratedProject = Delir.ProjectMigrator.migrate(projectJson)

await context.executeOperation(setActiveProject, {
Expand All @@ -166,52 +166,16 @@ export const openProject = operation(async (context) => {
})
})

export const overwriteProject = operation(async (context) => {
const state = context.getStore(EditorStateStore).getState()
const { project, projectPath } = state

if (!project) return

if (!projectPath) {
await context.executeOperation(saveProject, {})
return
}

const bson = new BSON()

await fs.writeFile(projectPath, bson.serialize(project.toPreBSON()))

await context.executeOperation(notify, {
message: 'Project saved',
title: '',
level: 'info',
timeout: 1000
})
})

export const saveProject = operation(async (context) => {
export const saveProject = operation(async (context, { path, silent = false }: { path: string, silent: boolean }) => {
const project = context.getStore(EditorStateStore).getState().project

if (!project) return

const path = remote.dialog.showSaveDialog({
title: 'Save as ...',
buttonLabel: 'Save',
filters: [
{
name: 'Delir Project File',
extensions: ['delir']
}
],
})

if (!path) return

const bson = new BSON()
await fs.writeFile(path, bson.serialize(project.toPreBSON()))
await fs.writeFile(path, MsgPack().encode({ project: project.toPreBSON() }))

context.executeOperation(setActiveProject, { project, path }) // update path
await context.executeOperation(notify, {

!silent && await context.executeOperation(notify, {
message: t('saved'),
title: '',
level: 'info',
Expand Down Expand Up @@ -240,12 +204,14 @@ export const autoSaveProject = operation(async (context) => {
const autoSaveFileName = `${frag.name}.auto-saved${frag.ext}`
const autoSavePath = path.join(frag.dir, autoSaveFileName)

const bson = new BSON()
await fs.writeFile(autoSavePath, bson.serialize(project.toPreBSON()))
await context.executeOperation(saveProject, { path: autoSavePath, silent: true })

context.executeOperation(notify, {
message: t('autoSaved', { fileName: autoSaveFileName }),
title: '',
level: 'info',
timeout: 2000
})
})

console.log(MsgPack().encode({ a: 'b' }))
2 changes: 2 additions & 0 deletions packages/delir/package.json
Expand Up @@ -14,6 +14,7 @@
"@types/fs-promise": "1.0.3",
"@types/keymirror": "0.1.1",
"@types/lodash": "4.14.116",
"@types/msgpack5": "3.4.1",
"@types/react": "16.4.12",
"@types/react-color": "2.13.6",
"@types/react-dom": "16.0.7",
Expand All @@ -34,6 +35,7 @@
"mkdirp-promise": "5.0.1",
"monaco-editor": "0.14.3",
"mouse-wheel": "1.2.0",
"msgpack5": "4.2.0",
"node-timecodes": "2.4.1",
"parse-color": "1.0.0",
"react": "16.4.1",
Expand Down
12 changes: 12 additions & 0 deletions packages/delir/views/AppMenu/AppMenu.i18n.ts
Expand Up @@ -37,6 +37,12 @@ export default I18n({
help: {
label: 'ヘルプ',
},
modals: {
saveAs: {
title: '新しいファイルに保存',
save: '保存',
}
},
},
en: {
appMenu: {
Expand Down Expand Up @@ -74,5 +80,11 @@ export default I18n({
help: {
label: 'Help',
},
modals: {
saveAs: {
title: 'Save as ...',
save: 'Save',
}
},
},
})
41 changes: 39 additions & 2 deletions packages/delir/views/AppMenu/AppMenu.tsx
Expand Up @@ -81,12 +81,49 @@ export default withComponentContext(connectToStores([EditorStateStore], (context
{
label: t('file.save'),
accelerator: 'CmdOrCtrl+S',
click: () => context.executeOperation(AppActions.overwriteProject, {})
click: () => {
const state = context.getStore(EditorStateStore).getState()
let path: string | null = state.projectPath

if (!path) {
path = remote.dialog.showSaveDialog({
title: t('modals.saveAs.title'),
buttonLabel: t('modals.saveAs.save'),
filters: [
{
name: 'Delir Project File',
extensions: ['delir']
}
],
})

// cancelled
if (!path) return
}

context.executeOperation(AppActions.saveProject, { path })
}
},
{
label: t('file.saveAs'),
accelerator: 'CmdOrCtrl+Shift+S',
click: () => context.executeOperation(AppActions.saveProject, {})
click: () => {
const path = remote.dialog.showSaveDialog({
title: t('modals.saveAs.title'),
buttonLabel: t('modals.saveAs.save'),
filters: [
{
name: 'Delir Project File',
extensions: ['delir']
}
],
})

// cancelled
if (!path) return

context.executeOperation(AppActions.saveProject, { path })
}
},
{type: 'separator'},
{
Expand Down
30 changes: 29 additions & 1 deletion yarn.lock
Expand Up @@ -27,6 +27,12 @@
dependencies:
any-observable "^0.3.0"

"@types/bl@*":
version "0.8.32"
resolved "https://registry.yarnpkg.com/@types/bl/-/bl-0.8.32.tgz#997d4332556c12eccae3bae93c0e6c0b53c562d4"
dependencies:
"@types/node" "*"

"@types/bson@1.0.11":
version "1.0.11"
resolved "https://registry.yarnpkg.com/@types/bson/-/bson-1.0.11.tgz#c95ad69bb0b3f5c33b4bb6cc86d86cafb273335c"
Expand Down Expand Up @@ -83,6 +89,12 @@
version "5.2.5"
resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-5.2.5.tgz#8a4accfc403c124a0bafe8a9fc61a05ec1032073"

"@types/msgpack5@3.4.1":
version "3.4.1"
resolved "https://registry.yarnpkg.com/@types/msgpack5/-/msgpack5-3.4.1.tgz#79a0bdf1a723abd8496b0dba380ee02a5e41264a"
dependencies:
"@types/bl" "*"

"@types/mz@*", "@types/mz@0.0.32":
version "0.0.32"
resolved "https://registry.yarnpkg.com/@types/mz/-/mz-0.0.32.tgz#e8248b4e41424c052edc1725dd33650c313a3659"
Expand Down Expand Up @@ -1468,6 +1480,13 @@ bindings@^1.2.1:
version "1.3.0"
resolved "https://registry.yarnpkg.com/bindings/-/bindings-1.3.0.tgz#b346f6ecf6a95f5a815c5839fc7cdb22502f1ed7"

bl@^2.0.0:
version "2.0.1"
resolved "https://registry.yarnpkg.com/bl/-/bl-2.0.1.tgz#1de8346d50c3078d088d6a60c2bbc8c516248bc5"
dependencies:
readable-stream "^2.3.5"
safe-buffer "^5.1.1"

block-stream@*:
version "0.0.9"
resolved "https://registry.yarnpkg.com/block-stream/-/block-stream-0.0.9.tgz#13ebfe778a03205cfe03751481ebb4b3300c126a"
Expand Down Expand Up @@ -5409,6 +5428,15 @@ ms@2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/ms/-/ms-2.0.0.tgz#5608aeadfc00be6c2901df5f9861788de0d597c8"

msgpack5@4.2.0:
version "4.2.0"
resolved "https://registry.yarnpkg.com/msgpack5/-/msgpack5-4.2.0.tgz#e005ec893b71e1140bb177f2d1f4b7f290169611"
dependencies:
bl "^2.0.0"
inherits "^2.0.3"
readable-stream "^2.3.6"
safe-buffer "^5.1.2"

mute-stdout@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/mute-stdout/-/mute-stdout-1.0.0.tgz#5b32ea07eb43c9ded6130434cf926f46b2a7fd4d"
Expand Down Expand Up @@ -6708,7 +6736,7 @@ readable-stream@^2.0.0, readable-stream@^2.0.1, readable-stream@^2.0.2, readable
string_decoder "~1.0.0"
util-deprecate "~1.0.1"

readable-stream@^2.0.6, readable-stream@^2.3.3, readable-stream@^2.3.5:
readable-stream@^2.0.6, readable-stream@^2.3.3, readable-stream@^2.3.5, readable-stream@^2.3.6:
version "2.3.6"
resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.6.tgz#b11c27d88b8ff1fbe070643cf94b0c79ae1b0aaf"
dependencies:
Expand Down