UNPKG

whiteboard-app

Version:

Whiteboard - a slide-based activity presentation system

288 lines (258 loc) 8.91 kB
const pathlib = require('path'); const fs = require('fs'); const schemaconf = require('schemaconf'); const { autogenerateDeckFromDir } = require('./fsimport.js'); const { getStore } = require('./prefs.js'); const packageJson = require('../../package.json'); const WB_FORMAT = '1'; const MAX_RECENT = 10; function updateRecentList(filepath) { const store = getStore(); let recent = store.get('recent'); const index = recent.indexOf(filepath); if (index !== -1) { recent.splice(index, 1); } recent.unshift({ path: filepath }); recent = recent.slice(0, MAX_RECENT); store.set('recent', recent); } function saveToFile(filepath, data, callback) { const string = schemaconf.format.stringify(data); fs.writeFile(filepath, string, (err) => { if (err) { console.error('cannot write to path: ', filepath); throw err; } updateRecentList(filepath); callback(); }); } module.exports = { WB_FORMAT, getRecentListData() { // TODO: clean this up, move it to Start, make it fault tolerant, and // async, and have it do it on ready const store = getStore(); const list = store.get('recent'); return list.map(({ path }) => { // otherwise read data from file try { const contents = fs.readFileSync(path, 'utf-8'); const data = schemaconf.format.parse(contents); return { path, data }; } catch (e) { return { path }; } }); }, getRecentList() { const store = getStore(); const list = store.get('recent'); // Process all entries removing the .whiteboard extension return list.map(({ path }) => ({ path, name: pathlib.basename(path).slice(0, -11), })); }, openHtml(manager, defaultPath, callback) { const { dialog } = manager.electron; dialog.showOpenDialog({ defaultPath, properties: ['openFile'], filters: [ { name: 'HTML', extensions: ['html', 'htm'] }, { name: 'All Files', extensions: ['*'] }, ], }, (paths) => { if (!paths) { return; // canceled } callback(paths[0]); }); }, openImage(manager, callback) { const { dialog } = manager.electron; dialog.showOpenDialog({ // defaultPath, properties: ['openFile'], filters: [ { name: 'Image', extensions: ['png', 'jpg', 'jpeg', 'gif', 'webp'] }, { name: 'All Files', extensions: ['*'] }, ], }, (paths) => { if (!paths) { return; // canceled } callback(paths[0]); }); }, openVideo(manager, callback) { const { dialog } = manager.electron; dialog.showOpenDialog({ // defaultPath, properties: ['openFile'], filters: [ { name: 'Video', extensions: ['mp4', 'webm', 'ogg', 'avi', 'mkv', 'm4v'] }, { name: 'All Files', extensions: ['*'] }, ], }, (paths) => { if (!paths) { return; // canceled } callback(paths[0]); }); }, loadDeck(manager, defaultPath, callback) { const { dialog } = manager.electron; dialog.showOpenDialog({ defaultPath, properties: ['openFile'], filters: [ { name: 'Whiteboard', extensions: ['whiteboard'] }, ], }, (paths) => { if (!paths) { return; // canceled } if (defaultPath === paths[0]) { return; // don't do anything if we are re-opening same file } updateRecentList(paths[0]); // Otherwise, create a new window opening this thing manager.createWindow(paths[0], callback); }); }, importDirectory(manager, defaultPath, callback) { const { dialog } = manager.electron; dialog.showOpenDialog({ defaultPath, properties: ['openDirectory'], }, (paths) => { if (!paths) { return; // canceled } // Otherwise, create a new window opening this thing const slides = autogenerateDeckFromDir(paths[0]); if (slides && slides.length > 0) { const filepath = pathlib.resolve(paths[0], 'deck.whiteboard'); const data = { slide: slides }; saveToFile(filepath, data, () => { // console.log('SAVED TO ', filepath); manager.createWindow(filepath, callback); updateRecentList(filepath); }); } }); }, newDeck(manager, defaultPath, callback) { const { dialog } = manager.electron; dialog.showSaveDialog({ defaultPath, filters: [ { name: 'Whiteboard', extensions: ['whiteboard'] }, ], }, (filepath) => { if (!filepath) { return; // canceled } // Otherwise, create a new window opening this thing const data = { format: [ { version: WB_FORMAT }, ], slide: [ { title: 'New Whiteboard Deck' }, ], }; saveToFile(filepath, data, () => { // console.log('SAVED TO ', filepath); manager.createWindow(filepath, callback); updateRecentList(filepath); }); }); }, setupShowConfirmQuit(deck) { const { dialog } = deck.manager.electron; const { browserWindow } = deck.windowInfo; browserWindow.on('close', function onClose(ev) { // Deck is readonly, don't prompt if (deck.readonly) { return; } // No unsaved changes, don't prompt if (deck.isSavedToDisk()) { return; } // TODO: Uncomment and test this refs #56 // if (deck.isAutasaveOn()) { // deck.save(); // return; // } // Show prompt about unsaved changes const choice = dialog.showMessageBox(this, { type: 'question', buttons: ['Quit', 'Save & Quit', 'Cancel'], title: 'Unsaved Changes', message: 'You have unsaved changes. ' + 'Are you sure you want to quit?', }); if (choice === 0) { // Quit was selected return; } ev.preventDefault(); if (choice === 1) { // Trigger save, followed by force window close (destroy) deck.save(() => { setTimeout(() => { browserWindow.destroy(); }, 100); }); } }); }, showAboutWindow(manager, windowInfo) { // TODO integrate full one into elmoed, this one is glitchy as hell const { dialog } = manager.electron; const title = 'About Whiteboard'; const message = ` Whiteboard v${packageJson.version} `.replace(/\s+/g, ' ').trim(); const detail = ` Whiteboard is free software, licensed under the ${packageJson.license} license. Built with Electron v${packageJson.devDependencies.electron}. `.replace(/\s+/g, ' ').trim(); const { browserWindow } = windowInfo; setTimeout(() => { dialog.showMessageBox(browserWindow, { title, detail, message, type: 'info', buttons: ['Ok'], }); }, 10); }, showErrorMessage(editor, message) { const { manager, windowInfo } = editor; const { dialog } = manager.electron; const title = 'Whiteboard Error'; const detail = ` If this problem persists, check for a newer version, or check http://whiteboard.michaelb.org/ and report a bug if one has not already been reported. `.replace(/\s+/g, ' ').trim(); const { browserWindow } = windowInfo; setTimeout(() => { dialog.showMessageBox(browserWindow, { title, detail, message, type: 'info', buttons: ['Ok'], }); }, 10); }, };