UNPKG

kui-shell

Version:

This is the monorepo for Kui, the hybrid command-line/GUI electron-based Kubernetes tool

310 lines 15.6 kB
"use strict"; 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 path_1 = require("path"); const core_1 = require("@kui-shell/core"); const sidecar_selector_1 = require("@kui-shell/core/webapp/views/sidecar-selector"); const sidecar_1 = require("@kui-shell/core/webapp/views/sidecar"); const strings = core_1.i18n('plugin-core-support'); const SECONDS_TILL_AUTO_CLOSE = 10; const usage = { strict: 'screenshot', command: 'screenshot', title: strings('screenshotUsageTitle'), header: strings('screenshotUsageHeader'), example: 'screenshot [which]', detailedExample: [ { command: 'screenshot sidecar', docs: strings('screenshotSidecarUsageDocs') }, { command: 'screenshot repl', docs: strings('screenshotReplUsageDocs') }, { command: 'screenshot last', docs: strings('screenshotLastUsageDocs') }, { command: 'screenshot full', docs: strings('screenshotFullUsageDocs') }, { command: 'screenshot', docs: strings('screenshotUsageDocs') } ], optional: [ { name: 'which', positional: true, docs: strings('screenshotWhichUsageDocs'), allowed: ['sidecar', 'repl', 'full', 'last', 'nth'] }, { name: '--nth', docs: strings('screenshotNUsageDocs'), numeric: true } ] }; const round = Math.round; const selectors = { full: 'body', default: 'body > .page', sidecar: (tab) => sidecar_selector_1.default(tab), repl: (tab) => tab.querySelector('.repl'), nth: (tab, n) => tab.querySelector(`.repl .repl-block:nth-child(${n}) .repl-output .repl-result`), 'last-full': (tab) => tab.querySelector('.repl .repl-block:nth-last-child(2)'), last: (tab) => tab.querySelector('.repl .repl-block:nth-last-child(2) .repl-output .repl-result') }; const hideCurrentReplBlock = [ { selector: '#main-repl .repl-block.processing', property: 'display', value: 'none' } ]; const squishers = { sidecar: [ { selector: 'body.subwindow', css: 'screenshot-squish' }, { selector: 'body.subwindow .page', css: 'screenshot-squish' }, { selector: 'body.subwindow .main', css: 'screenshot-squish' }, { selector: 'tab.visible', css: 'screenshot-squish' } ], full: hideCurrentReplBlock, repl: hideCurrentReplBlock }; const _squish = (tab, which, selector, op) => { let squisher = squishers[which]; if (typeof squisher === 'function') { squisher = squisher(selector); } if (squisher) { const impl = (dryRun) => squisher .map(({ selector, property, value, css }) => { const element = selector === 'tab.visible' ? tab : typeof selector === 'string' ? document.querySelector(selector) : selector; if (element) { return op(dryRun, element, property, value, css); } }) .find(x => x); const doNotSquish = impl(true); if (!doNotSquish) { impl(false); } return doNotSquish; } }; const squish = (tab, which, selector) => _squish(tab, which, selector, (dryRun, element, property, value, css) => { if (dryRun) { const scrollers = element.querySelectorAll('.overflow-auto'); for (let idx = 0; idx < scrollers.length; idx++) { const scroller = scrollers[idx]; if (scroller.scrollTop) { return true; } } } else { if (css) element.classList.add(css); if (property) element.style[property] = value; } }); const unsquish = (tab, which, selector) => _squish(tab, which, selector, (_, element, property, value, css) => { if (css) element.classList.remove(css); if (property) element.style[property] = null; }); const fill = (n) => (n < 10 ? `0${n}` : n); const dateString = (ts) => `${ts.getUTCFullYear()}-${fill(1 + ts.getUTCMonth())}-${fill(ts.getUTCDate())}`; const timeString = (ts) => ts.toLocaleTimeString('en-us').replace(/:/g, '.'); exports.default = (commandTree) => __awaiter(void 0, void 0, void 0, function* () { commandTree.listen('/screenshot', ({ tab, argvNoOptions, parsedOptions }) => new Promise((resolve, reject) => __awaiter(void 0, void 0, void 0, function* () { if (core_1.Capabilities.inBrowser()) { const error = new Error(strings('notSupportedInBrowser')); error['code'] = 500; reject(error); } const options = parsedOptions; try { const root = path_1.dirname(require.resolve('@kui-shell/plugin-core-support/package.json')); core_1.UI.injectCSS(path_1.join(root, 'web/css/screenshot.css')); const { ipcRenderer, nativeImage, remote, shell } = yield Promise.resolve().then(() => require('electron')); const { app } = remote; const which = (argvNoOptions[1] && argvNoOptions[1].toLowerCase()) || (options['nth'] && 'nth') || 'default'; let selector = selectors[which]; const N = options['nth']; if (typeof selector === 'function') { selector = selector(tab, N); } if (which === 'last' && !selector) { return reject(new Error(strings('screenshotREPLError'))); } else if (!selector) { return reject(new core_1.Errors.UsageError({ usage })); } else if (which === 'sidecar' && !sidecar_1.isVisible(tab)) { return reject(new Error(strings('screenshotSidecarNotOpen'))); } else if (which === 'nth') { if (N === undefined) { return reject(new Error('You must provide a numeric value for the "nth" argument')); } } const dom = selector && typeof selector === 'string' ? document.querySelector(selector) : selector; if (!dom) { console.error('bad selector', selector); return reject(new Error(strings('screenshotInternalError'))); } const screenshotButton = sidecar_selector_1.default(tab, '.sidecar-screenshot-button'); screenshotButton.classList.add('force-no-hover'); const doNotSquish = squish(tab, which, selector); const snap = () => { const domRect = dom.getBoundingClientRect(); const rect = { x: round(domRect.left) + (options.offset ? parseInt(options.offset, 10) : 0), y: round(domRect.top), width: round(domRect.width), height: round(domRect.height) }; if (which === 'sidecar') { rect.x += 1; rect.width -= 1; } const listener = (event, buf) => { document.body.classList.remove('no-tooltips-anywhere'); const page = document.querySelector('body > .page'); if (!buf) { screenshotButton.classList.remove('force-no-hover'); return reject(new Error('Internal Error')); } if (document.getElementById('screenshot-captured') !== null) { const prevSnapDom = document.getElementById('screenshot-captured'); if (prevSnapDom.kuiSnapshotTimer) { clearInterval(prevSnapDom.kuiSnapshotTimer); } prevSnapDom.remove(); } const img = nativeImage.createFromBuffer(buf); const snapDom = document.createElement('div'); const snapImg = document.createElement('img'); const message = document.createElement('div'); const messageContent = document.createElement('div'); const snapContent = document.createElement('div'); const close = document.createElement('div'); page.appendChild(snapDom); const finish = () => { snapDom.classList.add('screenshot-hide'); setTimeout(() => snapDom.classList.remove('screenshot-active'), 0); setTimeout(() => { page.removeChild(snapDom); core_1.UI.getCurrentPrompt(tab).readOnly = false; core_1.UI.getCurrentPrompt(tab).focus(); }, 1000); }; const windowSize = document.body.getBoundingClientRect(); const imgSize = img.getSize(); let widthPx = windowSize.width * 0.65; let heightPx = (imgSize.height / imgSize.width) * widthPx; if (heightPx > windowSize.height) { heightPx = windowSize.height * 0.65; widthPx = (imgSize.width / imgSize.height) * heightPx; } snapDom.appendChild(snapImg); snapDom.appendChild(snapContent); snapDom.appendChild(close); snapDom.setAttribute('data-notification', ''); snapDom.setAttribute('role', 'polite'); snapDom.setAttribute('data-notification', ''); snapDom.classList.add('bx--toast-notification'); snapDom.classList.add('bx--toast-notification--warning'); snapDom.classList.add('zoomable'); snapDom.id = 'screenshot-captured'; snapDom.classList.add('screenshot-hide'); snapDom.classList.add('screenshot-active'); setTimeout(() => snapDom.classList.remove('screenshot-hide'), 0); const saveButton = document.createElement('div'); const ts = new Date(); const filename = `Screen Shot ${dateString(ts)} ${timeString(ts)}.png`; const location = path_1.join(app.getPath('desktop'), filename); saveButton.className = 'screenshot-save-button'; saveButton.innerHTML = strings('Save to desktop'); saveButton.onclick = () => { remote.require('fs').writeFile(location, img.toPNG(), () => __awaiter(void 0, void 0, void 0, function* () { console.log(`screenshot saved to ${location}`); try { shell.showItemInFolder(location); } catch (err) { console.error('error opening screenshot file'); } })); }; snapImg.setAttribute('src', img.toDataURL()); snapImg.classList.add('screenshot-image'); snapContent.classList.add('screenshot-content'); message.classList.add('screenshot-success-message'); message.innerText = strings('Screenshot copied to clipboard'); messageContent.classList.add('screenshot-message'); messageContent.appendChild(message); const closeMessage = document.createElement('div'); closeMessage.classList.add('screenshot-closing-message'); closeMessage.setAttribute('id', 'close-msg'); messageContent.appendChild(closeMessage); snapContent.append(messageContent); snapContent.appendChild(saveButton); const closeButton = document.createElement('div'); close.classList.add('screenshot-close'); close.appendChild(closeButton); closeButton.innerHTML = '<div style="display: flex;justify-content:flex-end;align-items:baseline"><svg focusable="false" preserveAspectRatio="xMidYMid meet" style="will-change: transform; cursor:pointer" xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 32 32" aria-hidden="true"><path d="M24 9.4L22.6 8 16 14.6 9.4 8 8 9.4l6.6 6.6L8 22.6 9.4 24l6.6-6.6 6.6 6.6 1.4-1.4-6.6-6.6L24 9.4z" stroke="white" fill="white"></path></svg></div>'; closeButton.classList.add('screenshot-close-botton'); let timeleft = SECONDS_TILL_AUTO_CLOSE; snapDom.kuiSnapshotTimer = setInterval(() => { if (timeleft <= 0) { clearInterval(snapDom.kuiSnapshotTimer); finish(); } ; snapDom.querySelector('.screenshot-closing-message').innerText = strings('Closing in {0} seconds', timeleft.toString()); timeleft -= 1; }, 1000); const hiddenInput = document.createElement('input'); hiddenInput.classList.add('hidden'); hiddenInput.classList.add('grab-focus'); snapDom.appendChild(hiddenInput); hiddenInput.focus(); hiddenInput.addEventListener('keyup', (evt) => { if (evt.keyCode === core_1.UI.Keys.Codes.ESCAPE) { evt.preventDefault(); finish(); } }, { capture: true, once: true }); closeButton.onclick = finish; ipcRenderer.removeListener('capture-page-to-clipboard-done', listener); if (!doNotSquish) { unsquish(tab, which, selector); } screenshotButton.classList.remove('force-no-hover'); resolve(strings('Successfully captured a screenshot to the clipboard')); }; ipcRenderer.on('capture-page-to-clipboard-done', listener); ipcRenderer.send('capture-page-to-clipboard', remote.getCurrentWebContents().id, rect); }; document.body.classList.add('no-tooltips-anywhere'); setTimeout(snap, 100); } catch (e) { console.error(e); reject(new Error('Internal Error')); } })), { usage, noAuthOk: true, incognito: ['popup'], requiresLocal: true }); }); //# sourceMappingURL=screenshot.js.map