diff --git a/features/features.json b/features/features.json index a344f61e..00dec257 100644 --- a/features/features.json +++ b/features/features.json @@ -1,4 +1,9 @@ [ + { + "version": 2, + "id": "studio-invite-comments", + "versionAdded": "v4.2.0" + }, { "version": 2, "id": "copy-paste-lists", diff --git a/features/studio-invite-comments/data.json b/features/studio-invite-comments/data.json new file mode 100644 index 00000000..9e5ce642 --- /dev/null +++ b/features/studio-invite-comments/data.json @@ -0,0 +1,17 @@ +{ + "title": "Invite to Studio from Comments", + "description": "Adds an invite option next to report on studio comments.", + "credits": [ + { + "username": "Masaabu-YT", + "url": "https://scratch.mit.edu/users/Masaabu-YT/" + }, + { "username": "MaterArc", "url": "https://scratch.mit.edu/users/MaterArc/" } + ], + "type": ["Website"], + "tags": ["New", "Featured"], + "dynamic": true, + "styles": [{ "file": "style.css", "runOn": "/studios/*" }], + "scripts": [{ "file": "script.js", "runOn": "/studios/*" }], + "resources": [{ "name": "invite", "path": "/invite.svg" }] +} diff --git a/features/studio-invite-comments/invite.svg b/features/studio-invite-comments/invite.svg new file mode 100644 index 00000000..f1be48d6 --- /dev/null +++ b/features/studio-invite-comments/invite.svg @@ -0,0 +1,4 @@ + + + + diff --git a/features/studio-invite-comments/script.js b/features/studio-invite-comments/script.js new file mode 100644 index 00000000..cb778931 --- /dev/null +++ b/features/studio-invite-comments/script.js @@ -0,0 +1,48 @@ +export default async function ({ feature }) { + const parts = window.location.pathname.split("/"); + const studioId = parts[parts.length - 2]; + if (!studioId) return; + + const session = await ScratchTools.Session(); + if (!session?.user?.username) return; + + const csrfToken = document.cookie.match(/scratchcsrftoken=([^;]+)/)?.[1]; + if (!csrfToken) return; + + ScratchTools.waitForElements( + ".comment-body", + (comment) => { + const topRow = comment.querySelector(".comment-top-row"); + const actionList = topRow?.querySelector(".action-list"); + if (!topRow || !actionList) return; + if (actionList.querySelector(".ste-comment-invite")) return; + + const inviteBtn = document.createElement("span"); + inviteBtn.classList.add("ste-comment-invite"); + + const innerSpan = document.createElement("span"); + innerSpan.textContent = "Invite"; + inviteBtn.appendChild(innerSpan); + + inviteBtn.onclick = async () => { + const username = topRow.querySelector(".username")?.textContent.trim(); + if (!username) return; + const url = `https://scratch.mit.edu/site-api/users/curators-in/${studioId}/invite_curator/?usernames=${encodeURIComponent( + username + )}`; + await fetch(url, { + method: "PUT", + headers: { + "x-csrftoken": csrfToken, + "Content-Type": "application/json", + }, + credentials: "include", + }); + }; + + actionList.appendChild(inviteBtn); + }, + "ste-invite-buttons", + false + ); +} diff --git a/features/studio-invite-comments/style.css b/features/studio-invite-comments/style.css new file mode 100644 index 00000000..870f7ef8 --- /dev/null +++ b/features/studio-invite-comments/style.css @@ -0,0 +1,21 @@ +.ste-comment-invite { + cursor: pointer; + margin-left: 10px; + font-size: 0.75rem; + font-weight: 500; + opacity:0.5; +} + +.ste-comment-invite::before { + content: ""; + display: inline-block; + width: 1.1rem; + height: 1.1rem; + margin-right: 0.25rem; + vertical-align: -0.27rem; + background-image: var(--scratchtoolsresource-invite); + background-repeat: no-repeat; + background-size: contain; + background-position: center; + filter: brightness(0) saturate(100%) invert(38%) sepia(7%) saturate(582%) hue-rotate(185deg) brightness(94%) contrast(86%); +} \ No newline at end of file