UNPKG

alm

Version:

The best IDE for TypeScript

1,028 lines 51.2 kB
"use strict"; var __extends = (this && this.__extends) || (function () { var extendStatics = Object.setPrototypeOf || ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; }; return function (d, b) { extendStatics(d, b); function __() { this.constructor = d; } d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); }; })(); var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); var socketClient_1 = require("../socket/socketClient"); var types = require("../common/types"); var React = require("react"); var csx = require("./base/csx"); var ReactDOM = require("react-dom"); var ui_1 = require("./ui"); var ui = require("./ui"); var utils = require("../common/utils"); var styles = require("./styles/styles"); var state = require("./state/state"); var react_redux_1 = require("react-redux"); var icon_1 = require("./components/icon"); var commands = require("./commands/commands"); var DraggableCore = ui.DraggableCore; var utils_1 = require("../common/utils"); var robocop_1 = require("./components/robocop"); var inputDialog_1 = require("./dialogs/inputDialog"); var Mousetrap = require("mousetrap"); var clipboard = require("./components/clipboard"); var appTabsContainer_1 = require("./tabs/v2/appTabsContainer"); var settings = require("./state/settings"); var typestyle = require("typestyle"); var utils_2 = require("../common/utils"); var dirSelected = { isDir: true }; var fileSelected = { isDir: false }; var resizerWidth = 5; var resizerStyle = { background: 'radial-gradient(#444,transparent)', width: resizerWidth + 'px', cursor: 'ew-resize', color: '#666', }; var treeListStyle = { color: '#eee', fontSize: '.7rem', padding: '3px', }; var treeScrollClassName = typestyle.style({ border: '1px solid grey', $nest: { '&:focus': { outline: 'none', border: '1px solid ' + styles.highlightColor } } }); var treeItemClassName = typestyle.style({ whiteSpace: 'nowrap', cursor: 'pointer', padding: '3px', userSelect: 'none', fontSize: '.9em', opacity: .8, $nest: { '&:focus': { outline: 'none', } } }); var treeItemSelectedStyle = { backgroundColor: styles.selectedBackgroundColor, }; var treeItemInProjectStyle = { color: 'rgb(0, 255, 183)', opacity: 1, }; var treeItemIsGeneratedStyle = { fontSize: '.6em' }; var currentSelectedItemCopyStyle = { overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'pre', cursor: 'pointer', marginLeft: '2px', fontSize: '.6rem', fontWeight: 'bold', color: '#CCC', textShadow: '0 0 3px rgba(255, 255, 255, 0.5)', }; var helpRowStyle = { margin: '5px', lineHeight: '18px' }; var FileTree = /** @class */ (function (_super) { __extends(FileTree, _super); function FileTree(props) { var _this = _super.call(this, props) || this; /** can't be pure right now because of how we've written `selectedState` */ // shouldComponentUpdate = pure.shouldComponentUpdate; /** makes it easier to lookup directories */ _this.dirLookup = {}; _this.loading = true; // guilty till proven innocent _this.refNames = { __treeroot: '__treeroot', __treeViewScroll: '__treeViewScroll', }; _this.handleDrag = function (evt, ui) { _this.setState({ width: ui.deltaX + ui.lastX + resizerWidth }); }; _this.handleDragStop = function () { var width = _this.state.width; settings.fileTreeWidth.set(width); }; _this.setupTree = utils_2.throttle(function (props) { var filePaths = props.filePaths.filter(function (fp) { return fp.type == types.FilePathType.File; }).map(function (fp) { return fp.filePath; }); // initial boot up if (!filePaths.length) { return; } _this.loading = false; var rootDirPath = props.rootDir; var rootDir = { name: utils.getFileName(rootDirPath), filePath: rootDirPath, subDirs: [], files: [] }; // Always expand root _this.state.expansionState[rootDirPath] = true; _this.dirLookup = {}; _this.dirLookup[rootDirPath] = rootDir; // if not found creates a new dir and set its parent // (recursively e.g. last was /foo and new is /foo/bar/baz/quz) var createDirAndMakeSureAllParentExits = function (dir) { var dirTree = { name: utils_1.getFileName(dir), filePath: dir, subDirs: [], files: [] }; _this.dirLookup[dir] = dirTree; var parentDir = utils_1.getDirectory(dir); var parentDirTree = _this.dirLookup[parentDir]; if (!parentDirTree) { parentDirTree = createDirAndMakeSureAllParentExits(parentDir); } parentDirTree.subDirs.push(dirTree); return dirTree; }; for (var _i = 0, filePaths_1 = filePaths; _i < filePaths_1.length; _i++) { var filePath = filePaths_1[_i]; var dir = utils_1.getDirectory(filePath); var fileName = utils_1.getFileName(filePath); var subItem = { name: fileName, filePath: filePath, }; // lookup existing dir var treeDir = _this.dirLookup[dir]; if (!treeDir) { treeDir = createDirAndMakeSureAllParentExits(dir); } treeDir.files.push(subItem); } _this.setState({ treeRoot: rootDir, expansionState: _this.state.expansionState }); /** Also add the folders that may have no files */ var dirs = props.filePaths.filter(function (fp) { return fp.type == types.FilePathType.Dir; }).map(function (fp) { return fp.filePath; }); dirs.forEach(function (dirPath) { var treeDir = _this.dirLookup[dirPath]; if (!treeDir) { createDirAndMakeSureAllParentExits(dirPath); } }); /** * keep the selected file paths in sync with all the items that are available */ // A map for easier lookup var filePathMap = utils.createMap(filePaths); var oldSelectedPaths = Object.keys(_this.state.selectedPaths); var newSelectedPaths = {}; oldSelectedPaths.forEach(function (path) { var isDir = _this.state.selectedPaths[path].isDir; if (!filePathMap[path]) { return; } newSelectedPaths[path] = { isDir: isDir }; }); // If there is no selected path select the root if (Object.keys(newSelectedPaths).length === 0) { newSelectedPaths[rootDirPath] = { isDir: true }; } _this.setState({ selectedPaths: newSelectedPaths }); /** * Loading had focus. Transfer focus to root */ if (document.activeElement === _this.refs['loading']) { setTimeout(function () { var selectedPaths = (_a = {}, _a[_this.state.treeRoot.filePath] = dirSelected, _a); _this.setState({ selectedPaths: selectedPaths }); _this.focusOnPath(_this.state.treeRoot.filePath); var _a; }, 500); } }, 1000); _this.handleToggleDir = function (evt, item) { evt.stopPropagation(); var dirPath = item.filePath; var selectedPaths = (_a = {}, _a[dirPath] = dirSelected, _a); _this.state.expansionState[dirPath] = !_this.state.expansionState[dirPath]; _this.setState({ expansionState: _this.state.expansionState, selectedPaths: selectedPaths }); var _a; }; _this.handleSelectFile = function (evt, item) { evt.stopPropagation(); var filePath = item.filePath; var selectedPaths = (_a = {}, _a[filePath] = fileSelected, _a); _this.setState({ selectedPaths: selectedPaths }); commands.doOpenOrActivateFileTab.emit({ filePath: filePath }); var _a; }; _this.state = { width: 200, expansionState: {}, selectedPaths: {}, treeRoot: { name: 'loading', filePath: 'loading', subDirs: [], files: [] }, treeScrollHasFocus: false, }; _this.setupTree(props); return _this; // debug // this.state.shown = true; // debug } FileTree.prototype.componentWillReceiveProps = function (props) { this.setupTree(props); }; FileTree.prototype.componentDidMount = function () { var _this = this; settings.fileTreeWidth.get().then(function (res) { var width = res || _this.state.width; width = Math.min(window.innerWidth - 100, width); _this.setState({ width: width }); }); var handleFocusRequestBasic = function (shown) { if (!shown) { state.expandFileTree({}); } var selectedFilePaths = Object.keys(_this.state.selectedPaths); var pathToFocus = selectedFilePaths.length > 0 && _this.ref(selectedFilePaths[selectedFilePaths.length - 1]) ? selectedFilePaths[selectedFilePaths.length - 1] : _this.state.treeRoot.filePath; _this.focusOnPath(pathToFocus); return false; }; this.disposible.add(commands.esc.on(function () { if (_this.state.showHelp) { _this.setState({ showHelp: false }); setTimeout(function () { return _this.focusOnPath(_this.state.treeRoot.filePath); }, 150); } })); this.disposible.add(commands.treeViewToggle.on(function () { var shown = _this.props.fileTreeShown; shown ? state.collapseFileTree({}) : state.expandFileTree({}); if (!shown) { handleFocusRequestBasic(true); } else { commands.esc.emit({}); } })); this.disposible.add(commands.treeViewRevealActiveFile.on(function () { if (!_this.props.fileTreeShown) { state.expandFileTree({}); } var selectedTab = appTabsContainer_1.tabState.getSelectedTab(); if (selectedTab && selectedTab.url.startsWith('file://')) { var filePath = utils.getFilePathFromUrl(selectedTab.url); // expand the tree to make sure this file is visible var root = _this.state.treeRoot.filePath; var remainderAfterRoot = filePath.substr(root.length + 1 /* for `/` */); var dirPortionsAfterRoot = utils.getDirectory(remainderAfterRoot).split('/'); var runningPortion = ''; var expanded = {}; expanded[root] = true; for (var _i = 0, dirPortionsAfterRoot_1 = dirPortionsAfterRoot; _i < dirPortionsAfterRoot_1.length; _i++) { var portion = dirPortionsAfterRoot_1[_i]; runningPortion = runningPortion + '/' + portion; var fullPath = root + runningPortion; expanded[fullPath] = true; } var expansionState = csx.extend(_this.state.expansionState, expanded); // also only select this node var selectedPaths = (_a = {}, _a[filePath] = fileSelected, _a); _this.setState({ expansionState: expansionState, selectedPaths: selectedPaths }); _this.focusOnPath(filePath); } else { handleFocusRequestBasic(true); } return false; var _a; })); this.disposible.add(commands.treeViewFocus.on(function () { handleFocusRequestBasic(_this.props.fileTreeShown); })); /** * Utility: takes the selected state to the last item selected * If no item selected it selects the root */ var goDownToSmallestSelection = function () { var selectedFilePaths = Object.keys(_this.state.selectedPaths); if (selectedFilePaths.length == 0) { var selectedPaths = (_a = {}, _a[_this.state.treeRoot.filePath] = fileSelected, _a); _this.setState({ selectedPaths: selectedPaths }); } else if (selectedFilePaths.length > 1) { var path = selectedFilePaths[selectedFilePaths.length - 1]; var selectedPaths = (_b = {}, _b[path] = _this.state.selectedPaths[path], _b); _this.setState({ selectedPaths: selectedPaths }); } else { // already single selection :) } var selectedFilePath = Object.keys(_this.state.selectedPaths)[0]; var selectedFilePathDetails = _this.state.selectedPaths[selectedFilePath]; return { selectedFilePath: selectedFilePath, isDir: selectedFilePathDetails.isDir }; var _a, _b; }; /** * Utility : gets you the last item selected if any, otherwise the root dir * Does not modify state */ var getLastSelected = function () { var selectedFilePaths = Object.keys(_this.state.selectedPaths); var last = selectedFilePaths[selectedFilePaths.length - 1]; if (!last) { return { filePath: _this.state.treeRoot.filePath, isDir: true }; } var selectedFilePathDetails = _this.state.selectedPaths[last]; return { filePath: last, isDir: selectedFilePathDetails.isDir }; }; /** Utility : set an item as the only selected */ var setAsOnlySelectedNoFocus = function (filePath, isDir) { var selectedPaths = (_a = {}, _a[filePath] = { isDir: isDir }, _a); _this.setState({ selectedPaths: selectedPaths }); var _a; }; var setAsOnlySelected = function (filePath, isDir) { setAsOnlySelectedNoFocus(filePath, isDir); _this.focusOnPath(filePath); }; /** * Used in handling keyboard for tree items */ var treeRoot = this.ref('__treeroot'); var handlers = new Mousetrap(treeRoot); /** * file action handlers */ handlers.bind(commands.treeAddFile.config.keyboardShortcut, function () { if (_this.loading) return; var lastSelected = getLastSelected(); var dirPath = lastSelected.isDir ? lastSelected.filePath : utils.getDirectory(lastSelected.filePath); inputDialog_1.inputDialog.open({ header: "Enter a file name", onOk: function (value) { var filePath = value; socketClient_1.server.addFile({ filePath: filePath }).then(function (res) { commands.doOpenOrFocusFile.emit({ filePath: filePath }); }); }, onEsc: function () { setTimeout(handleFocusRequestBasic, 150); }, filterValue: dirPath + '/', }); return false; }); handlers.bind(commands.treeAddFolder.config.keyboardShortcut, function () { if (_this.loading) return; var lastSelected = getLastSelected(); var dirPath = lastSelected.isDir ? lastSelected.filePath : utils.getDirectory(lastSelected.filePath); inputDialog_1.inputDialog.open({ header: "Enter a folder name", onOk: function (value) { var filePath = value; socketClient_1.server.addFolder({ filePath: filePath }).then(function (res) { ui.notifyInfoQuickDisappear('Folder created'); }); }, onEsc: function () { setTimeout(handleFocusRequestBasic, 150); }, filterValue: dirPath + '/', }); return false; }); handlers.bind(commands.treeDuplicateFile.config.keyboardShortcut, function () { if (_this.loading) return; var selection = goDownToSmallestSelection(); if (!selection) { ui.notifyInfoNormalDisappear('Nothing selected'); return false; } var parentDir = utils.getDirectory(selection.selectedFilePath); if (selection.isDir) { inputDialog_1.inputDialog.open({ header: "Enter a new directory name", onOk: function (value) { var filePath = value; socketClient_1.server.duplicateDir({ src: selection.selectedFilePath, dest: filePath }); setAsOnlySelectedNoFocus(filePath, true); _this.state.expansionState[filePath] = true; _this.setState({ expansionState: _this.state.expansionState }); }, onEsc: function () { setTimeout(handleFocusRequestBasic, 150); }, filterValue: parentDir + '/', }); } else { inputDialog_1.inputDialog.open({ header: "Enter a new file name", onOk: function (value) { var filePath = value; socketClient_1.server.duplicateFile({ src: selection.selectedFilePath, dest: filePath }); commands.doOpenOrFocusFile.emit({ filePath: filePath }); setAsOnlySelectedNoFocus(filePath, false); }, onEsc: function () { setTimeout(handleFocusRequestBasic, 150); }, filterValue: parentDir + '/', }); } return false; }); handlers.bind([commands.treeMoveFile.config.keyboardShortcut, commands.treeRenameFile.config.keyboardShortcut], function () { if (_this.loading) return; var selection = goDownToSmallestSelection(); if (!selection) { ui.notifyInfoNormalDisappear('Nothing selected'); return false; } inputDialog_1.inputDialog.open({ header: "Enter a new location", onOk: function (value) { var filePath = value; socketClient_1.server.movePath({ src: selection.selectedFilePath, dest: filePath }).then(function (res) { if (res.error) { ui.notifyWarningNormalDisappear("Failed to move: " + res.error); return; } if (selection.isDir) { setAsOnlySelectedNoFocus(filePath, true); _this.state.expansionState[filePath] = true; _this.setState({ expansionState: _this.state.expansionState }); commands.closeFilesDirs.emit({ files: [], dirs: [selection.selectedFilePath] }); } else { commands.doOpenOrFocusFile.emit({ filePath: filePath }); setAsOnlySelectedNoFocus(filePath, false); commands.closeFilesDirs.emit({ files: [selection.selectedFilePath], dirs: [] }); } }); }, onEsc: function () { setTimeout(handleFocusRequestBasic, 150); }, filterValue: selection.selectedFilePath, }); return false; }); handlers.bind([commands.treeDeleteFile.config.keyboardShortcut, "backspace"], function () { if (_this.loading) return; var selectedFilePaths = Object.keys(_this.state.selectedPaths); var selectedFilePathsDetails = selectedFilePaths.map(function (fp) { return { filePath: fp, isDir: _this.state.selectedPaths[fp].isDir }; }); if (selectedFilePaths.length == 0) { ui.notifyInfoNormalDisappear('Nothing selected'); return false; } if (selectedFilePaths.some(function (fp) { return fp == _this.state.treeRoot.filePath; })) { ui.notifyWarningNormalDisappear("You cannot delete the root working directory"); return false; } inputDialog_1.inputDialog.open({ hideInput: true, header: "Delete " + (selectedFilePaths.length > 1 ? selectedFilePaths.length + ' items' : utils.getFileName(selectedFilePaths[0])) + "?", onOk: function () { var files = selectedFilePathsDetails.filter(function (x) { return !x.isDir; }).map(function (x) { return x.filePath; }); var dirs = selectedFilePathsDetails.filter(function (x) { return x.isDir; }).map(function (x) { return x.filePath; }); socketClient_1.server.deleteFromDisk({ files: files, dirs: dirs }).then(function (res) { commands.closeFilesDirs.emit({ files: files, dirs: dirs }); // Leave selection in a useful state var lastSelectedDetails = selectedFilePathsDetails[selectedFilePathsDetails.length - 1].filePath; setAsOnlySelected(utils.getDirectory(lastSelectedDetails), true); }); }, onEsc: function () { setTimeout(handleFocusRequestBasic, 150); } }); return false; }); handlers.bind(commands.treeOpenInExplorerFinder.config.keyboardShortcut, function () { if (_this.loading) return; var selection = goDownToSmallestSelection(); if (!selection) { ui.notifyInfoNormalDisappear('Nothing selected'); return false; } var dirFilePath = selection.selectedFilePath; if (!selection.isDir) { dirFilePath = utils.getDirectory(dirFilePath); } socketClient_1.server.launchDirectory({ filePath: dirFilePath }); ui.notifySuccessNormalDisappear("Command to open sent: " + dirFilePath); return false; }); handlers.bind(commands.treeOpenInCmdTerminal.config.keyboardShortcut, function () { if (_this.loading) return; var selection = goDownToSmallestSelection(); if (!selection) { ui.notifyInfoNormalDisappear('Nothing selected'); return false; } var dirFilePath = selection.selectedFilePath; if (!selection.isDir) { dirFilePath = utils.getDirectory(dirFilePath); } socketClient_1.server.launchTerminal({ filePath: dirFilePath }); ui.notifySuccessNormalDisappear("Command to open cmd/terminal sent: " + dirFilePath); return false; }); /** * navigation handlers */ handlers.bind('enter', function () { if (_this.loading) return; var _a = goDownToSmallestSelection(), selectedFilePath = _a.selectedFilePath, isDir = _a.isDir; if (isDir) { _this.state.expansionState[selectedFilePath] = !_this.state.expansionState[selectedFilePath]; _this.setState({ expansionState: _this.state.expansionState }); } else { commands.doOpenOrFocusFile.emit({ filePath: selectedFilePath }); } return false; }); handlers.bind('up', function () { if (_this.loading) return; var _a = goDownToSmallestSelection(), selectedFilePath = _a.selectedFilePath, isDir = _a.isDir; // if root do nothing if (selectedFilePath == _this.state.treeRoot.filePath) { return; } // find the parent dir && // find this in the parent dir var parentDirFilePath = utils.getDirectory(selectedFilePath); var parentDirTreeItem = _this.dirLookup[parentDirFilePath]; var indexInParentDir = isDir ? parentDirTreeItem.subDirs.map(function (x) { return x.filePath; }).indexOf(selectedFilePath) : parentDirTreeItem.files.map(function (x) { return x.filePath; }).indexOf(selectedFilePath); /** Goes to the bottom file / folder */ var gotoBottomOfFolder = function (closestDir) { while (true) { if (!_this.state.expansionState[closestDir.filePath]) { setAsOnlySelected(closestDir.filePath, true); break; } if (closestDir.files.length) { setAsOnlySelected(closestDir.files[closestDir.files.length - 1].filePath, false); break; } else if (closestDir.subDirs.length) { closestDir = closestDir.subDirs[closestDir.subDirs.length - 1]; continue; } else { setAsOnlySelected(closestDir.filePath, true); break; } } }; // if first if (indexInParentDir == 0) { if (isDir) { setAsOnlySelected(parentDirFilePath, true); } else if (parentDirTreeItem.subDirs.length == 0) { setAsOnlySelected(parentDirFilePath, true); } else { gotoBottomOfFolder(parentDirTreeItem.subDirs[parentDirTreeItem.subDirs.length - 1]); } } else if (!isDir) { setAsOnlySelected(parentDirTreeItem.files[indexInParentDir - 1].filePath, false); } else { var closestDir = parentDirTreeItem.subDirs[indexInParentDir - 1]; gotoBottomOfFolder(closestDir); } return false; }); handlers.bind('down', function () { if (_this.loading) return; var _a = goDownToSmallestSelection(), selectedFilePath = _a.selectedFilePath, isDir = _a.isDir; /** Goes to next sibling on any (recursive) parent folder */ var gotoNextSiblingHighUp = function (treeItem) { // Special handling for root. Don't change selection :) if (treeItem.filePath == _this.state.treeRoot.filePath) { return; } var parentDirFilePath = utils.getDirectory(treeItem.filePath); var parentTreeItem = _this.dirLookup[parentDirFilePath]; var indexInParent = parentTreeItem.subDirs.map(function (x) { return x.filePath; }).indexOf(treeItem.filePath); if (indexInParent !== (parentTreeItem.subDirs.length - 1)) { setAsOnlySelected(parentTreeItem.subDirs[indexInParent + 1].filePath, true); } else if (parentTreeItem.files.length) { setAsOnlySelected(parentTreeItem.files[0].filePath, false); } else { gotoNextSiblingHighUp(parentTreeItem); } }; if (isDir) { var dirTreeItem = _this.dirLookup[selectedFilePath]; // If expanded and has children, select first relevant child if (_this.state.expansionState[selectedFilePath] && (dirTreeItem.files.length || dirTreeItem.subDirs.length)) { dirTreeItem.subDirs[0] ? setAsOnlySelected(dirTreeItem.subDirs[0].filePath, true) : setAsOnlySelected(dirTreeItem.files[0].filePath, false); } else { // Else find the next sibling dir gotoNextSiblingHighUp(dirTreeItem); } } else { var parentDirFilePath = utils.getDirectory(selectedFilePath); var parentTreeItem = _this.dirLookup[parentDirFilePath]; var indexInParent = parentTreeItem.files.map(function (f) { return f.filePath; }).indexOf(selectedFilePath); // if not last select next sibling if (indexInParent !== (parentTreeItem.files.length - 1)) { setAsOnlySelected(parentTreeItem.files[indexInParent + 1].filePath, false); } else { gotoNextSiblingHighUp(parentTreeItem); } } return false; }); handlers.bind('left', function () { if (_this.loading) return; var _a = goDownToSmallestSelection(), selectedFilePath = _a.selectedFilePath, isDir = _a.isDir; if (isDir) { // if expanded then collapse if (_this.state.expansionState[selectedFilePath]) { delete _this.state.expansionState[selectedFilePath]; _this.setState({ expansionState: _this.state.expansionState }); return; } // if root ... leave if (_this.state.treeRoot.filePath == selectedFilePath) { return; } } // Goto the parent directory setAsOnlySelected(utils.getDirectory(selectedFilePath), true); return false; }); handlers.bind('right', function () { if (_this.loading) return; var _a = goDownToSmallestSelection(), selectedFilePath = _a.selectedFilePath, isDir = _a.isDir; if (isDir) { // just expand _this.state.expansionState[selectedFilePath] = true; _this.setState({ expansionState: _this.state.expansionState }); return false; } return false; }); handlers.bind('h', function () { _this.setState({ showHelp: !_this.state.showHelp }); }); handlers.bind('c', function () { var copyButtonRef = _this.ref('copypath'); if (!copyButtonRef) { ui.notifyInfoNormalDisappear('Nothing selected'); return; } var copypathDom = ReactDOM.findDOMNode(copyButtonRef); copypathDom.click(); }); /** * TS to js and JS to ts */ handlers.bind('t', function () { if (_this.loading) return; var selection = goDownToSmallestSelection(); if (!selection) { ui.notifyInfoNormalDisappear('Nothing selected'); return false; } var filePath = selection.selectedFilePath; if (selection.isDir || (!filePath.endsWith('.js')) && !filePath.endsWith('.jsx')) { ui.notifyInfoNormalDisappear('Please select a `.js`/`jsx` file'); return false; } var newFilePath = filePath.replace(/\.js$/g, '.ts').replace(/\.jsx$/g, '.tsx'); socketClient_1.server.movePath({ src: filePath, dest: newFilePath }).then(function (res) { commands.doOpenOrFocusFile.emit({ filePath: newFilePath }); setAsOnlySelectedNoFocus(newFilePath, false); commands.closeFilesDirs.emit({ files: [filePath], dirs: [] }); ui.notifySuccessNormalDisappear('File extension changed to be TypeScript'); }); return false; }); handlers.bind('j', function () { if (_this.loading) return; var selection = goDownToSmallestSelection(); if (!selection) { ui.notifyInfoNormalDisappear('Nothing selected'); return false; } var filePath = selection.selectedFilePath; if (selection.isDir || (!filePath.endsWith('.ts')) && !filePath.endsWith('.tsx')) { ui.notifyInfoNormalDisappear('Please select a `.ts`/`tsx` file'); return false; } var newFilePath = filePath.replace(/\.ts$/g, '.js').replace(/\.tsx$/g, '.jsx'); socketClient_1.server.movePath({ src: filePath, dest: newFilePath }).then(function (res) { commands.doOpenOrFocusFile.emit({ filePath: newFilePath }); setAsOnlySelectedNoFocus(newFilePath, false); commands.closeFilesDirs.emit({ files: [filePath], dirs: [] }); ui.notifySuccessNormalDisappear('File extension changed to be JavaScript'); }); return false; }); }; FileTree.prototype.render = function () { var _this = this; var singlePathSelected = Object.keys(this.state.selectedPaths).length == 1 && Object.keys(this.state.selectedPaths)[0]; var hideStyle = !this.props.fileTreeShown && { display: 'none' }; var haveFocus = this.state.treeScrollHasFocus; var helpOpacity = haveFocus ? 1 : 0; return (React.createElement("div", { ref: this.refNames.__treeroot, className: "alm-tree-root", style: csx.extend(csx.flexRoot, csx.horizontal, { width: this.state.width, zIndex: 6 }, hideStyle) }, React.createElement("div", { style: csx.extend(csx.flex, csx.vertical, treeListStyle, styles.someChildWillScroll, csx.newLayerParent) }, React.createElement("div", { ref: this.refNames.__treeViewScroll, className: treeScrollClassName, style: csx.extend(csx.flex, csx.scroll), tabIndex: 0, onFocus: function () { return _this.setState({ treeScrollHasFocus: true }); }, onBlur: function () { return _this.setState({ treeScrollHasFocus: false }); } }, this.renderDir(this.state.treeRoot)), this.props.filePathsCompleted || React.createElement(robocop_1.Robocop, null), singlePathSelected && React.createElement("div", { style: csx.extend(csx.content, csx.horizontal, csx.center, csx.centerJustified, { paddingTop: '5px', paddingBottom: '5px', width: this.state.width - 15 + 'px' }) }, React.createElement(clipboard.Clipboard, { ref: 'copypath', text: singlePathSelected }), React.createElement("span", { className: "hint--top", "data-hint": "Click to copy the file path to clipboard", "data-clipboard-text": singlePathSelected, style: currentSelectedItemCopyStyle, onClick: function () { return ui.notifyInfoQuickDisappear("Path copied to clipboard"); } }, singlePathSelected)), React.createElement("div", { style: csx.extend(csx.content, csx.centerCenter, { fontSize: '.7em', lineHeight: '2em', opacity: helpOpacity, transition: 'opacity .2s' }) }, React.createElement("span", null, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "H"), " to toggle tree view help")), this.state.showHelp && React.createElement("div", { style: csx.extend(csx.newLayer, csx.centerCenter, csx.flex, { background: 'rgba(0,0,0,.7)' }), onClick: function () { return _this.setState({ showHelp: false }); } }, React.createElement("div", { style: csx.extend(csx.flexRoot, csx.vertical) }, React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "ESC"), " to hide help"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "A"), " to add a file"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "Shift + A"), " to add a folder"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "D"), " to duplicate file / folder"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "M"), " to move file / folder"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "R"), " to rename file / folder"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "C"), " to copy path to clipboard"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "O"), " to open in explorer/finder"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "Shift + O"), " to open in cmd/terminal"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "T"), " to change .js to .ts"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "J"), " to change .ts to .js"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "arrow keys"), " to browse"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "del or backspace"), " to delete"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "enter"), " to open file / expand dir"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, commands.modName, " + \\"), " to toggle tree view"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, "Shift + ", commands.modName, " + \\"), " to locate open file in view"), React.createElement("div", { style: helpRowStyle }, "Tap ", React.createElement("span", { style: styles.Tip.keyboardShortCutStyle }, " ", commands.modName, " + 0"), " to focus on tree view")))), React.createElement(DraggableCore, { onDrag: this.handleDrag, onStop: this.handleDragStop }, React.createElement("div", { style: csx.extend(csx.flexRoot, csx.centerCenter, resizerStyle) }, React.createElement(icon_1.Icon, { name: "ellipsis-v" }))))); }; FileTree.prototype.renderDir = function (item, depth) { if (depth === void 0) { depth = 0; } var expanded = this.state.expansionState[item.filePath]; var sub = expanded ? this.renderDirSub(item, depth) : []; var selected = !!this.state.selectedPaths[item.filePath]; return ([React.createElement(TreeNode.Dir, { key: item.filePath, ref: item.filePath, item: item, depth: depth, selected: selected, expanded: expanded, handleToggleDir: this.handleToggleDir, activeProjectFilePathTruthTable: this.props.activeProjectFilePathTruthTable })].concat(sub)); }; FileTree.prototype.renderDirSub = function (item, depth) { var _this = this; return item.subDirs.map(function (item) { return _this.renderDir(item, depth + 1); }) .concat(item.files.map(function (file) { return _this.renderFile(file, depth + 1); })); }; FileTree.prototype.renderFile = function (item, depth) { var selected = !!this.state.selectedPaths[item.filePath]; return (React.createElement(TreeNode.File, { ref: item.filePath, key: item.filePath, item: item, depth: depth, selected: selected, handleSelectFile: this.handleSelectFile, activeProjectFilePathTruthTable: this.props.activeProjectFilePathTruthTable })); }; FileTree.prototype.focusOnPath = function (filePath) { if (!this.ref(filePath)) return; this.refs['__treeViewScroll'].focus(); this.ref(filePath).focus(); }; FileTree.prototype.componentWillUpdate = function (nextProps, nextState) { if (nextState.width !== this.state.width || nextProps.fileTreeShown !== this.props.fileTreeShown) { appTabsContainer_1.tabState.debouncedResize(); } }; FileTree = __decorate([ react_redux_1.connect(function (state) { return { filePaths: state.filePaths, filePathsCompleted: state.filePathsCompleted, rootDir: state.rootDir, activeProjectFilePathTruthTable: state.activeProjectFilePathTruthTable, fileTreeShown: state.fileTreeShown, }; }), __metadata("design:paramtypes", [Object]) ], FileTree); return FileTree; }(ui_1.BaseComponent)); exports.FileTree = FileTree; var TreeNode; (function (TreeNode) { var Dir = /** @class */ (function (_super) { __extends(Dir, _super); function Dir() { return _super !== null && _super.apply(this, arguments) || this; } Dir.prototype.focus = function (filePath) { this.refs['root'].scrollIntoViewIfNeeded(false); }; Dir.prototype.render = function () { var _this = this; var _a = this.props, item = _a.item, depth = _a.depth, expanded = _a.expanded; var icon = expanded ? 'folder-open' : 'folder'; var selectedStyle = this.props.selected ? treeItemSelectedStyle : {}; var inProjectStyle = this.props.activeProjectFilePathTruthTable[item.filePath] ? treeItemInProjectStyle : {}; return (React.createElement("div", { className: treeItemClassName, style: csx.extend(selectedStyle, inProjectStyle), key: item.filePath, ref: 'root', tabIndex: -1, onClick: function (evt) { return _this.props.handleToggleDir(evt, item); } }, React.createElement("div", { style: { marginLeft: depth * 10 } }, " ", React.createElement(icon_1.Icon, { name: icon }), " ", item.name))); }; return Dir; }(React.PureComponent)); TreeNode.Dir = Dir; /** * File Name Based Icon */ var FileNameBasedIcon = /** @class */ (function (_super) { __extends(FileNameBasedIcon, _super); function FileNameBasedIcon() { return _super !== null && _super.apply(this, arguments) || this; } FileNameBasedIcon.prototype.render = function () { var fileName = this.props.fileName.toLowerCase(); var ext = utils.getExt(fileName); // Default var iconName = 'file-text-o'; if (ext == 'md') { iconName = 'book'; } else if (ext == 'json') { iconName = 'database'; } else if (ext == 'html' || ext == 'htm') { iconName = 'file-code-o'; } else if (ext == 'css' || ext == 'less' || ext == 'scss' || ext == 'sass') { iconName = 'css3'; } else if (ext.startsWith('git')) { iconName = 'github'; } else if (ext.endsWith('sh') || ext == 'bat' || ext == 'batch') { iconName = 'terminal'; } else if (ext.endsWith('coffee')) { iconName = 'coffee'; } else if (utils.isTs(fileName)) { iconName = 'rocket'; } else if (utils.isJs(fileName)) { iconName = 'plane'; } else if (utils.isImage(fileName)) { iconName = 'file-image-o'; } var icon = React.createElement(icon_1.Icon, { name: iconName }); return React.createElement("div", null, icon, " ", this.props.fileName); }; return FileNameBasedIcon; }(React.PureComponent)); /** Renders the file item */ var File = /** @class */ (function (_super) { __extends(File, _super); function File() { return _super !== null && _super.apply(this, arguments) || this; } File.prototype.focus = function () { this.refs['root'].scrollIntoViewIfNeeded(false); }; File.prototype.render = function () { var _this = this; var filePath = this.props.item.filePath; var selectedStyle = this.props.selected ? treeItemSelectedStyle : {}; var inProjectStyle = this.props.activeProjectFilePathTruthTable[filePath] ? treeItemInProjectStyle : {}; /** Determine if generated