kui-shell
Version:
This is the monorepo for Kui, the hybrid command-line/GUI electron-based Kubernetes tool
286 lines • 12.9 kB
JavaScript
;
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
const debug_1 = require("debug");
const uuid = require("uuid/v4");
const capabilities_1 = require("@kui-shell/core/api/capabilities");
const commands_1 = require("@kui-shell/core/api/commands");
const events_1 = require("@kui-shell/core/api/events");
const i18n_1 = require("@kui-shell/core/api/i18n");
const models_1 = require("@kui-shell/core/api/models");
const settings_1 = require("@kui-shell/core/api/settings");
const UI = require("@kui-shell/core/api/ui-lite");
const sidecar_visibility_1 = require("@kui-shell/core/webapp/views/sidecar-visibility");
const sidecar_selector_1 = require("@kui-shell/core/webapp/views/sidecar-selector");
const listen_1 = require("@kui-shell/core/webapp/listen");
const status_1 = require("@kui-shell/core/webapp/status");
const tab_1 = require("@kui-shell/core/webapp/tab");
const strings = i18n_1.i18n('plugin-core-support');
const debug = debug_1.default('plugins/core-support/new-tab');
exports.tabButtonSelector = '#new-tab-button';
const { topTabs = { names: 'command' } } = settings_1.default.config;
const usage = {
strict: 'switch',
command: 'switch',
required: [{ name: 'tabIndex', numeric: true, docs: 'Switch to the given tab index' }]
};
function element(id, parent = document) {
return parent.querySelector(id);
}
function isUsingCommandName() {
return topTabs.names !== 'fixed' && !document.body.classList.contains('kui--alternate');
}
function getTabFromIndex(idx) {
return element(`.main tab:nth-child(${idx})`);
}
const getTabButton = (tab) => element(`.main .left-tab-stripe .left-tab-stripe-button[data-tab-id="${tab_1.getTabId(tab)}"]`);
const getCurrentTabButton = () => element('.main .left-tab-stripe .left-tab-stripe-button-selected');
const getTabButtonLabel = (tab) => getTabButton(tab).querySelector('.left-tab-stripe-button-label .kui-tab--label-text');
const getTabCloser = (tab) => getTabButton(tab).querySelector('.left-tab-stripe-button-closer');
const switchTab = (tabId, activateOnly = false) => {
debug('switchTab', tabId);
const currentTab = tab_1.getCurrentTab();
const nextTab = document.querySelector(`.main > .tab-container > tab[data-tab-id="${tabId}"]`);
const nextTabButton = document.querySelector(`.main .left-tab-stripe .left-tab-stripe-button[data-tab-id="${tabId}"]`);
if (!nextTab || !nextTabButton) {
debug('Cannot find the desired tab to switch to');
}
if (!activateOnly) {
const currentVisibleTab = tab_1.getCurrentTab();
const currentTabButton = getCurrentTabButton();
currentVisibleTab.classList.remove('visible');
currentTabButton.classList.remove('left-tab-stripe-button-selected');
currentTabButton.classList.remove('kui-tab--active');
}
nextTab.classList.add('visible');
nextTabButton.classList.add('left-tab-stripe-button-selected');
nextTabButton.classList.add('kui-tab--active');
if (currentTab) {
currentTab.state.capture();
}
if (nextTab.state) {
nextTab.state.restore();
}
const promptToFocus = UI.getCurrentPrompt(nextTab);
if (promptToFocus) {
promptToFocus.focus();
}
return true;
};
const addKeyboardListeners = () => {
};
const addCommandEvaluationListeners = () => {
events_1.default.on('/command/complete', (event) => {
if (event.execType !== undefined && event.execType !== commands_1.default.ExecType.Nested && event.route) {
const button = getTabButton(event.tab);
if (button) {
button.classList.remove('processing');
}
}
});
events_1.default.on('/command/start', (event) => {
if (event.execType !== undefined && event.execType !== commands_1.default.ExecType.Nested && event.route) {
const tab = event.tab;
if (event.route !== undefined &&
!event.route.match(/^\/(tab|getting\/started)/)) {
if (/^\/clear/.test(event.route)) {
if (!sidecar_visibility_1.isVisible(tab)) {
if (isUsingCommandName()) {
getTabButtonLabel(tab).innerText = settings_1.default.theme.productName;
}
}
}
else {
if (isUsingCommandName()) {
getTabButtonLabel(tab).innerText = event.command;
}
getTabButton(tab).classList.add('processing');
}
}
}
});
};
const closeTab = (tab = tab_1.getCurrentTab()) => {
debug('closeTab', tab);
const nTabs = document.querySelectorAll('.main > .tab-container > tab').length;
if (nTabs <= 1) {
if (capabilities_1.default.inElectron()) {
debug('closing window on close of last tab');
tab.REPL.qexec('window close');
}
return true;
}
if (tab === tab_1.getCurrentTab()) {
const makeThisTabActive = tab.nextElementSibling || tab.previousElementSibling;
debug('makeThisTabActive', makeThisTabActive, tab.nextSibling);
switchTab(tab_1.getTabId(makeThisTabActive), true);
}
const tabState = tab.state;
tabState.abortAllJobs();
tabState.closed = true;
const tabButton = getTabButton(tab);
tab.parentNode.removeChild(tab);
tabButton.parentNode.removeChild(tabButton);
events_1.default.emit('/tab/close', tab);
return true;
};
function isElement(target) {
return target.classList !== undefined;
}
function getSelectionText() {
if (window.getSelection) {
return window.getSelection().toString();
}
}
function isInViewport(el) {
const scroll = window.scrollY || window.pageYOffset;
const boundsTop = el.getBoundingClientRect().top + scroll;
const viewportTop = scroll;
const viewportBottom = scroll + window.innerHeight;
const boundsBottom = boundsTop + el.clientHeight;
return ((boundsBottom >= viewportTop && boundsBottom <= viewportBottom) ||
(boundsTop <= viewportBottom && boundsTop >= viewportTop));
}
const perTabInit = (tab, tabButton, doListen = true) => {
tab.state = new models_1.default.Tab.State();
const newTabId = uuid();
tab.setAttribute('data-tab-id', newTabId);
tabButton.setAttribute('data-tab-id', newTabId);
tabButton.onclick = () => switchTab(newTabId);
setTimeout(() => __awaiter(void 0, void 0, void 0, function* () {
const { REPL } = yield Promise.resolve().then(() => require('@kui-shell/core/api/repl'));
REPL.getImpl(tab);
events_1.default.emit('/tab/new', tab);
}));
if (doListen) {
listen_1.listen(UI.getCurrentPrompt(tab));
}
const grabFocus = (checkPath) => (evt) => {
const target = evt.target;
if (isElement(target)) {
setTimeout(() => {
const prompt = UI.getCurrentPrompt(tab);
if (prompt &&
getSelectionText().length === 0 &&
(target.classList.contains('repl-inner') ||
target.classList.contains('repl-output') ||
target.classList.contains('kui--tab-navigatable') ||
(checkPath && evt['path'] && evt['path'].find(_ => isElement(_) && /header/i.test(_.tagName))))) {
if (target.classList.contains('repl-inner') || isInViewport(prompt)) {
prompt.focus();
}
}
}, 0);
}
};
tab.querySelector('sidecar').addEventListener('click', grabFocus(false));
tab.querySelector('.repl-inner').addEventListener('click', grabFocus(true));
getTabCloser(tab).onclick = (event) => {
event.stopPropagation();
return closeTab(tab);
};
sidecar_selector_1.default(tab, '.sidecar-screenshot-button').onclick = () => {
debug('sidecar screenshot');
tab.REPL.pexec('screenshot sidecar');
};
};
const newTab = (basedOnEvent = false) => __awaiter(void 0, void 0, void 0, function* () {
debug('new tab');
if (basedOnEvent && process.env.RUNNING_SHELL_TEST) {
debug('aborting: spectron issues');
return;
}
const currentVisibleTab = tab_1.getCurrentTab();
currentVisibleTab.state.capture();
const newTab = currentVisibleTab.cloneNode(true);
newTab.className = 'visible';
const currentTabButton = getCurrentTabButton();
currentTabButton.classList.remove('left-tab-stripe-button-selected');
currentTabButton.classList.remove('kui-tab--active');
const newTabButton = currentTabButton.cloneNode(true);
newTabButton.classList.add('left-tab-stripe-button-selected');
newTabButton.classList.add('kui-tab--active');
newTabButton.classList.remove('processing');
currentTabButton.parentNode.appendChild(newTabButton);
const temps = newTab.querySelectorAll('.repl-temporary');
for (let idx = 0; idx < temps.length; idx++) {
temps[idx].remove();
}
const { REPL } = yield Promise.resolve().then(() => require('@kui-shell/core/api/repl'));
const currentlyProcessingBlock = yield REPL.qexec('clear --keep-current-active', undefined, undefined, { tab: newTab });
if (currentlyProcessingBlock !== true) {
debug('new tab cloned from one that is currently processing a command', currentlyProcessingBlock, currentlyProcessingBlock.querySelector('.repl-result').children.length);
status_1.setStatus(currentlyProcessingBlock, "repl-active");
}
UI.empty(newTab.querySelector('.repl-result'));
models_1.default.Selection.clear(newTab);
perTabInit(newTab, newTabButton);
newTabButton.scrollIntoView();
currentVisibleTab.classList.remove('visible');
currentVisibleTab.parentNode.appendChild(newTab);
UI.getCurrentPrompt(newTab).focus();
getTabButtonLabel(newTab).innerText = !isUsingCommandName() ? strings('Tab') : strings('New Tab');
return true;
});
const oneTimeInit = () => {
const initialTab = getTabFromIndex(1);
const initialTabButton = getCurrentTabButton();
if (document.body.classList.contains('subwindow')) {
element(exports.tabButtonSelector).onclick = () => window.open(window.location.href, '_blank');
}
else {
element(exports.tabButtonSelector).onclick = () => newTab();
}
addKeyboardListeners();
addCommandEvaluationListeners();
perTabInit(initialTab, initialTabButton, false);
getTabButtonLabel(tab_1.getCurrentTab()).innerText = !isUsingCommandName() ? strings('Tab') : settings_1.default.theme.productName;
document.querySelector('.main > .left-tab-stripe').onclick = () => {
UI.getCurrentPrompt().focus();
};
};
const newTabAsync = ({ execOptions }) => {
if (execOptions.nested) {
newTab();
return true;
}
else {
events_1.default.once('/core/cli/install-block', () => newTab());
return true;
}
};
const registerCommandHandlers = (commandTree) => {
commandTree.listen('/tab/switch', ({ argvNoOptions }) => switchTab(tab_1.getTabId(getTabFromIndex(parseInt(argvNoOptions[argvNoOptions.length - 1], 10)))), { usage, needsUI: true, noAuthOk: true });
commandTree.listen('/tab/new', newTabAsync, {
needsUI: true,
noAuthOk: true
});
commandTree.listen('/tab/close', () => closeTab(), {
needsUI: true,
noAuthOk: true
});
};
exports.default = (commandTree) => __awaiter(void 0, void 0, void 0, function* () {
if (typeof document !== 'undefined') {
oneTimeInit();
events_1.default.on('/theme/change', () => {
const tabLabels = document.querySelectorAll('.main .kui-header .kui-tab--label-text');
const usingCommandName = isUsingCommandName();
if (!usingCommandName) {
for (let idx = 0; idx < tabLabels.length; idx++) {
tabLabels[idx].innerText = strings('Tab');
}
}
});
return registerCommandHandlers(commandTree);
}
});
//# sourceMappingURL=new-tab.js.map