diff --git a/.babelrc b/.babelrc index 203e6427..f8a7a654 100644 --- a/.babelrc +++ b/.babelrc @@ -1,3 +1,3 @@ { - "presets": ["react", "es2015"] + "presets": ["react", "es2015", "stage-2"] } \ No newline at end of file diff --git a/renderer/components/App.js b/renderer/components/App.js index ef8c8293..b77cd704 100755 --- a/renderer/components/App.js +++ b/renderer/components/App.js @@ -1,19 +1,19 @@ -import React from 'react'; -import FileTree from './FileTree'; -import TextEditorPane from './TextEditorPane'; -import DeletePrompt from './DeletePrompt'; -import MockComponentTree from './MockComponentTree'; -import MockComponentInspector from './MockComponentInspector'; - -const { ipcRenderer } = require('electron'); -const { getTree } = require('../../lib/file-tree'); -const fs = require('fs'); -const path = require('path'); -const { File, Directory } = require('../../lib/item-schema'); +import React from 'react' +import FileTree from './FileTree' +import TextEditorPane from './TextEditorPane' +import DeletePrompt from './DeletePrompt' +import MockComponentTree from './MockComponentTree' +import MockComponentInspector from './MockComponentInspector' + +import { ipcRenderer } from 'electron' +import { getTree } from '../../lib/file-tree' +import fs from 'fs' +import path from 'path' +import { File, Directory } from '../../lib/item-schema' export default class App extends React.Component { constructor() { - super(); + super() this.state = { nextTabId: 0, openTabs: [], @@ -37,62 +37,47 @@ export default class App extends React.Component { fileChangeType: null, deletePromptOpen: false, newName: '' - }; - - this.fileTreeInit(); - this.clickHandler = this.clickHandler.bind(this); - this.setFileTree = this.setFileTree.bind(this); - this.dblClickHandler = this.dblClickHandler.bind(this); - this.setActiveTab = this.setActiveTab.bind(this); - this.isFileOpened = this.isFileOpened.bind(this); - this.saveTab = this.saveTab.bind(this); - this.addEditorInstance = this.addEditorInstance.bind(this); - this.closeTab = this.closeTab.bind(this); - this.openCreateMenu = this.openCreateMenu.bind(this); - this.closeOpenDialogs = this.closeOpenDialogs.bind(this); - this.createMenuHandler = this.createMenuHandler.bind(this); - this.createItem = this.createItem.bind(this); - this.findParentDir = this.findParentDir.bind(this); - this.deletePromptHandler = this.deletePromptHandler.bind(this); - this.renameHandler = this.renameHandler.bind(this); + } + + this.fileTreeInit() //reset tabs, should store state in local storage before doing this though ipcRenderer.on('openDir', (event, projPath) => { if (this.state.openedProjectPath !== projPath) { - this.setState({ openTabs: [], activeTab: null, openedProjectPath: projPath, nextTabId: 0 }); + this.setState({ openTabs: [], activeTab: null, openedProjectPath: projPath, nextTabId: 0 }) } - }); + }) ipcRenderer.on('saveFile', (event, arg) => { if (this.state.activeTab !== null) { - this.saveTab(); + this.saveTab() } - }); + }) ipcRenderer.on('delete', (event, arg) => { if (this.state.selectedItem.id) { this.setState({ deletePromptOpen: true, fileChangeType: 'delete' - }); + }) } - }); + }) ipcRenderer.on('enter', (event, arg) => { if (this.state.selectedItem.focused) { //rename property just true or false i guess this.setState({ renameFlag: true - }); + }) } - }); + }) } //registers listeners for opening projects and new projects fileTreeInit() { ipcRenderer.on('openDir', (event, dirPath) => { if (dirPath !== this.state.rootDirPath) { - this.setFileTree(dirPath); + this.setFileTree(dirPath) } - }); + }) ipcRenderer.on('newProject', (event, arg) => { - if (this.state.watch) this.state.watch.close(); + if (this.state.watch) this.state.watch.close() this.setState({ fileTree: null, watch: null, @@ -102,66 +87,66 @@ export default class App extends React.Component { path: null, type: null } - }); - }); + }) + }) } //sends old path and new name to main process to rename, closes rename form and sets filechangetype and newName for fswatch - renameHandler(event) { + renameHandler = (event) => { if (event.key === 'Enter' && event.target.value) { - ipcRenderer.send('rename', this.state.selectedItem.path, event.target.value); + ipcRenderer.send('rename', this.state.selectedItem.path, event.target.value) this.setState({ renameFlag: false, fileChangeType: 'rename', newName: event.target.value - }); + }) } else if (event.key === 'Enter' && !event.target.value) { this.setState({ renameFlag: false - }); + }) } } //handles click event from delete prompt - deletePromptHandler(answer) { + deletePromptHandler = (answer) => { if (answer) { - ipcRenderer.send('delete', this.state.selectedItem.path); + ipcRenderer.send('delete', this.state.selectedItem.path) } else { this.setState({ fileChangeType: null - }); + }) } this.setState({ deletePromptOpen: false - }); + }) } //handles click events for directories and files in file tree render - clickHandler(id, filePath, type, event) { - const temp = this.state.fileTree; + clickHandler = (id, filePath, type, event) => { + const temp = this.state.fileTree document.body.onkeydown = event => { if (event.key === 'Enter') { this.setState({ renameFlag: true - }); - document.body.onkeydown = () => {}; + }) + document.body.onkeydown = () => {} } - }; + } if (type === 'directory') { function toggleClicked(dir) { if (dir.path === filePath) { - dir.opened = !dir.opened; - return; + dir.opened = !dir.opened + return } else { for (var i = 0; i < dir.subdirectories.length; i++) { - toggleClicked(dir.subdirectories[i]); + toggleClicked(dir.subdirectories[i]) } } } - toggleClicked(temp); + toggleClicked(temp) } //so opened menu doesn't immediately close - if (this.state.openMenuId === null) event.stopPropagation(); + if (this.state.openMenuId === null) event.stopPropagation() this.setState({ selectedItem: { @@ -176,7 +161,7 @@ export default class App extends React.Component { id: null, type: null } - }); + }) } //calls file tree module and sets state with file tree object representation in callback @@ -184,52 +169,52 @@ export default class App extends React.Component { getTree(dirPath, fileTree => { //if watcher instance already exists close it as it's for the previously opened project if (this.state.watch) { - this.state.watch.close(); + this.state.watch.close() } let watch = fs.watch(dirPath, { recursive: true }, (eventType, fileName) => { if (eventType === 'rename') { - const fileTree = this.state.fileTree; - const absPath = path.join(this.state.rootDirPath, fileName); - const parentDir = this.findParentDir(path.dirname(absPath), fileTree); - const name = path.basename(absPath); - const openTabs = this.state.openTabs; + const fileTree = this.state.fileTree + const absPath = path.join(this.state.rootDirPath, fileName) + const parentDir = this.findParentDir(path.dirname(absPath), fileTree) + const name = path.basename(absPath) + const openTabs = this.state.openTabs //delete handler if (this.state.fileChangeType === 'delete') { - let index; + let index if (this.state.selectedItem.type === 'directory') { - index = this.findItemIndex(parentDir.subdirectories, name); - parentDir.subdirectories.splice(index, 1); + index = this.findItemIndex(parentDir.subdirectories, name) + parentDir.subdirectories.splice(index, 1) } else { - index = this.findItemIndex(parentDir.files, name); - parentDir.files.splice(index, 1); + index = this.findItemIndex(parentDir.files, name) + parentDir.files.splice(index, 1) } for (var i = 0; i < this.state.openTabs.length; i++) { if (openTabs[i].name === name) { - openTabs.splice(i, 1); - break; + openTabs.splice(i, 1) + break } } } else if (this.state.fileChangeType === 'new') { //new handler if (this.state.createMenuInfo.type === 'directory') { - parentDir.subdirectories.push(new Directory(absPath, name)); + parentDir.subdirectories.push(new Directory(absPath, name)) } else { - parentDir.files.push(new File(absPath, name)); + parentDir.files.push(new File(absPath, name)) } } else if (this.state.fileChangeType === 'rename' && this.state.newName) { //rename handler //fileName has new name, selectedItem has old name and path - let index; + let index if (this.state.selectedItem.type === 'directory') { - index = this.findItemIndex(parentDir.subdirectories, name); - parentDir.subdirectories[index].name = this.state.newName; - parentDir.subdirectories[index].path = path.join(path.dirname(absPath), this.state.newName); + index = this.findItemIndex(parentDir.subdirectories, name) + parentDir.subdirectories[index].name = this.state.newName + parentDir.subdirectories[index].path = path.join(path.dirname(absPath), this.state.newName) } else { - index = this.findItemIndex(parentDir.files, name); - parentDir.files[index].name = this.state.newName; - parentDir.files[index].path = path.join(path.dirname(absPath), this.state.newName); + index = this.findItemIndex(parentDir.files, name) + parentDir.files[index].name = this.state.newName + parentDir.files[index].path = path.join(path.dirname(absPath), this.state.newName) } //renames path of selected renamed file so it has the right info @@ -239,13 +224,13 @@ export default class App extends React.Component { type: this.state.selectedItem.type, path: path.join(path.dirname(absPath), this.state.newName) } - }); + }) //rename the opened tab of the renamed file if it's there for (var i = 0; i < this.state.openTabs.length; i++) { if (openTabs[i].name === name) { - openTabs[i].name = this.state.newName; - break; + openTabs[i].name = this.state.newName + break } } } @@ -259,43 +244,43 @@ export default class App extends React.Component { type: null }, openTabs - }); + }) } - }); + }) this.setState({ fileTree, rootDirPath: dirPath, watch - }); - }); + }) + }) } //returns index of file/dir in files or subdirectories array - findItemIndex(filesOrDirs, name) { + findItemIndex = (filesOrDirs, name) => { for (var i = 0; i < filesOrDirs.length; i++) { if (filesOrDirs[i].name === name) { - return i; + return i } } - return -1; + return -1 } //returns parent directory object of file/directory in question - findParentDir(dirPath, directory = this.state.fileTree) { - if (directory.path === dirPath) return directory; + findParentDir = (dirPath, directory = this.state.fileTree) => { + if (directory.path === dirPath) return directory else { - let dirNode; + let dirNode for (var i in directory.subdirectories) { - dirNode = this.findParentDir(dirPath, directory.subdirectories[i]); - if (dirNode) return dirNode; + dirNode = this.findParentDir(dirPath, directory.subdirectories[i]) + if (dirNode) return dirNode } } } //click handler for plus button on directories, 'opens' new file/dir menu by setting openMenuID state - openCreateMenu(id, itemPath, type, event) { - event.stopPropagation(); + openCreateMenu = (id, itemPath, type, event)=> { + event.stopPropagation() this.setState({ openMenuId: id, selectedItem: { @@ -303,15 +288,15 @@ export default class App extends React.Component { path: itemPath, type } - }); + }) } //handler for create menu - createMenuHandler(id, type, event) { + createMenuHandler = (id, type, event) => { //unhook keypress listeners - document.body.onkeydown = () => {}; + document.body.onkeydown = () => {} - event.stopPropagation(); + event.stopPropagation() this.setState({ createMenuInfo: { @@ -319,12 +304,12 @@ export default class App extends React.Component { type }, openMenuId: null - }); + }) } //sends input name to main, where the file/directory is actually created. //creation of new file/directory will trigger watch handler - createItem(event) { + createItem = (event) => { if (event.key === 'Enter') { //send path and file type to main process to actually create file/dir only if there is value if (event.target.value) @@ -333,105 +318,105 @@ export default class App extends React.Component { this.state.selectedItem.path, event.target.value, this.state.createMenuInfo.type - ); + ) //set type of file change so watch handler knows which type this.setState({ fileChangeType: 'new' - }); + }) } } //tab close handler - closeTab(id, event) { - const temp = this.state.openTabs; + closeTab = (id, event) => { + const temp = this.state.openTabs for (var i = 0; i < temp.length; i++) { if (temp[i].id === id) { - temp.splice(i, 1); - break; + temp.splice(i, 1) + break } } - event.stopPropagation(); - this.setState({ openTabs: temp, activeTab: temp[0] ? temp[0].id : null }); + event.stopPropagation() + this.setState({ openTabs: temp, activeTab: temp[0] ? temp[0].id : null }) } - addEditorInstance(editor, id) { - const temp = this.state.openTabs; - let i = 0; + addEditorInstance = (editor, id) => { + const temp = this.state.openTabs + let i = 0 while (this.state.openTabs[i].id !== id) { - i++; + i++ } - temp[i].editor = editor; + temp[i].editor = editor this.setState({ openTabs: temp - }); + }) } //save handler - saveTab() { + saveTab = () => { for (var i = 0; i < this.state.openTabs.length; i++) { if (this.state.openTabs[i].id === this.state.activeTab) { - fs.writeFileSync(this.state.openTabs[i].path, this.state.openTabs[i].editor.getValue(), { encoding: 'utf8' }); - break; + fs.writeFileSync(this.state.openTabs[i].path, this.state.openTabs[i].editor.getValue(), { encoding: 'utf8' }) + break } } } //sets active tab - setActiveTab(id) { + setActiveTab = (id) => { this.setState({ activeTab: id }, () => { - let editorNode = document.getElementById(id); + let editorNode = document.getElementById(id) //for text editor window resizing - let parent = editorNode.parentElement; - editorNode.style.width = parent.clientWidth; - editorNode.firstElementChild.style.width = parent.clientWidth; - editorNode.firstElementChild.firstElementChild.style.width = parent.clientWidth; - editorNode.getElementsByClassName('monaco-scrollable-element')[0].style.width = parent.clientWidth - 46; - }); + let parent = editorNode.parentElement + editorNode.style.width = parent.clientWidth + editorNode.firstElementChild.style.width = parent.clientWidth + editorNode.firstElementChild.firstElementChild.style.width = parent.clientWidth + editorNode.getElementsByClassName('monaco-scrollable-element')[0].style.width = parent.clientWidth - 46 + }) } //double click handler for files - dblClickHandler(file) { - let id = this.isFileOpened(file); + dblClickHandler = (file) => { + let id = this.isFileOpened(file) if (id === -1) { - const openTabs = this.state.openTabs; - id = this.state.nextTabId; + const openTabs = this.state.openTabs + id = this.state.nextTabId openTabs.push({ path: file.path, id, name: file.name, modified: false, editor: null - }); - this.setState({ openTabs, activeTab: id, nextTabId: id + 1 }); + }) + this.setState({ openTabs, activeTab: id, nextTabId: id + 1 }) // store.dispatch() } else { - this.setState({ activeTab: id }); + this.setState({ activeTab: id }) } } //checks if project is already open - isFileOpened(file) { + isFileOpened = (file) => { for (var i = 0; i < this.state.openTabs.length; i++) { if (this.state.openTabs[i].path === file.path) { - return this.state.openTabs[i].id; + return this.state.openTabs[i].id } } - return -1; + return -1 } //simulator click handler openSim() { - ipcRenderer.send('openSimulator'); + ipcRenderer.send('openSimulator') } //closes any open dialogs, handles clicks on anywhere besides the active open menu/form - closeOpenDialogs() { - const selectedItem = this.state.selectedItem; - selectedItem.focused = false; + closeOpenDialogs = () => { + const selectedItem = this.state.selectedItem + selectedItem.focused = false - document.body.onkeydown = () => {}; + document.body.onkeydown = () => {} this.setState({ openMenuId: null, createMenuInfo: { @@ -440,7 +425,7 @@ export default class App extends React.Component { }, selectedItem, renameFlag: false - }); + }) } render() { @@ -501,6 +486,6 @@ export default class App extends React.Component { - ); + ) } }