Skip to content

Commit

Permalink
Crearting 'View Trash' and more restore option in Musicblocks (#4191)
Browse files Browse the repository at this point in the history
* Creating View Trash option

* creating view trash option

* creating view trash option

* Creating view trash list and more restore options

* Creating view trash list and more restore options

* Creating view trash and more restore options

* create view trash option

* Creating view trash and more restore options

* Creating view trash and more restore options

* Creating view trash and more restore options

* Creating view Trash and more restore options

* Creating view trash and more restore options
  • Loading branch information
subhas-pramanik-09 authored Jan 18, 2025
1 parent 6efdccf commit 39171f4
Show file tree
Hide file tree
Showing 3 changed files with 212 additions and 61 deletions.
66 changes: 66 additions & 0 deletions css/activities.css
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,72 @@
font-size: large;
}

.trash-view {
position: relative;
background-color: white;
max-width: 396px;
max-height: 200px;
overflow-y: auto;
font-size: 16px;
color: black;
border: 2px solid #87cefa;
list-style-type: none;
margin: 0;
padding: 0;
text-align: left;
}

.button-container {
position: sticky;
display: flex;
justify-content: space-between;
top: 0;
z-index: 10;
display: flex;
gap: 10px;
background: #2196F3;
margin: 0;
padding: 5px;
border-bottom: 1px solid #d9d9d9;
}

.trash-item {
padding: 2px 12px;
margin: 1px 0;
border-radius: 4px;
transition: background-color 0.3s;
}

.trash-item.hover {
background-color: #d9d9d9;
}

.trash-item-icon {
width: 30px;
height: 30px;
margin-right: 10px;
vertical-align: middle;
}

#restoreLastIcon, #restoreAllIcon {
display: flex;
align-items: center;
justify-content: center;
width: 48px;
height: 48px;
cursor: pointer;
}


.material-icons.md-48 {
font-size: 32px;
}


.hidden {
display: none;
}

.ui-menu {
position: relative;
background-color: rgba(255, 255, 255, 1);
Expand Down
2 changes: 2 additions & 0 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -780,6 +780,7 @@
>
<a style="color: transparent;">space&nbsp;&nbsp;&nbsp;</a>
</li>

<li>
<a
id="restoreIcon"
Expand All @@ -789,6 +790,7 @@
>restore_from_trash</i
></a
>
<div id="trashList"></div>
</li>
<li>
<a
Expand Down
205 changes: 144 additions & 61 deletions js/activity.js
Original file line number Diff line number Diff line change
Expand Up @@ -3346,91 +3346,89 @@ class Activity {
const restoreTrash = (activity) => {
if (!activity.blocks || !activity.blocks.trashStacks || activity.blocks.trashStacks.length === 0) {
activity.textMsg(
_("Nothing in the trash to restore."),
_("Trash can is empty."),
3000
);
return;
}
activity._restoreTrash();

if (docById("helpfulWheelDiv").style.display !== "none") {
docById("helpfulWheelDiv").style.display = "none";
activity.__tick();
}
};

const restoreTrashPop = (activity) => {
if (!activity.blocks || !activity.blocks.trashStacks || activity.blocks.trashStacks.length === 0) {
activity.textMsg(
_("Trash can is empty."),
3000
);
return;
}
this._restoreTrashById(this.blocks.trashStacks[this.blocks.trashStacks.length - 1]);
activity.textMsg(
_("Item restored from the trash."),
3000
);

if (docById("helpfulWheelDiv").style.display !== "none") {
docById("helpfulWheelDiv").style.display = "none";
activity.__tick();
}
};

}

this._restoreTrash = () => {
this._restoreTrashById = (blockId) => {
const blockIndex = this.blocks.trashStacks.indexOf(blockId);
if (blockIndex === -1) return; // Block not found in trash

this.blocks.trashStacks.splice(blockIndex, 1); // Remove from trash

for (const name in this.palettes.dict) {
this.palettes.dict[name].hideMenu(true);
}

this.blocks.activeBlock = null;
this.refreshCanvas();

const dx = 0;
const dy = -this.cellSize * 3; // Reposition

if (this.blocks.trashStacks.length === 0) {
return;
}

const thisBlock = this.blocks.trashStacks.pop();

// Restore drag group in trash
this.blocks.findDragGroup(thisBlock);

// Restore drag group
this.blocks.findDragGroup(blockId);
for (let b = 0; b < this.blocks.dragGroup.length; b++) {
const blk = this.blocks.dragGroup[b];
this.blocks.blockList[blk].trash = false;
this.blocks.moveBlockRelative(blk, dx, dy);
this.blocks.blockList[blk].show();
}

this.blocks.raiseStackToTop(thisBlock);

if (
this.blocks.blockList[thisBlock].name === "start" ||
this.blocks.blockList[thisBlock].name === "drum"
) {
const turtle = this.blocks.blockList[thisBlock].value;

this.blocks.raiseStackToTop(blockId);
const restoredBlock = this.blocks.blockList[blockId];

if (restoredBlock.name === 'start' || restoredBlock.name === 'drum') {
const turtle = restoredBlock.value;
this.turtles.turtleList[turtle].inTrash = false;
this.turtles.turtleList[turtle].container.visible = true;
} else if (this.blocks.blockList[thisBlock].name === "action") {
// We need to add a palette entry for this action.
// But first we need to ensure we have a unqiue name,
// as the name could have been taken in the interim.
const actionArg = this.blocks.blockList[
this.blocks.blockList[thisBlock].connections[1]
];
} else if (restoredBlock.name === 'action') {
const actionArg = this.blocks.blockList[restoredBlock.connections[1]];
if (actionArg !== null) {
let label;
const oldName = actionArg.value;
// Mark the action block as still being in the
// trash so that its name won't be considered when
// looking for a unique name.
this.blocks.blockList[thisBlock].trash = true;
restoredBlock.trash = true;
const uniqueName = this.blocks.findUniqueActionName(oldName);
this.blocks.blockList[thisBlock].trash = false;
restoredBlock.trash = false;

if (uniqueName !== actionArg) {
actionArg.value = uniqueName;

label = actionArg.value.toString();
if (label.length > 8) {
label = label.substr(0, 7) + "...";
}
label = uniqueName.length > 8 ? uniqueName.substr(0, 7) + '...' : uniqueName;
actionArg.text.text = label;

if (actionArg.label !== null) {
actionArg.label.value = uniqueName;
}

actionArg.container.updateCache();

// Check the drag group to ensure any do blocks are updated (in case of recursion).
for (let b = 0; b < this.blocks.dragGroup.length; b++) {
const me = this.blocks.blockList[this.blocks.dragGroup[b]];
if (
Expand All @@ -3441,11 +3439,7 @@ class Activity {
) {
me.privateData = uniqueName;
me.value = uniqueName;

label = me.value.toString();
if (label.length > 8) {
label = label.substr(0, 7) + "...";
}
label = uniqueName.length > 8 ? uniqueName.substr(0, 7) + '...' : uniqueName;
me.text.text = label;
me.overrideName = label;
me.regenerateArtwork();
Expand All @@ -3455,21 +3449,110 @@ class Activity {
}
}
}

activity.textMsg(
_("Item restored from the trash."),
3000
);

this.refreshCanvas();
};
};

// Add event listener for trash icon click
document.getElementById('restoreIcon').addEventListener('click', () => {
this._renderTrashView();
});

// function to hide trashView from canvas
function handleClickOutsideTrashView(trashView) {
let firstClick = true;
document.addEventListener('click', (event) => {
if (firstClick) {
firstClick = false;
return;
}
if (!trashView.contains(event.target) && event.target !== trashView) {
trashView.style.display = 'none';
}
});
}

this.handleKeyDown = (event) => {

if (event.ctrlKey && event.key === "z") {
this._restoreTrash(activity);
activity.__tick();
event.preventDefault();
this._renderTrashView = () => {
if (!activity.blocks || !activity.blocks.trashStacks || activity.blocks.trashStacks.length === 0) {
return;
}
};

// Attach keydown event listener to document
document.addEventListener("keydown", this.handleKeyDown);
const trashList = document.getElementById('trashList');
const trashView = document.createElement('div');
trashView.id = 'trashView';
trashView.classList.add('trash-view');

// Sticky icons
const buttonContainer = document.createElement('div');
buttonContainer.classList.add('button-container');

const restoreLastIcon = document.createElement('a');
restoreLastIcon.id = 'restoreLastIcon';
restoreLastIcon.classList.add('restore-last-icon');
restoreLastIcon.innerHTML = '<i class="material-icons md-48">restore_from_trash</i>';
restoreLastIcon.addEventListener('click', () => {
this._restoreTrashById(this.blocks.trashStacks[this.blocks.trashStacks.length - 1]);
trashView.classList.add('hidden');
});

const restoreAllIcon = document.createElement('a');
restoreAllIcon.id = 'restoreAllIcon';
restoreAllIcon.classList.add('restore-all-icon');
restoreAllIcon.innerHTML = '<i class="material-icons md-48">delete_sweep</i>';
restoreAllIcon.addEventListener('click', () => {
while (this.blocks.trashStacks.length > 0) {
this._restoreTrashById(this.blocks.trashStacks[0]);
}
trashView.classList.add('hidden');
});
restoreLastIcon.setAttribute("title", _("Restore last item"));
restoreAllIcon.setAttribute("title", _("Restore all items"));

buttonContainer.appendChild(restoreLastIcon);
buttonContainer.appendChild(restoreAllIcon);
trashView.appendChild(buttonContainer);

// Render trash items
this.blocks.trashStacks.forEach((blockId) => {
const block = this.blocks.blockList[blockId];
const listItem = document.createElement('div');
listItem.classList.add('trash-item');

const svgData = block.artwork;
const encodedData = 'data:image/svg+xml;utf8,' + encodeURIComponent(svgData);

const img = document.createElement('img');
img.src = encodedData;
img.alt = 'Block Icon';
img.classList.add('trash-item-icon');

const textNode = document.createTextNode(block.name);

listItem.appendChild(img);
listItem.appendChild(textNode);
listItem.dataset.blockId = blockId;

listItem.addEventListener('mouseover', () => listItem.classList.add('hover'));
listItem.addEventListener('mouseout', () => listItem.classList.remove('hover'));
listItem.addEventListener('click', () => {
this._restoreTrashById(blockId);
trashView.classList.add('hidden');
});
handleClickOutsideTrashView(trashView);

trashView.appendChild(listItem);
});

const existingView = document.getElementById('trashView');
if (existingView) {
trashList.replaceChild(trashView, existingView);
} else {
trashList.appendChild(trashView);
}
};

/*
* Open aux menu
Expand Down Expand Up @@ -5840,7 +5923,7 @@ class Activity {
this.helpfulWheelItems.push({label: "Increase block size", icon: "imgsrc:data:image/svg+xml;base64," + window.btoa(base64Encode(BIGGERBUTTON)), display: true, fn: doLargerBlocks});

if (!this.helpfulWheelItems.find(ele => ele.label === "Restore"))
this.helpfulWheelItems.push({label: "Restore", icon: "imgsrc:header-icons/restore-from-trash.svg", display: true, fn: restoreTrash});
this.helpfulWheelItems.push({label: "Restore", icon: "imgsrc:header-icons/restore-from-trash.svg", display: true, fn: restoreTrashPop});

if (!this.helpfulWheelItems.find(ele => ele.label === "Turtle Wrap Off"))
this.helpfulWheelItems.push({label: "Turtle Wrap Off", icon: "imgsrc:header-icons/wrap-text.svg", display: true, fn: this.toolbar.changeWrap});
Expand Down

0 comments on commit 39171f4

Please sign in to comment.