diff options
author | lonkaars <loek@pipeframe.xyz> | 2021-07-24 19:01:14 +0200 |
---|---|---|
committer | lonkaars <loek@pipeframe.xyz> | 2021-07-24 19:01:14 +0200 |
commit | 4b9263e00382cad8d067187a093f19b4276f0f9f (patch) | |
tree | fba73a3332ba94ac83c205164b4051e869c8dccf | |
parent | def71ea56c99873af04dadc1c0e801d42c406826 (diff) |
settings saved + project file version bump
-rw-r--r-- | package.json | 4 | ||||
-rw-r--r-- | pages/editor.tsx | 67 | ||||
-rw-r--r-- | pages/present.tsx | 17 | ||||
-rw-r--r-- | project.ts | 51 | ||||
-rw-r--r-- | timeline.schema.json | 210 | ||||
-rw-r--r-- | timeline.ts | 5 |
6 files changed, 91 insertions, 263 deletions
diff --git a/package.json b/package.json index 9637f4d..b5f16d5 100644 --- a/package.json +++ b/package.json @@ -10,8 +10,7 @@ "scripts": { "dev": "next dev", "build": "next build", - "start": "next start", - "schema": "npx ts-json-schema-generator --path timeline.ts --type timeline > timeline.schema.json" + "start": "next start" }, "dependencies": { "@hookstate/core": "^3.0.8", @@ -36,7 +35,6 @@ "react-use-gesture": "^9.1.3", "semver": "^7.3.5", "timecode-boss": "^4.2.3", - "ts-json-schema-generator": "^0.93.0", "use-mousetrap": "^1.0.4", "uuid": "^8.3.2" }, diff --git a/pages/editor.tsx b/pages/editor.tsx index b90ba7f..f9c0e80 100644 --- a/pages/editor.tsx +++ b/pages/editor.tsx @@ -18,13 +18,12 @@ import KeybindSelector from '../components/keybindselector'; import PlaySkipIconAni from '../components/play-skip'; import Selection from '../components/selection'; import TimecodeInput from '../components/timeinput'; -import Project, { arrayBufferToBase64, VideoSources, VideoSourceType } from '../project'; +import Project, { arrayBufferToBase64, PresentationSettings, VideoSources, VideoSourceType } from '../project'; import timeline, { anySlide, clickThroughBehaviours, loopBeginSlide, loopSlide, - presentationSettings, slide, slideTypes, toolToSlide, @@ -155,9 +154,6 @@ var project = createState<project>({ timeline: { name: '', slides: [], - settings: { - controlType: 'FullScreen', - }, framerate: 0, framecount: 0, }, @@ -967,15 +963,10 @@ function TimelineEditor() { } function DefaultSettings() { - var [nextSlideKeybinds, setNextSlideKeybinds] = useState(['Space', 'n', 'Enter']); - var [previousSlideKeybinds, setPreviousSlideKeybinds] = useState(['Backspace', 'p']); - var [showMenuKeybinds, setShowMenuKeybinds] = useState(['Escape', 'm']); - - var [videoSourceType, setVideoSourceType] = useState(VideoSources[0].type); - - var proj = useHookstate(project).timeline; - var ready = useHookstate(global).ready; + var [dummy, setDummy] = useState(false); + var rerender = () => setDummy(!dummy); + return <> <h2 className='title posabs h0 t0'>Presentation settings</h2> <div className='scroll posabs h0 b0'> @@ -983,14 +974,23 @@ function DefaultSettings() { <span className='title'>Controls</span> <div className='sidebyside'> <span className='body'>Allow remote control during presentation</span> - <Switch /> + <Switch + value={projectFile.settings.remotes.AllowRemotes} + onChange={() => { + projectFile.settings.remotes.AllowRemotes = !projectFile.settings.remotes.AllowRemotes; + rerender(); + }} + /> </div> <FormControl variant='filled'> <InputLabel>On-screen controls</InputLabel> <Select - value={proj.settings.controlType.get()} - onChange={e => - proj.settings.controlType.set(e.target.value as presentationSettings['controlType'])} + value={projectFile.settings.controls.ControlType} + onChange={e => { + projectFile.settings.controls.ControlType = e.target + .value as PresentationSettings['controls']['ControlType']; + rerender(); + }} IconComponent={ArrowDropDownRoundedIcon} > <MenuItem value='FullScreen'> @@ -1038,13 +1038,30 @@ function DefaultSettings() { </div> <div className={'section ' + (ready.timeline.value ? '' : 'disabled')}> <span className='title'>Keybindings</span> - <KeybindSelector label='Next slide' value={nextSlideKeybinds} onChange={setNextSlideKeybinds} /> + <KeybindSelector + label='Next slide' + value={projectFile.settings.keybindings.NextSlide} + onChange={e => { + projectFile.settings.keybindings.NextSlide = e; + rerender(); + }} + /> <KeybindSelector label='Previous slide' - value={previousSlideKeybinds} - onChange={setPreviousSlideKeybinds} + value={projectFile.settings.keybindings.PreviousSlide} + onChange={e => { + projectFile.settings.keybindings.PreviousSlide = e; + rerender(); + }} + /> + <KeybindSelector + label='Show menu' + value={projectFile.settings.keybindings.ShowMenu} + onChange={e => { + projectFile.settings.keybindings.ShowMenu = e; + rerender(); + }} /> - <KeybindSelector label='Show menu' value={showMenuKeybinds} onChange={setShowMenuKeybinds} /> </div> <div className={'section ' + (ready.timeline.value ? '' : 'disabled')}> <span className='title'>Source</span> @@ -1071,7 +1088,13 @@ function DefaultSettings() { <span className='title'>Remotes</span> <div className='sidebyside'> <span className='body'>Allow anonymous remotes</span> - <Switch /> + <Switch + value={projectFile.settings.remotes.AllowQRRemotes} + onChange={() => { + projectFile.settings.remotes.AllowQRRemotes = !projectFile.settings.remotes.AllowQRRemotes; + rerender(); + }} + /> </div> </div> <div className='section'> diff --git a/pages/present.tsx b/pages/present.tsx index fe46a5f..a99d239 100644 --- a/pages/present.tsx +++ b/pages/present.tsx @@ -152,20 +152,7 @@ export class TimedVideoPlayer { } loadSlides(jsonString: string) { - try { - var timeline = JSON.parse(jsonString); - } catch (e) { - console.log('invalid json object!' + e); - return; - } - var ajv = new Ajv({ allErrors: true }); - var validate = ajv.compile(timelineSchema); - if (!validate(timeline)) { - console.log('schema not passed!'); - return; - } - - this.timeline = timeline as timeline; + this.timeline = JSON.parse(jsonString) as timeline; this.timeline.slides[-1] = { id: '00000000-0000-0000-0000-000000000000', @@ -214,7 +201,7 @@ export class TimedVideoPlayer { export default function Present() { var [dummy, setDummy] = useState(false); var rerender = () => setDummy(!dummy); - var [player, setPlayer] = useState(new TimedVideoPlayer()); + var [player, _setPlayer] = useState(new TimedVideoPlayer()); useEffect(() => { setInterval(() => { @@ -74,14 +74,46 @@ export const VideoSources = [ export type VideoSourceClass = InstanceType<typeof VideoSources[number]['class']>; export type VideoSourceType = typeof VideoSources[number]['type']; +export class PresentationSettings { + keybindings: { + NextSlide: string[]; + PreviousSlide: string[]; + ShowMenu: string[]; + }; + controls: { + ControlType: 'FullScreen' | 'MenuBar'; + }; + remotes: { + AllowRemotes: boolean; + AllowQRRemotes: boolean; + }; + + constructor() { + this.keybindings = { + NextSlide: ['Space', 'n', 'Enter'], + PreviousSlide: ['Backspace', 'p'], + ShowMenu: ['Escape', 'm'], + }; + this.controls = { + ControlType: 'FullScreen', + }; + this.remotes = { + AllowRemotes: false, + AllowQRRemotes: false, + }; + } +} + export default class { - version: string; + version: string = '0.2.0'; + fileVersion: string; zip: JSZip; project: TimedVideoPlayer['timeline']; video: VideoSourceClass; + settings: PresentationSettings; constructor() { - this.version = '0.1.1'; + this.settings = new PresentationSettings(); this.zip = new JSZip(); } @@ -101,29 +133,28 @@ export default class { } saveProject() { + this.zip = new JSZip(); + var meta = this.zip.folder('meta'); meta.file('version', this.version); meta.file('name', this.project.name); - var settings = this.zip.folder('settings'); - settings.file('controlType', this.project.settings.controlType); - var source = this.zip.folder('source'); this.video.save(source); source.file('mimetype', this.video.mimetype); source.file('config', JSON.stringify(this.video.config, null, 4)); this.zip.file('slides', JSON.stringify(this.project.slides, null, 4)); + this.zip.file('settings', JSON.stringify(this.settings, null, 4)); } async openProject(data: ArrayBuffer) { this.zip = new JSZip(); await this.zip.loadAsync(data); - this.version = await this.zip.file('meta/version').async('string'); + this.fileVersion = await this.zip.file('meta/version').async('string'); this.project = { name: await this.zip.file('meta/name').async('string'), - settings: { controlType: await this.zip.file('settings/controlType').async('string') }, slides: JSON.parse(await this.zip.file('slides').async('string')), framerate: Number(await this.zip.file('source/framerate').async('string')), framecount: Number(await this.zip.file('source/framecount').async('string')), @@ -135,8 +166,12 @@ export default class { this.video = new videoSourceType.class(await this.zip.file('source/video').async('arraybuffer')); this.video.mimetype = await this.zip.file('source/mimetype').async('string'); - if (semver.lt('0.1.1', this.version)) { + if (semver.lt('0.1.1', this.fileVersion)) { this.video.config = JSON.parse(await this.zip.file('source/config').async('string')); } + + if (semver.lt('0.2.0', this.fileVersion)) { + this.settings = JSON.parse(await this.zip.file('settings').async('string')); + } } } diff --git a/timeline.schema.json b/timeline.schema.json deleted file mode 100644 index 3076125..0000000 --- a/timeline.schema.json +++ /dev/null @@ -1,210 +0,0 @@ -{ - "$ref": "#/definitions/timeline", - "$schema": "http://json-schema.org/draft-07/schema#", - "definitions": { - "anySlide": { - "anyOf": [ - { - "$ref": "#/definitions/slide" - }, - { - "$ref": "#/definitions/delaySlide" - }, - { - "$ref": "#/definitions/speedChangeSlide" - }, - { - "$ref": "#/definitions/loopSlide" - } - ] - }, - "delaySlide": { - "additionalProperties": false, - "properties": { - "clickThroughBehaviour": { - "enum": [ - "ImmediatelySkip", - "PlayOut" - ], - "type": "string" - }, - "delay": { - "type": "number" - }, - "frame": { - "type": "number" - }, - "id": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/slideTypes" - } - }, - "required": [ - "clickThroughBehaviour", - "delay", - "frame", - "id", - "type" - ], - "type": "object" - }, - "loopSlide": { - "additionalProperties": false, - "properties": { - "beginFrame": { - "type": "number" - }, - "clickThroughBehaviour": { - "enum": [ - "ImmediatelySkip", - "PlayOut" - ], - "type": "string" - }, - "frame": { - "type": "number" - }, - "id": { - "type": "string" - }, - "playbackType": { - "enum": [ - "PingPong", - "Normal" - ], - "type": "string" - }, - "type": { - "$ref": "#/definitions/slideTypes" - } - }, - "required": [ - "beginFrame", - "clickThroughBehaviour", - "frame", - "id", - "playbackType", - "type" - ], - "type": "object" - }, - "presentationSettings": { - "additionalProperties": false, - "properties": { - "controlType": { - "enum": [ - "FullScreen", - "MenuBar" - ], - "type": "string" - } - }, - "required": [ - "controlType" - ], - "type": "object" - }, - "slide": { - "additionalProperties": false, - "properties": { - "clickThroughBehaviour": { - "enum": [ - "ImmediatelySkip", - "PlayOut" - ], - "type": "string" - }, - "frame": { - "type": "number" - }, - "id": { - "type": "string" - }, - "type": { - "$ref": "#/definitions/slideTypes" - } - }, - "required": [ - "clickThroughBehaviour", - "type", - "id", - "frame" - ], - "type": "object" - }, - "slideTypes": { - "enum": [ - "default", - "delay", - "speedChange", - "loop" - ], - "type": "string" - }, - "speedChangeSlide": { - "additionalProperties": false, - "properties": { - "clickThroughBehaviour": { - "enum": [ - "ImmediatelySkip", - "PlayOut" - ], - "type": "string" - }, - "frame": { - "type": "number" - }, - "id": { - "type": "string" - }, - "newFramerate": { - "type": "number" - }, - "type": { - "$ref": "#/definitions/slideTypes" - } - }, - "required": [ - "clickThroughBehaviour", - "frame", - "id", - "newFramerate", - "type" - ], - "type": "object" - }, - "timeline": { - "additionalProperties": false, - "properties": { - "framecount": { - "type": "number" - }, - "framerate": { - "type": "number" - }, - "name": { - "type": "string" - }, - "settings": { - "$ref": "#/definitions/presentationSettings" - }, - "slides": { - "items": { - "$ref": "#/definitions/anySlide" - }, - "type": "array" - } - }, - "required": [ - "slides", - "framecount", - "framerate", - "name", - "settings" - ], - "type": "object" - } - } -} diff --git a/timeline.ts b/timeline.ts index d0780ff..052ae8d 100644 --- a/timeline.ts +++ b/timeline.ts @@ -50,14 +50,9 @@ export var toolToSlide = { loop: loopSlide, }; -export interface presentationSettings { - controlType: 'FullScreen' | 'MenuBar'; -} - export default interface timeline { slides: Array<anySlide>; framecount: number; framerate: number; name: string; - settings: presentationSettings; } |