"use strict"; const fs = require("fs"); const path = require("path"); const _ = require("lodash"); const $ = require("jquery"); const React = require("react"); const { CompositeDisposable } = require("atom"); const atomIntegration = require("./atom-react/atom-integration"); const jsonOpener = require("./common/json-opener"); const packageGeneratorModal = require("./package-generator/package-generator-modal"); const launcher = require("./launcher/launcher"); const treeViewHelper = require("./common/tree-view-helper"); const CheatSheetTab = require("./cheat-sheet/cheat-sheat-tab"); const StyleguideEditor = require("./atom-react/styleguide/styleguide-editor"); const JiboSim = require("./animation-preview/jibo-sim"); const AnimationEditor = require("./animation-editor/animation-editor"); const BehaviorEditor = require("./behavior-editor/behavior-editor"); const AnimationModel = require("./animation-editor/models/animation-model"); const BehaviorTreeModel = require("./behavior-editor/tree-model"); function createUniquePath(directory, baseName, extension) { let candidate = path.join(directory, `${baseName}.${extension}`); let i = 1; while (fs.existsSync(candidate)) { candidate = path.join(directory, `${baseName}-${i}.${extension}`); i += 1; } return candidate; } function getSelectedProjectSubdir(subdirName) { return treeViewHelper.getFolderPathWithDirectory( treeViewHelper.getFolderPathOfSelection(), subdirName, ); } function notifyError(title, err) { if (!atom.notifications) return; atom.notifications.addError(title, { detail: String((err && err.stack) || err), dismissable: true, }); } module.exports = { config: { AnimationEditorBackgroundColor: { type: "color", default: "#4C4C4C", description: "The background color in the Animation Editor", }, AnimationEditorGridColor: { type: "color", default: "#E5E5E5", description: "The grid color in the Animation Editor", }, "RunConfiguration.type": { type: "string", enum: ["local", "remote"], default: "local", description: "Which mode to use when running/debugging your skill.", }, "RunConfiguration.host": { type: "string", default: "", description: "The host or ip of the robot you want to target.", }, "RunConfiguration.run-dir": { type: "string", default: "${project}", description: "The directory to run your skill from if it's not the root of your opened project.", }, DisableRunSkillShortcut: { type: "boolean", default: false, description: "Disable the shortcut for running skills, if you prefer it binding to built in the Symbol-Viewer toggle.", }, }, activate() { this.disposables = new CompositeDisposable(); try { atomIntegration.activate(); this.disposables.add( atom.workspace.addOpener((uri) => { return this.openURI(uri); }), ); this.disposables.add( atom.commands.add("atom-workspace", { "jibo-sdk:new-project": () => { try { packageGeneratorModal(); } catch (err) { notifyError("Jibo: New Project failed", err); } }, "jibo-sdk:open-as-json": () => { try { jsonOpener.open(); } catch (err) { notifyError("Jibo: Open as JSON failed", err); } }, "jibo-sdk:new-animation-file": () => { try { const dir = getSelectedProjectSubdir("animations"); if (!dir) { alert( "You must have a valid project loaded in order to create a new animation.", ); return; } const filePath = createUniquePath(dir, "new-animation", "keys"); if (!AnimationEditor.isValidDirectory(filePath)) { alert('You must save animations under the "animations" folder.'); return; } AnimationModel.createNewFile(filePath); atom.workspace.open(filePath); } catch (err) { notifyError("Jibo: New Animation failed", err); } }, "jibo-sdk:new-behavior-tree-file": () => { try { const dir = getSelectedProjectSubdir("behaviors"); if (!dir) { alert( "You must have a valid project loaded in order to create a new behavior tree file.", ); return; } const filePath = createUniquePath(dir, "new-behavior", "bt"); if (!BehaviorEditor.isValidDirectory(filePath)) { alert('You must save behavior trees under the "behaviors" folder.'); return; } const schema = BehaviorEditor.getNewSchema(filePath); BehaviorTreeModel.createNewFile(filePath, schema.core.schema.Sequence); atom.workspace.open(filePath); } catch (err) { notifyError("Jibo: New Behavior Tree failed", err); } }, "jibo-sdk:play": () => { try { launcher.play(); } catch (err) { notifyError("Jibo: Play failed", err); } }, "jibo-sdk:play-animation": () => { try { launcher.play(); } catch (err) { notifyError("Jibo: Play Animation failed", err); } }, "jibo-sdk:stop": () => { try { launcher.stop(); } catch (err) { notifyError("Jibo: Stop failed", err); } }, "jibo-sdk:cheat-sheet": () => { try { atom.workspace.open("atom://jibo-cheat-sheet"); } catch (err) { notifyError("Jibo: Open Cheat Sheet failed", err); } }, "atom-react:styleguide": () => { try { atom.workspace.open("atom://atom-react-styleguide"); } catch (err) { notifyError("Jibo: Open Styleguide failed", err); } }, "jibo-sdk:run-skill": (event) => { if (atom.config.get("jibo-sdk.DisableRunSkillShortcut")) { if (event && typeof event.abortKeyBinding === "function") event.abortKeyBinding(); return; } try { launcher.togglePlayer(); } catch (err) { notifyError("Jibo: Run Skill failed", err); } }, "jibo-sdk:login": () => { // Legacy login gating is no longer supported; keep as no-op. if (atom.notifications) { atom.notifications.addInfo("Jibo: Login is not required in Pulsar", { detail: "The original Atom-era login flow depended on deprecated Electron APIs.", dismissable: true, }); } }, }), ); } catch (err) { notifyError("Jibo SDK failed to activate", err); } }, deactivate() { if (this.disposables) this.disposables.dispose(); try { atomIntegration.deactivate(); } catch (err) { // ignore } }, openURI(uri) { // Always handle package URIs. if (uri === "atom://jibo-cheat-sheet") return new CheatSheetTab(uri, true); if (uri === "atom://atom-react-styleguide") return new StyleguideEditor(uri, true); // Respect JSON opener toggle for file-based editors. if (jsonOpener.useDefaultEditor() === false) return undefined; const handlers = { ".anim": JiboSim, ".keys": AnimationEditor, ".bt": BehaviorEditor, }; const ext = path.extname(uri).toLowerCase(); if (_.has(handlers, ext)) return new handlers[ext](uri); return undefined; }, };