kopyl

Figma plugin November 9 JS

Nov 9th, 2021
171
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. let fgLayer = null
  2.  
  3. const keypresses = {}
  4.  
  5. const l = console.log
  6.  
  7. class Styles {
  8.     constructor(layer) {
  9.         this.text = layer.textStyleId
  10.         this.color = layer.fillStyleId
  11.     }
  12. }
  13.  
  14. const getStyles = (layer) => {
  15.     return new Styles(layer)
  16. }
  17.  
  18.  
  19. const styles = {
  20.     get color() {
  21.         return new Styles(fSelected()).color
  22.     },
  23.     get text() {
  24.         return new Styles(fSelected()).text
  25.     }
  26. }
  27.  
  28. function isNumeric(str) {
  29.   if (typeof str != "string") return false // we only process strings!
  30.   return !isNaN(str) && // use type coercion to parse the _entirety_ of the string (`parseFloat` alone does not do this)...
  31.          !isNaN(parseFloat(str)) // ...and ensure strings of whitespace fail
  32. }
  33.  
  34. alphabet = {
  35.     getCharCodes(lower=true) {
  36.         const addValue = lower ? 97 : 65
  37.         const emptyArray = Array.from(Array(26))
  38.         return emptyArray.map((e, i) => i + addValue)
  39.     },
  40.     generateAlphabesArray(lower=true) {
  41.         const charCodes = this.getCharCodes(lower)
  42.         return charCodes.map((x) => String.fromCharCode(x))
  43.     },
  44.     get lower() {
  45.         return this.generateAlphabesArray(lower=true)
  46.     },
  47.     get upper() {
  48.         return this.generateAlphabesArray(lower=false)
  49.     }
  50. }
  51.  
  52. const selected = () => figma.currentPage.selection
  53.  
  54. const sleep = delay => new Promise(resolve => setTimeout(resolve, delay));
  55.  
  56. const select = (arrayLayers) => {
  57.     figma.currentPage.selection = arrayLayers
  58. }
  59.  
  60. const getStrDate = () => {
  61.     date = new Date()
  62.  
  63.     d = date.getDate()
  64.     mm = date.getMonth()
  65.     y = date.getFullYear()
  66.     h = date.getHours()
  67.     m = date.getMinutes()
  68.     s = date.getSeconds()
  69.    
  70.     return `${d}.${mm}.${y} ${h}:${m}:${s}`
  71. }
  72.  
  73. // Object.prototype.__defineGetter__(
  74. //     'values',
  75. //     function() {
  76. //         return Object.values(this)
  77. //     }
  78. // )
  79.  
  80. // Object.prototype.__defineGetter__(
  81. //     'keys',
  82. //     function() {
  83. //         return Object.keys(this)
  84. //     }
  85. // )
  86.  
  87. const fSelected = () => {
  88.     return figma.currentPage.selection[0]
  89. }
  90.  
  91. const replaceWithRandomNumbers = async(min, max) => {
  92.     let allNumbers = []
  93.     while(allNumbers.length < selected().length){
  94.             let numberReplaceWith = getRandomNmber(min, max)
  95.             numberReplaceWith = String(numberReplaceWith)
  96.             if(allNumbers.indexOf(numberReplaceWith) === -1) allNumbers.push(numberReplaceWith);
  97.         }
  98.  
  99.     for (let number = 0; number < selected().length; number++) {
  100.         await figma.loadFontAsync(selected()[number].fontName)
  101.         selected()[number].characters = allNumbers[number]
  102.     }
  103. }
  104.  
  105. const randomizeHotCold = () => {
  106.     let bools = createRandomBooArray(80)
  107.     let hot = figma.getNodeById("41:149")
  108.     let cold = figma.getNodeById("41:155")
  109.     let swapWith
  110.     for (let frame = 0; frame < selected().length; frame++) {
  111.         if (bools[frame] === true) {
  112.             swapWith = hot
  113.         } else {
  114.             swapWith = cold
  115.         }
  116.         selected()[frame].children.slice(-1)[0].swapComponent(swapWith)
  117.     }
  118. }
  119.  
  120.  
  121.  
  122.  
  123. class Archive {
  124.  
  125.     constructor() {
  126.         this.id = null
  127.         this.page = this.find()
  128.         this.exists = Boolean(this.page)
  129.         this.create()
  130.         this.notEmpty = this.page.findChild(e => e)
  131.         this.placeholderNode = this.createPlaceholderNode()
  132.     }
  133.  
  134.     find() {
  135.         const archive = figma.root.findChild(
  136.             e => e.type == "PAGE" && e.name == "Archive"
  137.         )
  138.         if (archive) this.id = archive.id
  139.         return archive
  140.     }
  141.  
  142.     create() {
  143.         if (this.exists) return
  144.         this.page = figma.createPage()
  145.         this.page.name = "Archive"
  146.         this.id = this.page.id
  147.     }
  148.    
  149.     createPlaceholderNode() {
  150.         /*
  151.         In case there were no layers in archive
  152.         It should have been better implemented
  153.         but there is no time for that,
  154.         and it works
  155.         so I'm leaving it as is
  156.         */
  157.         if (this.notEmpty) return
  158.         const placeholderNode = figma.createRectangle()
  159.         this.page.appendChild(placeholderNode)
  160.         return placeholderNode
  161.     }
  162.    
  163.     removePlaceholder() {
  164.         if (!this.placeholderNode) return
  165.         this.placeholderNode.remove()
  166.     }
  167.  
  168. }
  169.  
  170.  
  171.  
  172. const createRandomBooArray = (amount) => {
  173.     let allNumbers = []
  174.     while(allNumbers.length < amount){
  175.         let number = getRandomNmber(0, amount)
  176.         allNumbers.push(number)
  177.     }
  178.     let allBools = []
  179.     for (number of allNumbers) {
  180.         if (number % 2 === 0) {
  181.             allBools.push(true)
  182.         } else {
  183.             allBools.push(false)
  184.         }
  185.     }
  186.     return allBools
  187. }
  188.  
  189. const getRandomNmber = (min, max) => {
  190.   number = Math.random() * (max - min) + min
  191.   return Math.floor(number);
  192. }
  193.  
  194. const doublePressed = (event) => {
  195.     key = event.key
  196.     if (!keypresses[key]) {
  197.         keypresses[key] = Date.now()
  198.         return false
  199.     }
  200.     difference = Date.now() - keypresses[key]
  201.     if (difference < 1000) {
  202.         delete keypresses[key]
  203.         return true
  204.     } else {
  205.         delete keypresses[key]
  206.         return false
  207.     }
  208. }
  209.  
  210. const operators = {
  211.     '+': function(a) { return a + 1 },
  212.     '-': function(a) { return a - 1 },
  213. };
  214.  
  215. const revertResize = (currentlySelectedLayers, resizeDirection, horizontalOrVerical="horizontal") => {
  216.     for (let x=0; x<currentlySelectedLayers.length; x++) {
  217.         let currentlySelectedLayerWidth = currentlySelectedLayers[x].width
  218.         let currentlySelectedLayerHeight = currentlySelectedLayers[x].height
  219.        
  220.         if (horizontalOrVerical == "vertical") {
  221.             if (currentlySelectedLayers[x].type === "LINE") {continue}
  222.             currentlySelectedLayers[x].resize(currentlySelectedLayerWidth, operators[resizeDirection](currentlySelectedLayerHeight))
  223.             continue
  224.         }
  225.         currentlySelectedLayers[x].resize(operators[resizeDirection](currentlySelectedLayerWidth), currentlySelectedLayerHeight)
  226.     }  
  227. }
  228.  
  229. const collapseParentOf = (currentlySelectedLayer) => {
  230.     let parent = currentlySelectedLayer.parent
  231.     try {
  232.         figma.currentPage.selection = [parent]
  233.         parent.expanded = false
  234.      } catch {
  235.         currentlySelectedLayer.expanded = false
  236.      }
  237. }
  238.  
  239. const ToggleCurrentLayerCollapsion = () => {
  240.     selectedLayer = fSelected()
  241.     if ( selectedLayer.expanded == undefined ) {
  242.         select([selectedLayer.parent])
  243.         selectedLayer.parent.expanded = !selectedLayer.parent.expanded
  244.         return
  245.     }
  246.     selectedLayer.expanded = !selectedLayer.expanded
  247. }
  248.  
  249. const selectFirstLayerInGroup = () => {
  250.     let nodeToSelect = figma.currentPage.selection[0].children.slice(-1)[0] // last
  251.     figma.currentPage.selection = [nodeToSelect]
  252.     nodeToSelect.expanded = false
  253. }
  254.  
  255. const toggleTextBoundBox = async() => {
  256.     textLayer = figma.currentPage.selection[0]
  257.     await figma.loadFontAsync(textLayer.fontName)
  258.     if (textLayer.textAutoResize != "WIDTH_AND_HEIGHT") {
  259.         textLayer.textAutoResize = "WIDTH_AND_HEIGHT"
  260.     } else {
  261.         textLayer.textAutoResize = "HEIGHT"
  262.     }
  263. }
  264.  
  265. const getNextLayer = (parentChildren, nextLayer, event) => {
  266.     layerToSelect = [parentChildren[nextLayer]]
  267.     layersToSelect = layerToSelect.concat(figma.currentPage.selection)
  268.     let layersToSelectSatuses = {}
  269.     for (layer of layersToSelect) {
  270.         let layerStatus = layer.expanded
  271.         layersToSelectSatuses[layer.id] = layerStatus
  272.     }
  273.     if (event.altKey) {
  274.         figma.currentPage.selection = layersToSelect
  275.     } else {
  276.         figma.currentPage.selection = [layersToSelect[0]]
  277.     }
  278.     for (layer of layersToSelect) {
  279.         let layerStatus = layersToSelectSatuses[layer.id]
  280.         node = figma.getNodeById(layer.id)
  281.         node.expanded = layerStatus
  282.     }
  283. }
  284.  
  285. const getPrevLayer = (parentChildren, previousLayer, event) => {
  286.     layerToSelect = [parentChildren[previousLayer]]
  287.     layersToSelect = layerToSelect.concat(figma.currentPage.selection)
  288.     l(layersToSelect)
  289.     let layersToSelectSatuses = {}
  290.     for (layer of layersToSelect) {
  291.         let layerStatus = layer.expanded
  292.         layersToSelectSatuses[layer.id] = layerStatus
  293.     }
  294.     if (event.altKey) {
  295.         figma.currentPage.selection = layersToSelect
  296.     } else {
  297.         figma.currentPage.selection = [layersToSelect[0]]
  298.     }
  299.     for (layer of layersToSelect) {
  300.         let layerStatus = layersToSelectSatuses[layer.id]
  301.         node = figma.getNodeById(layer.id)
  302.         node.expanded = layerStatus
  303.     }
  304. }
  305.  
  306.  
  307. // const getPrevLayer = (parentChildren, previousLayer, event) => {
  308. //  layerToSelect = [parentChildren[previousLayer]]
  309. //  layersToSelect = figma.currentPage.selection.concat(layerToSelect)
  310. //  let layersToSelectSatuses = {}
  311. //  for (layer of layersToSelect) {
  312. //      let layerStatus = layer.expanded
  313. //      layersToSelectSatuses[layer.id] = layerStatus
  314. //  }
  315. //  if (event.altKey) {
  316. //      figma.currentPage.selection = layersToSelect
  317. //  } else {
  318. //      figma.currentPage.selection = [layersToSelect[0]]
  319. //  }
  320. //  for (layer of layersToSelect) {
  321. //      let layerStatus = layersToSelectSatuses[layer.id]
  322. //      node = figma.getNodeById(layer.id)
  323. //      node.expanded = layerStatus
  324. //  }
  325. // }
  326.  
  327. const getLayer = (order="next", event) => {
  328.     selection = figma.currentPage.selection
  329.     if (order == "next") {
  330.         selection = selection[0]
  331.     } else {
  332.         selection = selection[selection.length-1]
  333.     }
  334.     parent = selection.parent
  335.     parentChildren = parent.children
  336.     selectionId = selection.id
  337.  
  338.     orderOfSelectedLayerInGroup = 0
  339.     for (let x = 0; x<=parentChildren.length; x++) {
  340.         if (parentChildren[x].id == selectionId) {
  341.             break
  342.         }
  343.         orderOfSelectedLayerInGroup += 1
  344.     }
  345.     nextLayer = orderOfSelectedLayerInGroup - 1
  346.     previousLayer = orderOfSelectedLayerInGroup + 1
  347.  
  348.     if (order == "next") {
  349.         getNextLayer(parentChildren, nextLayer, event)
  350.     } else {
  351.         getPrevLayer(parentChildren, previousLayer, event)
  352.     }
  353. }
  354.  
  355. const revertFixedHeightTextLayer = async(currentlySelectedLayers) => {
  356.     for (let x=0; x<currentlySelectedLayers.length; x++) {
  357.         currentlySelectedLayer = currentlySelectedLayers[x]
  358.         if (currentlySelectedLayer.type == "TEXT") {
  359.             await figma.loadFontAsync(currentlySelectedLayer.fontName)
  360.             textAutoResize = localStorage.getItem(currentlySelectedLayer.id);
  361.             currentlySelectedLayer.textAutoResize = textAutoResize
  362.         }
  363.     }
  364. }
  365.  
  366. const saveTextLayerProperty = async(currentlySelectedLayers, event) => {
  367.     for (let x=0; x<currentlySelectedLayers.length; x++) {
  368.         currentlySelectedLayer = currentlySelectedLayers[x]
  369.         if (currentlySelectedLayer.type == "TEXT") {
  370.             await figma.loadFontAsync(currentlySelectedLayer.fontName)
  371.             localStorage.setItem(currentlySelectedLayer.id, currentlySelectedLayer.textAutoResize);
  372.         }
  373.     }
  374. }
  375.  
  376. const resetVerticalAlignment = () => {
  377.     selected()[0].textAlignVertical = "TOP"
  378. }
  379.  
  380. const fixPositionOfLayerWhichWasTakenOutOfGroup = (previousProperties) => {
  381.     fSelected().x = previousProperties.parent.x + previousProperties.x
  382.     fSelected().y = previousProperties.parent.y + previousProperties.y
  383. }
  384.  
  385. const getOutLayerOfTheGroup = () => {
  386.     layerToGetOut = figma.getNodeById(selected()[0].id)
  387.     layers = layerToGetOut.parent.parent.children
  388.     ids = layers.map(layer => layer.id)
  389.     layerIndex = ids.indexOf(layerToGetOut.parent.id)
  390.     layerToGetOut.parent.parent.insertChild(layerIndex+1, layerToGetOut)
  391. }
  392.  
  393. const pasteY = (rect) => {
  394.     rectSmall = selected()[0]
  395.     rectSmall.y = rect.y + rect.height + 144
  396.     rectSmall.x = rect.x
  397. }
  398.  
  399. const align = () => {
  400.     previouslySelected = selected()[0]
  401.     let focusSwitched = setInterval(function() {
  402.        if (previouslySelected.id != selected()[0].id) {
  403.           pasteY(previouslySelected)
  404.           clearInterval(focusSwitched);
  405.        }
  406.     }, 100); // check every 100ms
  407. }
  408.  
  409. const copyPastePosition = () => {
  410.     positions = localStorage.getItem('positions')
  411.     if (positions && positions != null) {
  412.         positions = JSON.parse(positions)
  413.         selected()[0].x = positions.x
  414.         selected()[0].y = positions.y
  415.         localStorage.removeItem('positions')
  416.     } else {
  417.         x = selected()[0].x
  418.         y = selected()[0].y
  419.         let xy = {"x": x, "y": y}
  420.         positions = JSON.stringify(xy)
  421.         localStorage.setItem('positions', positions)
  422.     }
  423. }
  424.  
  425.  
  426. document.addEventListener('keydown', function(event) {
  427.   if (event.ctrlKey && event.key === 't') {
  428.     resetVerticalAlignment()
  429.   }
  430. });
  431.  
  432. document.addEventListener('keydown', function(event) {
  433.   if (event.ctrlKey && event.key != 'ArrowDown' && event.key != 'ArrowUp' && event.key != 'ArrowLeft') {
  434.     let currentlySelectedLayers = figma.currentPage.selection
  435.     saveTextLayerProperty(currentlySelectedLayers, event)
  436.   }
  437. });
  438.  
  439. document.addEventListener('keydown', function(event) {
  440.   if (event.ctrlKey && event.key === 'ArrowLeft') {
  441.     let currentlySelectedLayers = figma.currentPage.selection
  442.     revertResize(currentlySelectedLayers, "+")
  443.     collapseParentOf(currentlySelectedLayers[0])
  444.     revertFixedHeightTextLayer(currentlySelectedLayers)
  445.   }
  446. });
  447.  
  448. document.addEventListener('keydown', function(event) {
  449.   if (event.shiftKey && event.key === 'Ç') {
  450.     ToggleCurrentLayerCollapsion()
  451.   }
  452. });
  453.  
  454. document.addEventListener('keydown', function(event) {
  455.   if (event.ctrlKey && event.key === 'ArrowRight') {
  456.     let currentlySelectedLayers = figma.currentPage.selection
  457.     revertResize(currentlySelectedLayers, "-")
  458.     selectFirstLayerInGroup()
  459.   }
  460. });
  461.  
  462. document.addEventListener('keydown', function(event) {
  463.   if (event.shiftKey && event.altKey && event.key === 'ˇ') {
  464.     toggleTextBoundBox()
  465.   }
  466. });
  467.  
  468. document.addEventListener('keydown', function(event) {
  469.   if (event.ctrlKey && event.key === 'ArrowUp') {
  470.     let currentlySelectedLayers = figma.currentPage.selection
  471.     revertResize(currentlySelectedLayers, "+", horizontalOrVerical="vertical")
  472.     getLayer("prev", event)
  473.     revertFixedHeightTextLayer(currentlySelectedLayers)
  474.   }
  475. });
  476.  
  477. document.addEventListener('keydown', function(event) {
  478.   if (event.ctrlKey && event.key === 'ArrowDown') {
  479.     let currentlySelectedLayers = figma.currentPage.selection
  480.     revertResize(currentlySelectedLayers, "-", horizontalOrVerical="vertical")
  481.     getLayer("next", event)
  482.     revertFixedHeightTextLayer(currentlySelectedLayers)
  483.     event.stopPropagation()
  484.   }
  485. });
  486.  
  487. document.addEventListener('keyup', function(event) {
  488.   if (event.key === 'Enter') {
  489.     let layer = figma.currentPage.selection[0]
  490.     if (layer.name == "bg") {
  491.         layer.name = "Background"
  492.     }
  493.   }
  494. });
  495.  
  496. document.addEventListener('keydown', function(event) {
  497.   if (event.ctrlKey && event.key === 'a') {
  498.     align()
  499.   }
  500. });
  501.  
  502. document.addEventListener('keydown', function(event) {
  503.   if (event.shiftKey && event.key === 'G') {
  504.     if (doublePressed(event)) {
  505.         // previousProperties = {x: fSelected().x, y: fSelected().y, parent: fSelected().parent}
  506.         getOutLayerOfTheGroup()
  507.         // fixPositionOfLayerWhichWasTakenOutOfGroup(previousProperties)
  508.     }
  509.   }
  510. });
  511.  
  512. document.addEventListener('keydown', function(event) {
  513.   if (event.shiftKey && event.key === '~') {
  514.     copyPastePosition()
  515.   }
  516. });
  517.  
  518.  
  519. const exportImageAsync = async(layer) => {
  520.     return await layer.exportAsync({format: "PNG", constraint: { type: "SCALE", value: 4 }})
  521. }
  522.  
  523. const sendNotification = async(message, hideAfterSeconds=1000) => {
  524.     let notification = document.createElement("p")
  525.     notification.innerText = message
  526.     notification.style.textAlign = "center"
  527.     notification.style.padding = "0px 0 0px 0"
  528.     notification.style.zIndex = "100"
  529.     notification.style.position = 'fixed'
  530.     notification.style.width = '0%'
  531.     notification.style.height = '48px'
  532.     notification.style.lineHeight = '48px'
  533.     notification.style.color = 'white'
  534.     notification.style.background = 'blue'
  535.     notification.style.overflow = 'hidden'
  536.     notification.style.left = '50%'
  537.     notification.style.transform = 'translateX(-50%)'
  538.     notification.style.fontFamily = 'Roboto'
  539.     notification.classList.add('notificationCustom')
  540.    
  541.     let parent = document.getElementById("fullscreen-body")
  542.     parent.insertBefore(notification, parent.firstChild);
  543.     await sleep(hideAfterSeconds);
  544.     notification.remove()
  545. }
  546.  
  547. const copyImage = async() => {
  548.    
  549.     const image = await exportImageAsync(fSelected())
  550.     const blob = new Blob([image.buffer], { type: 'image/png' })
  551.     const clipimage = new ClipboardItem({
  552.         'image/png': blob
  553.     })
  554.     navigator.clipboard.write([clipimage])
  555.     figma.notify("Image copied to clipboard :)")
  556. }
  557.  
  558. const downloadImage = async() => {
  559.     for ( layer of selected() ) {
  560.         const image = await exportImageAsync(layer)
  561.    
  562.         const link = document.createElement( 'a' );
  563.         link.style.display = 'none';
  564.         document.body.appendChild( link );
  565.    
  566.    
  567.         const blob = new Blob( [ image ], { type: 'text/plain' } );
  568.         const objectURL = URL.createObjectURL( blob );
  569.          
  570.         link.href = objectURL;
  571.         link.href = URL.createObjectURL( blob );
  572.         fileName = `${layer.name}.png`
  573.         link.download =  fileName;
  574.         link.click();
  575.        
  576.         const data = [new ClipboardItem({ [blob.type]: blob })]
  577.         await navigator.clipboard.write(data)
  578.     }
  579. }
  580.  
  581. document.addEventListener('keydown', function(event) {
  582.   if (event.shiftKey && event.ctrlKey &&  event.key === 'E') {
  583.     downloadImage()
  584.   }
  585. });
  586.  
  587. document.addEventListener('keydown', function(event) {
  588.   if (event.ctrlKey && event.altKey && event.which === 69) {
  589.     copyImage()
  590.   }
  591. });
  592.  
  593.  
  594.  
  595.  
  596. const markApproved = () => {
  597.     layer = selected()[0]
  598.     if (layer.name.includes("✅✅ ")) {
  599.         layer.name = layer.name.replace("✅✅ ", "")
  600.     } else if (layer.name.charAt(0) == "✅") {
  601.         layer.name = "✅" + layer.name
  602.     } else {
  603.         layer.name = "✅ " + layer.name
  604.     }
  605. }
  606.  
  607. document.addEventListener('keydown', function(event) {
  608.   if (event.shiftKey && event.key === ' ') {
  609.     markApproved()
  610.   }
  611. });
  612.  
  613.  
  614.  
  615.  
  616.  
  617.  
  618.  
  619. const saveFgLayer = () => {
  620.     fgLayer = fSelected()
  621. }
  622.  
  623. const pasteSelectedLayerOverCopiedLayer = () => {
  624.     bgLayer = fSelected()
  625.     bgLayer.parent
  626.     bgParentChildren = bgLayer.parent.children
  627.      
  628.     orderOfSelectedLayerInGroup = 0
  629.     for (let x = 0; x<bgParentChildren.length; x++) {
  630.         l(bgParentChildren[x])
  631.         if (bgParentChildren[x].id == bgLayer.id) {
  632.             break
  633.         }
  634.         orderOfSelectedLayerInGroup += 1
  635.     }
  636.    
  637.     bgLayer.parent.insertChild(orderOfSelectedLayerInGroup+1, fgLayer)
  638.     figma.currentPage.selection = [fgLayer]
  639. }
  640.  
  641. document.addEventListener('keydown', function(event) {
  642.   if (event.altKey && event.shiftKey && event.key === 'Ç') {
  643.     l("layerindexcopied")
  644.     saveFgLayer()
  645.   }
  646. });
  647. document.addEventListener('keydown', function(event) {
  648.   if (event.altKey && event.shiftKey && event.key === '◊') {
  649.     l("layerindexpasted")
  650.     pasteSelectedLayerOverCopiedLayer()
  651.   }
  652. });
  653.  
  654.  
  655.  
  656. const increaseSpace = () => {
  657.     let selection = selected()
  658.     selection = [].concat(selection)
  659.     selection.sort(function(a, b) {return a.x - b.x})
  660.  
  661.     let addBy = 1
  662.  
  663.     for (let layer = 1; layer < selection.length; layer++) {
  664.         l(selection[layer].name)
  665.         selection[layer].x = selection[layer].x + addBy
  666.         addBy += 1
  667.     }
  668. }
  669.  
  670. const decreaseSpace = () => {
  671.     let selection = selected()
  672.     selection = [].concat(selection)
  673.     selection.sort(function(a, b) {return a.x - b.x})
  674.  
  675.     let subtractBy = 1
  676.  
  677.     for (let layer = 1; layer < selection.length; layer++) {
  678.         l(selection[layer].name)
  679.         selection[layer].x = selection[layer].x - subtractBy
  680.         subtractBy += 1
  681.     }
  682. }
  683.  
  684. const increaseSpaceVertical = () => {
  685.     let selection = selected()
  686.     selection = [].concat(selection)
  687.     selection.sort(function(a, b) {return a.y - b.y})
  688.  
  689.     let subtractBy = 1
  690.  
  691.     for (let layer = 1; layer < selection.length; layer++) {
  692.         l(selection[layer].name)
  693.         selection[layer].y = selection[layer].y + subtractBy
  694.         subtractBy += 1
  695.     }
  696. }
  697.  
  698. const decreaseSpaceVertical = () => {
  699.     let selection = selected()
  700.     selection = [].concat(selection)
  701.     selection.sort(function(a, b) {return a.y - b.y})
  702.  
  703.     let subtractBy = 1
  704.  
  705.     for (let layer = 1; layer < selection.length; layer++) {
  706.         l(selection[layer].name)
  707.         selection[layer].y = selection[layer].y - subtractBy
  708.         subtractBy += 1
  709.     }
  710. }
  711.  
  712.  
  713. document.addEventListener('keydown', function(event) {
  714.   if (event.altKey && event.key === '≠') {
  715.     increaseSpace()
  716.   }
  717.   else if (event.altKey && event.key === '–') {
  718.     decreaseSpace()
  719.   }
  720.   else if (event.altKey && event.key === '‘') {
  721.     increaseSpaceVertical()
  722.   }
  723.   else if (event.altKey && event.key === '“') {
  724.     decreaseSpaceVertical()
  725.   }
  726. });
  727.  
  728.  
  729. // document.addEventListener('keydown', function(event) {
  730. //  if (event.ctrlKey && event.key === 'u') {
  731. //      const layer = figma.union(selected(), fSelected().parent)
  732. //      figma.currentPage.selection = [layer]
  733. //  } else if (event.ctrlKey && event.key === 's') {
  734. //      const layer = figma.subtract(selected(), fSelected().parent)
  735. //      figma.currentPage.selection = [layer]
  736. //  }
  737. // })
  738.  
  739.  
  740.  
  741. document.addEventListener('keydown', function(event) {
  742.     if (!(event.ctrlKey)) return
  743.     const booleanOperations = {u: figma.union, s: figma.subtract}
  744.     if (!(Object.keys(booleanOperations).includes(event.key))) return
  745.     let operation = booleanOperations[event.key]
  746.     let layer = operation(selected(), fSelected().parent)
  747.     figma.currentPage.selection = [layer]
  748. })
  749.  
  750.  
  751.  
  752.  
  753.  
  754.  
  755.  
  756. // document.addEventListener('keydown', function(event) {
  757. //  const operatorsDecimal = {
  758. //      x: {
  759. //          'ArrowRight': function() { return fSelected().x - 0.9 },
  760. //          'ArrowLeft': function() { return fSelected().x + 0.9 }
  761. //      },
  762. //      y: {
  763. //          'ArrowUp': function() { return fSelected().y - 0.9 },
  764. //          'ArrowDown': function() { return fSelected().y + 0.9 },
  765. //      }
  766. //  }
  767. //  if (!event.altKey) return
  768. //  fSelected().x = operatorsDecimal.x[event.key]()
  769. //  fSelected().y = operatorsDecimal.y[event.key]()
  770. // });
  771.  
  772.  
  773.  
  774.  
  775.  
  776. // document.addEventListener('keydown', function(event) {
  777. //  if (event.shiftKey) return
  778. //  const operatorsDecimal = {
  779. //      x: {
  780. //          'ArrowRight': function() { return Math.round(fSelected().x * 10)/10 - 0.9 },
  781. //          'ArrowLeft': function() { return Math.round(fSelected().x * 10)/10 + 0.9 }
  782. //      },
  783. //      y: {
  784. //          'ArrowUp': function() { return Math.round(fSelected().y * 10)/10 + 0.9 },
  785. //          'ArrowDown': function() { return Math.round(fSelected().y * 10)/10 - 0.9 },
  786. //      }
  787. //  }
  788. //  for (let i of Object.keys(operatorsDecimal)) {
  789. //      if (!(event.altKey && event.ctrlKey && Object.keys(operatorsDecimal[i]).includes(event.key))) continue
  790. //      if (Object.keys(operatorsDecimal[i]).includes(event.key)){
  791. //          fSelected()[i] = operatorsDecimal[i][event.key]()
  792. //      }
  793. //  }
  794. // });
  795.  
  796.  
  797.  
  798.  
  799.  
  800.  
  801.  
  802. let previouslySelected = null
  803. previouslySelectedArray = []
  804. previouslySelectedArrayLastTen = []
  805.  
  806. let focusSwitched = setInterval(function() {
  807.     if (fSelected() == undefined) return
  808.     if (previouslySelected == null) {
  809.         previouslySelected = fSelected()
  810.     }
  811.  
  812.    if (previouslySelected.id != fSelected().id) {
  813.       previouslySelected = fSelected()
  814.    }
  815.     currentlySelected = selected().map(el => el.id).toString()
  816.     wasPreviouslySelected = previouslySelectedArray.map(el => el.id).toString()
  817.     if (currentlySelected == wasPreviouslySelected) return
  818.     previouslySelectedArray = selected()
  819.     if (fSelected().parent.id != '638:3349') {
  820.         previouslySelectedArrayLastTen.push(...previouslySelectedArray)
  821.         if (previouslySelectedArrayLastTen.length > 10) {
  822.             previouslySelectedArrayLastTen = previouslySelectedArrayLastTen.slice(Math.max(previouslySelectedArrayLastTen.length - 10, 0))
  823.         }
  824.     }
  825.     l("changed")
  826. }, 100); // check every 100ms
  827.  
  828.  
  829.  
  830. const getBottomLayerOfArchive = () => {
  831.     archive = new Archive().page
  832.     children = [ ...archive.children]
  833.     children.sort(function(a, b) {return a.y - b.y})
  834.     bottomLayer = children.slice(-1)[0]
  835.     return bottomLayer
  836. }
  837.  
  838. const getRightLayerOfArchive = () => {
  839.     archive = new Archive().page
  840.     children = [ ...archive.children]
  841.     children.sort(function(a, b) {return a.x - b.x})
  842.     rightLayer = children.slice(-1)[0]
  843.     return rightLayer
  844. }
  845.  
  846. const getDateFromStr = (str) => {
  847.     str = str.split("|").slice(-1)[0].split(" ").filter(el => el != "")
  848.     let dateLayer = str[0]
  849.     return dateLayer
  850. }
  851.  
  852. const dateOfBottomLayerIsDifferent = () => {
  853.     let dateAndTimeLayer = getRightLayerOfArchive().name
  854.     let dateLayer = getDateFromStr(dateAndTimeLayer)
  855.     let currentDate = getDateFromStr(getStrDate())
  856.     return !( [currentDate, dateLayer].every((val, i, arr) => val == arr[0]) )
  857. }
  858.  
  859. const getFurthestXLayerX = (layers) => {
  860.     let biggestXLayerValue = Number.NEGATIVE_INFINITY
  861.     let biggestXLayer = null
  862.     for (const layer of layers) {
  863.         if ( layer.x > biggestXLayerValue ) {
  864.             biggestXLayerValue = layer.x
  865.             biggestXLayer = layer
  866.         }
  867.     }
  868.     return biggestXLayer.x
  869. }
  870.  
  871. const getXCoordToPutNewDayLayer = () => {
  872.     const dateAndTimeLayer = getRightLayerOfArchive()
  873.     const layers = archive.findAll(
  874.         layer => layer.name.includes(
  875.             getDateFromStr(dateAndTimeLayer.name)
  876.         )
  877.     )
  878.     const widths = layers.map(layer => layer.width)
  879.     const maxWidth = Math.max(...widths)
  880.     const furthestXLayerX = getFurthestXLayerX(layers)
  881.     return furthestXLayerX + maxWidth + 500
  882. }
  883.  
  884.  
  885. document.addEventListener("keydown", function(event) {
  886.     if (event.which == 8 && event.shiftKey && event.altKey) {
  887.         if (
  888.             // selected().length && selected().map((el) => el.type).every( (val, i, arr) => {l(val); return val === arr[0] && (val == "FRAME" && arr[0] == "FRAME")})
  889.             selected().length
  890.         ) {
  891.                 const archive = new Archive
  892.                  for (layer of selected()) {
  893.                     layer.name = layer.name + " | " + getStrDate()
  894.                     rightLayer = getRightLayerOfArchive()
  895.                     if (dateOfBottomLayerIsDifferent() ) {
  896.                         archive.page.appendChild(layer)
  897.                         layer.x = getXCoordToPutNewDayLayer()
  898.                         layer.y = 5915
  899.                     } else {
  900.                         archive.page.appendChild(layer)
  901.                         layer.x = rightLayer.x
  902.                         layer.y = rightLayer.y + rightLayer.height + 200
  903.                     }
  904.                  }
  905.                 archive.removePlaceholder()
  906.                 /*^ in case there were no layers in archive */
  907.                 figma.currentPage.selection = []
  908.      
  909.         }
  910.         }
  911. });
  912.  
  913.  
  914.  
  915. // let dateTimeWorkdayIsFinished = new Date('September 17, 2021 00:36:00');
  916. // let timeLeft = new Date( dateTimeWorkdayIsFinished - Date.now()).toISOString().substr(11, 8)
  917. // document.title = timeLeft
  918.  
  919.  
  920. let timeLeftToEndWorkday = setInterval(function() {
  921.     let dateTimeWorkdayIsFinished = new Date('September 18, 2021 01:17:00');
  922.     if (dateTimeWorkdayIsFinished - Date.now() < 0) {
  923.         return
  924.     }
  925.     let timeLeft = new Date( dateTimeWorkdayIsFinished - Date.now()).toISOString().substr(11, 8)
  926.     document.title = timeLeft
  927. }, 1000)
  928.  
  929.  
  930.  
  931. const layerInCurrentPage = (layer) => {
  932.     if (!(layer)) return
  933.     layer = figma.currentPage.findAll(l => l.id === layer.id)
  934.     return Boolean(layer.length)
  935. }
  936.  
  937. // while
  938.  
  939.  
  940. // figmaIsLoaded = () => {
  941. //  try {
  942. //      figma
  943. //      return true
  944. //  } catch {
  945. //      return false
  946. //  }
  947. // }
  948.  
  949. // while (true) {
  950. //  if ( figmaIsLoaded() ) {
  951. //      Object.prototype.select = function() {figma.currentPage.selection = [this]}
  952. //  }
  953. // }
  954.  
  955.  
  956.  
  957.  
  958. // document.addEventListener('keydown', function(event) {
  959. //  if (!(event.ctrlKey && event.key === 'Enter')) return
  960. //  for (layer of previouslySelectedArray.reverse()) {
  961. //      if (layerInCurrentPage(layer)) {
  962. //          figma.currentPage.
  963. //      }
  964. //  }
  965. // })
  966.  
  967.  
  968.  
  969.  
  970.  
  971.  
  972. const isSpeacialCharAndNotNumber = (inputString) => {
  973.     return inputString
  974.            .match(/^[^a-zA-Z]+$/)
  975.            ? true : false
  976. }
  977.  
  978.  
  979. const enumerate = (array) => {
  980.     return array.map((item, index) => [index, item])
  981. }
  982.  
  983.  
  984. const insertAfterFirsItemOfArray = (array, value) => {
  985.     const newArray = [
  986.         array[0], value, ...array.slice(1)
  987.     ]
  988.     return newArray
  989. }
  990.  
  991.  
  992. const fakeTranslateReplacementForWord = (charObject) => {
  993.     if (charObject.isSpecialOrNumber) {
  994.         return charObject.char
  995.     } else {
  996.         return charObject.fakeTranslateReplacement
  997.     }
  998. }
  999.  
  1000. const defineCharToAdd = (wordObject) => {
  1001.     if (wordObject.isAllUpper) return "P"
  1002.     return "v"
  1003. }
  1004.  
  1005.  
  1006. const fakeTranslateReplacementForStr = (wordObject) => {
  1007.     let word
  1008.  
  1009.     if (wordObject.wholeWordIsSpecialCharOrNumber) {
  1010.         word = wordObject.fakeTranslateReplacement
  1011.         word = word.join("")
  1012.         return word
  1013.     }
  1014.  
  1015.     const fakeTranslateReplacement = wordObject.fakeTranslateReplacement
  1016.  
  1017.     let amountCharsToAdd = 12 - wordObject.length.nonSpecial
  1018.     if (amountCharsToAdd < 0) amountCharsToAdd = 0
  1019.    
  1020.     const charToAdd = defineCharToAdd(wordObject)
  1021.     const charsToAdd = charToAdd.repeat(amountCharsToAdd)
  1022.  
  1023.     word = insertAfterFirsItemOfArray(fakeTranslateReplacement, charsToAdd)
  1024.     word = word.join("")
  1025.     return word
  1026. }
  1027.  
  1028.  
  1029. const convertStrToStrObject = (inputString) => {
  1030.  
  1031.  
  1032.     const strObject = {}
  1033.     strObject.string = inputString
  1034.     strObject.fakeTranslateReplacement = ""
  1035.  
  1036.     const words = inputString.split(" ")
  1037.     const wordObjects = []
  1038.  
  1039.  
  1040.     for (let [wordOrder, word] of enumerate(words)) {
  1041.         const wordObject = {}
  1042.  
  1043.         wordObject.word = word
  1044.         wordObject.fakeTranslateReplacement = []
  1045.         wordObject.specialCharInWord = false
  1046.         wordObject.isLast = wordOrder == words.length-1
  1047.         wordObject.isAllUpper = false
  1048.         wordObject.wholeWordIsSpecialCharOrNumber = false
  1049.  
  1050.         wordObject.length = {}
  1051.         wordObject.length.total = word.length
  1052.         wordObject.length.nonSpecial = 0
  1053.         wordObject.length.special = 0
  1054.  
  1055.         wordObject.chars = []
  1056.        
  1057.         word = Array.from(word)
  1058.         for (const [charOrder, char] of enumerate(word)) {
  1059.             const speacialChar = isSpeacialCharAndNotNumber(char)
  1060.             wordObject.length.nonSpecial += ( () => !speacialChar ? 1 : 0 )()
  1061.             wordObject.length.special += ( () => speacialChar ? 1 : 0 )()
  1062.             wordObject.specialCharInWord = speacialChar
  1063.             strObject.specialCharInStr = speacialChar
  1064.  
  1065.             const charObject = {}
  1066.             charObject.char = char
  1067.             charObject.fakeTranslateReplacement = ""
  1068.             charObject.isSpecialOrNumber = speacialChar
  1069.             charObject.isLast = charOrder == word.length-1
  1070.             charObject.isUpper = char == char.toUpperCase()
  1071.             charObject.fakeTranslateReplacement = charObject.isUpper ? "P" : "v"
  1072.             charObject.charOrder = charOrder
  1073.  
  1074.             wordObject.chars.push(charObject)
  1075.         }
  1076.  
  1077.         wordObject.fakeTranslateReplacement = wordObject.chars.map(
  1078.             charObject => (fakeTranslateReplacementForWord(charObject))
  1079.         )
  1080.  
  1081.         wordObject.isAllUpper = (
  1082.             wordObject.chars
  1083.             .every(char => char.isUpper)
  1084.         )
  1085.  
  1086.         wordObject.wholeWordIsSpecialCharOrNumber = (
  1087.             wordObject.chars
  1088.             .every(char => char.isSpecialOrNumber)
  1089.         )
  1090.  
  1091.         wordObjects.push(wordObject)
  1092.     }
  1093.  
  1094.     strObject.wordObjects = wordObjects
  1095.  
  1096.     let strFakeTranslateReplacement = strObject.wordObjects.map(
  1097.         word => ( fakeTranslateReplacementForStr(word) )
  1098.     )
  1099.     strFakeTranslateReplacement = strFakeTranslateReplacement.join(" ")
  1100.     strObject.fakeTranslateReplacement = strFakeTranslateReplacement
  1101.  
  1102.     return strObject
  1103. }
  1104.  
  1105.  
  1106. const fakeTranslate = async() => {
  1107.  
  1108.     await figma.loadFontAsync( fSelected().fontName )
  1109.     const layersText = fSelected().characters
  1110.    
  1111.     const StrObject = convertStrToStrObject(layersText)
  1112.    
  1113.     fSelected().name = layersText
  1114.     fSelected().characters = StrObject.fakeTranslateReplacement
  1115. }
  1116.  
  1117.  
  1118.  
  1119.  
  1120.  
  1121. const revertTranslate = async() => {
  1122.    
  1123.     await figma.loadFontAsync( fSelected().fontName )
  1124.     fSelected().characters = fSelected().name
  1125. }
  1126.  
  1127.  
  1128.  
  1129.  
  1130.  
  1131.  
  1132.  
  1133.  
  1134. document.addEventListener('keydown', function(event) {
  1135.     /* option + shift + L */
  1136.   if (event.shiftKey && event.altKey && event.which === 76) {
  1137.     l("FAKE traaaaanslate")
  1138.     fakeTranslate()
  1139.   }
  1140. });
  1141.  
  1142.  
  1143. document.addEventListener('keydown', function(event) {
  1144.   if (event.shiftKey && event.altKey && event.key === '') {
  1145.     revertTranslate()
  1146.   }
  1147. });
  1148.  
  1149.  
  1150.  
  1151. const collapseAllCollapsableLayers = () => {
  1152.     const page = figma.currentPage
  1153.     const filterFunction = (layer) => {
  1154.         return layer.expanded != undefined
  1155.     }
  1156.     const collapsableLayers = page.findAll(filterFunction)
  1157.     for (const layer of collapsableLayers) {
  1158.         layer.expanded = false
  1159.     }
  1160. }
  1161.  
  1162. const controlOptionC = {
  1163.     get pressed() {
  1164.         return (
  1165.             event.which == 67 &&
  1166.             event.altKey &&
  1167.             event.ctrlKey
  1168.         )
  1169.     }
  1170. }
  1171.  
  1172.  
  1173. document.addEventListener('keydown', function(event){
  1174.     if (controlOptionC.pressed) {
  1175.         collapseAllCollapsableLayers()
  1176.     }
  1177. })
  1178.  
  1179.  
  1180.  
  1181.  
  1182.  
  1183.  
  1184.  
  1185.  
  1186.  
  1187.  
  1188.  
  1189.  
  1190.  
  1191.  
  1192. const getElementsByPartialClassName = (part) => {
  1193.     return document.querySelectorAll(`[class*=${part}]`)
  1194. }
  1195.  
  1196.  
  1197. const updateSelectedItemsCounter = (cls='selectedCounter') => {
  1198.     setInterval(function(){
  1199.         try {
  1200.         const counter = document.querySelector(`.${cls}`)
  1201.         counter.innerText = figma.currentPage.selection.length
  1202.         } catch {}
  1203.     }, 100)
  1204. }
  1205.  
  1206.  
  1207. const addCounterToToolBar = (
  1208.     cls='selectedCounter',
  1209.     innerText="Selected",
  1210.     width="100px"
  1211. ) => {
  1212.     const counterShell = document.createElement('div')
  1213.    
  1214.     counterShell.style.width = width
  1215.     counterShell.style.background = "black"
  1216.     counterShell.style.padding = "10px 10px 10px 0px"
  1217.     counterShell.style.textAlign = "right"
  1218.     counterShell.style.borderRadius = "6px"
  1219.     counterShell.style.marginRight = "6px"
  1220.     counterShell.style.position = "relative"
  1221.    
  1222.     const counterText = document.createElement('span')
  1223.     counterText.classList.add(cls)
  1224.     try {
  1225.         counterText.innerText = figma.currentPage.selection.length
  1226.     } catch {
  1227.         counterText.innerText = "0"
  1228.     }
  1229.    
  1230.     const infoText = document.createElement('span')
  1231.     infoText.innerText = innerText
  1232.     infoText.style.position = "absolute"
  1233.     infoText.style.left = "10px"
  1234.     infoText.style.color = "#bbbbbb"
  1235.    
  1236.     counterShell.appendChild(counterText)
  1237.     counterShell.appendChild(infoText)
  1238.     toolBar = getElementsByPartialClassName('toolbar_view--sideButtonGroup')[1]
  1239.     toolBar.appendChild(counterShell)
  1240.    
  1241.     updateSelectedItemsCounter()
  1242.  
  1243. }
  1244.  
  1245.  
  1246.  
  1247. document.addEventListener('keydown', async function(event){
  1248.     if (!(event.metaKey && event.which == 190)) return
  1249.     await sleep(100)
  1250.     addCounterToToolBar()
  1251. })
  1252.  
  1253.  
  1254. const shiftAsterisk = {
  1255.     get pressed() {
  1256.         return (
  1257.             event.which == 192 &&
  1258.             event.shiftKey
  1259.         )
  1260.     }
  1261. }
  1262.  
  1263.  
  1264.  
  1265.  
  1266.  
  1267.  
  1268.  
  1269. function *iterateOverSelected() {
  1270.    
  1271.     addCounterToToolBar(cls='mmessage', innerText='iterated', width="150px")
  1272.     const iteratedCounter = document.querySelector(".mmessage")
  1273.     document.addEventListener('keydown', () => {
  1274.         if (!shiftAsterisk.pressed) return
  1275.         iteratedCounter.parentNode.remove()
  1276.     })
  1277.     let sel
  1278.     let order = 0
  1279.     for (const layer of sel = selected()) {
  1280.         if (order == 0) {
  1281.             console.log(
  1282.                 "document.addEventListener(" +
  1283.                     " 'keydown', function(e) {" +
  1284.                 " if (e.key == \"`\") {" +
  1285.                 " s.next()" +
  1286.                 " }})"
  1287.             )
  1288.         }
  1289.         select([layer])
  1290.         figma.viewport.scrollAndZoomIntoView([layer])
  1291.         order++
  1292.         const message = `${order} / ${sel.length}`
  1293.         console.log(message)
  1294.         iteratedCounter.innerText = message
  1295.         yield layer
  1296.     }
  1297.     return iteratedCounter.parentNode.remove()
  1298. }
  1299.  
  1300.  
  1301.  
  1302.  
  1303.  
  1304. const commandOptionG = {
  1305.     get pressed() {
  1306.         return (
  1307.             event.which == 71 &&
  1308.             event.altKey &&
  1309.             event.metaKey
  1310.         )
  1311.     }
  1312. }
  1313.  
  1314.  
  1315.  
  1316. document.addEventListener('keydown', function(event){
  1317.     if (!commandOptionG.pressed) return
  1318.     if (fSelected().fills.some(fill => fill.visible)) return
  1319.     fSelected().fills = []
  1320.    
  1321. })
  1322.  
  1323.  
  1324.  
  1325.  
  1326.  
  1327.  
  1328.  
  1329.  
  1330.  
  1331.  
  1332.  
  1333. let selectedNodes = ""
  1334.  
  1335. const getFrameToSelect = (arraySwitch) => {
  1336.     const toReturn = arraySwitch ? 1 : 0
  1337.     arraySwitch = !arraySwitch
  1338.     return toReturn
  1339. }
  1340.  
  1341. const switchFrameViews = () => {
  1342.  
  1343.     if (selected().length <= 1) return
  1344.  
  1345.     let arraySwitch
  1346.  
  1347.     if ( selectedNodes != selected().map(e => e.id).join("") ) {
  1348.         arraySwitch = true
  1349.         selectedNodes = selected().map(e => e.id).join("")
  1350.     } else {
  1351.         arraySwitch = false
  1352.         selectedNodes = ""
  1353.     }
  1354.  
  1355.     let frameToSelect = getFrameToSelect(arraySwitch)
  1356.     frameToSelect = selected()[frameToSelect]
  1357.     figma.viewport.scrollAndZoomIntoView([frameToSelect])
  1358.     figma.viewport.zoom = 1
  1359.     return frameToSelect
  1360. }
  1361.  
  1362.  
  1363. document.addEventListener('keydown', (event) => {
  1364.    if (!(event.which == 27 && event.shiftKey)) return
  1365.    switchFrameViews()
  1366. })
  1367.  
  1368.  
  1369.  
  1370.  
  1371.  
  1372.  
  1373. const alignLayersVertically = (verticalSpaceInPixels=200) => {
  1374.     let height = 0
  1375.  
  1376.     const layers = Array.from( selected() ).sort(e => e.y)
  1377.    
  1378.     for (layer of layers) {
  1379.    
  1380.         layer.y = layers[0].y + height
  1381.         height += layer.height + verticalSpaceInPixels
  1382.    
  1383.     }
  1384. }
  1385.  
  1386.  
  1387.  
  1388.  
  1389.  
  1390.  
  1391. const figmaFunctions = {
  1392.  
  1393.     "alignLayersVertically(verticalSpaceInPixels: string = 200)": {
  1394.         "howToUse": [
  1395.             `Select layers i want to align verically
  1396.             with 200px
  1397.             `
  1398.         ],
  1399.         use(verticalSpaceInPixels=200) {
  1400.             alignLayersVertically(verticalSpaceInPixels)
  1401.            
  1402.         }
  1403.     }
  1404.    
  1405. }
  1406.  
  1407.  
  1408.  
  1409.  
  1410.  
  1411.  
  1412. /* Move layers without cursor hold (as in Sketch) start */
  1413.  
  1414. const mousePositions = {
  1415.     initial: {
  1416.         x: null,
  1417.         y: null
  1418.     },
  1419.     end: {
  1420.         x: 0,
  1421.         y: 0
  1422.     }
  1423. }
  1424.  
  1425. const releasedKeys = {
  1426.     Alt: false,
  1427.     Control: false
  1428. }
  1429.  
  1430. let selectedLayers = []
  1431. let selectedLayerXs = []
  1432. let selectedLayerYs = []
  1433.  
  1434. const trackCursorAndMoveLayers = (event) => {
  1435.  
  1436.     if (mousePositions.initial.x == null) {
  1437.         mousePositions.initial.x = event.clientX
  1438.         mousePositions.initial.y = event.clientY
  1439.     }
  1440.  
  1441.     mousePositions.end.x = event.clientX
  1442.     mousePositions.end.y = event.clientY
  1443.  
  1444.     const reduceByX = (mousePositions.initial.x - mousePositions.end.x) * 1 / figma.viewport.zoom
  1445.     const reduceByY = (mousePositions.initial.y - mousePositions.end.y) * 1 / figma.viewport.zoom
  1446.     /*
  1447.         To deal with different scale of the Figma's viewport
  1448.     */
  1449.  
  1450.     for (let selectedLayer = 0; selectedLayer < selectedLayers.length; selectedLayer++) {
  1451.         selectedLayers[selectedLayer].x = Math.round(selectedLayerXs[selectedLayer] - reduceByX)
  1452.         selectedLayers[selectedLayer].y = Math.round(selectedLayerYs[selectedLayer] - reduceByY)
  1453.     }
  1454.  
  1455. }
  1456.  
  1457. const setLayerToMove = (event) => {
  1458.     if (!(event.altKey && event.ctrlKey)) return  // 3 keys are pressed
  1459.     selectedLayers = figma.currentPage.selection
  1460.     if (!selectedLayers.length) return
  1461.  
  1462.     for (let selectedLayer = 0; selectedLayer < selectedLayers.length; selectedLayer++) {
  1463.         selectedLayerXs.push(selectedLayers[selectedLayer].x)
  1464.         selectedLayerYs.push(selectedLayers[selectedLayer].y)
  1465.     }
  1466.    
  1467.     document.addEventListener('mousemove', trackCursorAndMoveLayers )
  1468. }
  1469.  
  1470. const unsetLayerToMove = (event) => {
  1471.     if (!(event.key == 'Alt' || event.key == 'Control')) return
  1472.    
  1473.     releasedKeys[event.key] = true
  1474.  
  1475.     if (!(releasedKeys.Alt == true && releasedKeys.Control == true)) return  // 3 keys are released
  1476.     releasedKeys.Alt = false
  1477.     releasedKeys.Control = false
  1478.  
  1479.     selectedLayers = []
  1480.     selectedLayerXs = []
  1481.     selectedLayerYs = []
  1482.    
  1483.     document.removeEventListener('mousemove', trackCursorAndMoveLayers )
  1484.    
  1485.     mousePositions.initial.x = null
  1486.     mousePositions.initial.y = null
  1487. }
  1488.  
  1489. document.addEventListener('keydown', setLayerToMove )
  1490. document.addEventListener('keyup', unsetLayerToMove )
  1491.  
  1492.  
  1493. /* Move layers without cursor hold (as in Sketch) end */
  1494.  
  1495.  
  1496.  
  1497.  
  1498.  
  1499.  
  1500.  
  1501.  
  1502. let view = {
  1503.     page: null,
  1504.     center: null,
  1505.     zoom: null
  1506. }
  1507.  
  1508. const bookmarkView = () => {
  1509.     view.page = figma.currentPage
  1510.     view.center = figma.viewport.center
  1511.     view.zoom = figma.viewport.zoom
  1512.  
  1513.     sendNotification("View bookmarked")
  1514. }
  1515.  
  1516. const gotoBookmarkedView = () => {
  1517.    
  1518.     if (view.page == null) {
  1519.         sendNotification("Bookmark view first")
  1520.         return
  1521.     }
  1522.    
  1523.     figma.currentPage = view.page
  1524.     figma.viewport.center = view.center
  1525.     figma.viewport.zoom = view.zoom
  1526.  
  1527.     sendNotification("Switched to bookmarked view")
  1528. }
  1529.  
  1530.  
  1531. const pressedKeysForBookmark = {
  1532.     32: false, // space
  1533. }
  1534.  
  1535. const doBookmarkAction = (event) => {
  1536.  
  1537.     if (![32, 66, 71].includes(event.which)) return
  1538.    
  1539.     pressedKeysForBookmark[event.which] = true
  1540.    
  1541.     if (!pressedKeysForBookmark[32]) return
  1542.    
  1543.     switch (event.which) {
  1544.         case 66:
  1545.             bookmarkView()
  1546.             break
  1547.         case 71:
  1548.             gotoBookmarkedView()
  1549.             break
  1550.     }
  1551.  
  1552. }
  1553.  
  1554.  
  1555. const updatePressedKeys = (event) => {
  1556.     if (!(event.which == 32)) return
  1557.     pressedKeysForBookmark[32] = false
  1558. }
  1559.  
  1560. document.addEventListener('keydown', doBookmarkAction )
  1561. document.addEventListener('keyup', updatePressedKeys )
  1562.  
  1563.  
  1564.  
  1565.  
  1566.  
  1567. const keysPressedForBgRename = {
  1568.     66: {  // B
  1569.         isPressed: false,
  1570.         timestamp: Infinity
  1571.     },
  1572.     71: {  // G
  1573.         isPressed: false,
  1574.         timestamp: Infinity
  1575.     },
  1576. }
  1577.  
  1578. const renameToBg = (event) => {
  1579.     if (event.which == 66 || event.which == 71) {
  1580.  
  1581.         keysPressedForBgRename[event.which].isPressed = true
  1582.         keysPressedForBgRename[event.which].timestamp = event.timeStamp
  1583.  
  1584.         if (
  1585.             Object.values(keysPressedForBgRename)
  1586.             .every(v => v.isPressed) &&
  1587.             Math.abs(
  1588.                 keysPressedForBgRename[66].timestamp -
  1589.                 keysPressedForBgRename[71].timestamp
  1590.             ) < 100
  1591.         ) {
  1592.             keysPressedForBgRename[66].isPressed = false
  1593.             keysPressedForBgRename[71].isPressed = false
  1594.            
  1595.             if (
  1596.                 fSelected() &&
  1597.                 ['RECTANGLE', 'ELLIPSE']
  1598.                 .includes(fSelected().type)
  1599.             ) {
  1600.                 fSelected().name = 'Background'
  1601.             }
  1602.         }
  1603.         return
  1604.     }
  1605.     keysPressedForBgRename[66].isPressed = false
  1606.     keysPressedForBgRename[71].isPressed = false
  1607. }
  1608.  
  1609.  
  1610. document.addEventListener('keydown', renameToBg)
  1611.  
  1612.  
  1613.  
  1614.  
Add Comment
Please, Sign In to add comment