My fourth accepted PR on github hacktoberfest
Tags: hacktoberfest
Published: 2021-10-30 00:25:00

Hello every, my name is Dustin. I'd like to talk about my experience of solving another issue on github that are labelled as hacktoberfest 2021. 

## Reasons
The reason behind why I chose this project is so interesting and written completely in Javascript.

## Fourth pull request
My fouth pull request was pretty hard and took me nearly 2 days to finish it.

The project can be found [here](https://github.com/NotWoods/maskable)
My pull request can be found [here](https://github.com/NotWoods/maskable/pull/65)

## Detail
The issue was about using `control z` to undo previous changes. It was quite simple and easy to understand what the project owner is asking but coding is absolutely the opposite. It got me a few hours to finish everything and push it to github, but unfortunately that is not what the project owner is looking for. What I did was that I had an array of history. So each layer will have their own history. If user clicks on a layer, and hit `control z`, I would undo changes on that layer. That also sounded correct to me but it didn't to project owner. His idea was that I had to have 1 history to store every change happening in all layers. 

For example, I change X and then add a new layer, and then change X on that layer. If I `control z` it will change X back to 0, and `control z` again, it will remove the second layer. 

So it means that I had to completely change my code and started again. It took me another few hours to figure it out but I got to say that it's not that much code as I thought. 

Luckily, he also has comments on type so that as beginners who want to contribute to the code can easily understand which one is which.

This is what I have when a key is clicked
```js
document.addEventListener('keydown', (e) => {
  if (e.ctrlKey && e.key === 'z' && history.isAvailableToPop()) {
    let current = history.pop();
    // also delete layer by looping through the history
    // check if there is any current.position in the array
    if (history.isLastOne(current.position)) {
      const layerToDelete = controller.getLayer(current.position);
      if (layerToDelete.locked) return;
      const radio = current.input;
      const sibling = radio.closest('.layer').nextElementSibling;
      /** @type {HTMLInputElement} */
      const nextRadio = sibling.querySelector('input[name="layer"]');
      nextRadio.checked = true;
      selectLayer(layers.get(nextRadio));

      controller.delete(layerToDelete);
      radio.closest('.layer').remove();
      history.decreasePosition();
    } else if (current.position !== history.getLast().position) {
      current = history.getLastOfPosition(current.position);
      const position = current.position;

      selectLayer(current.layer);

      const layer = controller.getLayer(position);

      Object.assign(layer, current.layer);
      cancelAnimationFrame(lastHandle);
      lastHandle = requestAnimationFrame(() => {
        updatePreview(current.input);
        controller.draw(layer);
      });
    } else {
      const position = history.getLast().position;

      selectLayer(history.getLast().layer);

      const layer = controller.getLayer(position);

      Object.assign(layer, history.getLast().layer);
      cancelAnimationFrame(lastHandle);
      lastHandle = requestAnimationFrame(() => {
        updatePreview(history.getLast().input);
        controller.draw(layer);
      });
    }
  }
});
```