Rename folder + first build

This commit is contained in:
2022-09-03 22:53:47 +03:00
parent ad69591471
commit 8b4f8f19f7
11 changed files with 31 additions and 4 deletions

View File

@@ -0,0 +1,48 @@
const activeTabs = {};
let contentScriptRerunner = null;
function runContentScript(tabId) {
chrome.tabs.executeScript(tabId, {
allFrames: true,
file: 'run.js',
});
}
function rerunContentScripts() {
// unfortunately we need to rerun periodically to handle iframes changing..
// eventually fixed when we require the new host permission or chrome releases a content script api
for (const tabId of Object.keys(activeTabs)) {
runContentScript(parseInt(tabId, 10));
}
}
function registerDynamicContentScript() {
chrome.tabs.onUpdated.addListener((tabId, {status}, {url}) => {
if (!status || !url) {
return;
}
runContentScript(tabId);
activeTabs[tabId] = true;
if (contentScriptRerunner == null) {
contentScriptRerunner = setInterval(rerunContentScripts, 5000);
}
});
chrome.tabs.onRemoved.addListener((tabId) => {
delete activeTabs[tabId];
if (contentScriptRerunner != null && Object.keys(activeTabs).length === 0) {
clearInterval(contentScriptRerunner);
contentScriptRerunner = null;
}
});
}
chrome.runtime.onInstalled.addListener(({reason}) => {
if (reason !== 'install') {
return;
}
});
registerDynamicContentScript();

BIN
Twitch Notes/icon.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -0,0 +1,34 @@
{
"background": {
"scripts": ["background.js"]
},
"browser_action": {
"default_popup": "settings.html"
},
"content_scripts": [
{
"all_frames": true,
"exclude_matches": [
"*://*.twitch.tv/*.html",
"*://*.twitch.tv/*.html?*",
"*://*.twitch.tv/*.htm",
"*://*.twitch.tv/*.htm?*"
],
"js": ["run.js"],
"matches": ["*://*.twitch.tv/*"]
}
],
"description": "Add notes to twitch users (only visible to you)",
"externally_connectable": {
"matches": ["*://*.twitch.tv/*"]
},
"homepage_url": "https://rdarius.lt/projects/chrome-extensions/twitch-notes",
"icons": {
"128": "icon.png"
},
"manifest_version": 2,
"name": "Twitch Notes",
"permissions": ["*://*.twitch.tv/*"],
"version": "0.0.0.1",
"web_accessible_resources": ["twitch-notes.js", "twitch-notes.css"]
}

View File

@@ -0,0 +1,46 @@
<?xml version="1.0" encoding="iso-8859-1"?>
<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
viewBox="0 0 508.1 508.1" style="enable-background:new 0 0 508.1 508.1;" xml:space="preserve">
<g>
<g>
<path d="M440.85,55.3h-168.3v-0.7c0-30.1-24.5-54.6-54.6-54.6c-30.1,0-54.6,24.5-54.6,54.6c0,0.2,0.1,0.5,0.1,0.7h-31.7
c-7.8,0-14.1,6.3-14.1,14.1v43.4h-50.4c-7.8,0-14.1,6.3-14.1,14.1v262.4c0,3.7,1.5,7.3,4.1,10L161.85,504c2.6,2.6,6.2,4.1,10,4.1
h204.5c7.8,0,14.1-6.3,14.1-14.1v-37.5h50.4c7.8,0,14.1-6.3,14.1-14.1v-373C454.95,61.6,448.65,55.3,440.85,55.3z M191.55,54.6
c0-14.5,11.8-26.4,26.4-26.4c14.6,0,26.4,11.8,26.4,26.4v0.7h-52.8C191.55,55.1,191.55,54.8,191.55,54.6z M145.85,83.5h98.5v29.3
h-98.5V83.5z M244.35,141v31c0,14.5-11.8,26.4-26.4,26.4s-26.4-11.8-26.4-26.4v-31H244.35z M157.75,459.8l-56.5-56.5h56.5V459.8z
M362.25,479.8h-176.2v-90.5c0-7.8-6.3-14.1-14.1-14.1h-90.6V141h82v31c0,30.1,24.5,54.6,54.6,54.6c30.1,0,54.6-24.5,54.6-54.6
v-31h89.7V479.8z M426.75,428.1h-36.3V126.9c0-7.8-6.3-14.1-14.1-14.1h-103.8V83.5h154.2V428.1z"/>
</g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
<g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

24
Twitch Notes/run.js Normal file
View File

@@ -0,0 +1,24 @@
(function twitchNotes() {
const head = document.getElementsByTagName("head")[0];
if (!head) {
return;
}
if (!document.querySelector("script#twitchNotesScript")) {
const script = document.createElement("script");
script.type = "text/javascript";
script.src = chrome.runtime.getURL("twitch-notes.js");
script.id = "twitchNotesScript";
head.appendChild(script);
}
if (!document.querySelector("style#twitchNotesStyle")) {
const style = document.createElement("link");
style.setAttribute("href", chrome.runtime.getURL("twitch-notes.css"));
style.setAttribute("type", "text/css");
style.setAttribute("rel", "stylesheet");
style.setAttribute("crossorigin", "anonymous");
style.id = "twitchNotesStyle";
head.appendChild(style);
}
})();

View File

@@ -0,0 +1,3 @@
<div style="width: 250px">
Exporting, Importing and Data clearing will be available in the future
</div>

View File

@@ -0,0 +1,115 @@
:root {
--window-close: #f77669;
--window-minify: #ffcb6b;
--window-expand: #c3e88d;
--background-header: #393d3e;
--background-code: #1f1e1e;
}
.twitch-note-container {
position: fixed;
z-index: 1000000;
min-width: 420px;
max-width: 95vw;
min-height: 240px;
max-height: 50vh;
background: var(--color-background-base);
border: var(--border-width-default) solid var(--color-border-base) !important;
}
.twitch-note-header {
width: 100%;
height: 32px;
line-height: 32px;
border-bottom: var(--border-width-default) solid var(--color-border-base) !important;
position: relative;
cursor: move;
}
.twitch-note-title {
color: var(--color-text-alt) !important;
font-size: var(--font-size-6) !important;
font-weight: var(--font-weight-semibold) !important;
text-transform: uppercase !important;
padding-left: calc((32px - var(--font-size-6)) / 2);
}
.twitch-note-close-button {
position: absolute;
right: 5px;
top: 5px;
width: 22px;
height: 22px;
line-height: 22px;
text-align: center;
aspect-ration: 1;
color: var(--color-text-alt) !important;
font-size: var(--font-size-6) !important;
font-weight: var(--font-weight-semibold) !important;
text-transform: uppercase !important;
border: var(--border-width-default) solid var(--color-border-base) !important;
cursor: pointer;
}
.twitch-note-content {
position: absolute;
top: 32px;
left: 0;
right: 0;
bottom: 32px;
background: transparent;
color: var(--color-text-base) !important;
font-family: var(--font-base);
vertical-align: baseline;
outline: none;
overflow: auto;
padding: calc((32px - var(--font-size-6)) / 2);
}
.twitch-note-save-button {
position: absolute;
bottom: 0;
left: 0;
right: 0;
height: 32px;
border-top: var(--border-width-default) solid var(--color-border-base) !important;
cursor: pointer;
color: var(--color-text-alt) !important;
font-size: var(--font-size-6) !important;
font-weight: var(--font-weight-semibold) !important;
text-transform: uppercase !important;
text-align: center;
line-height: 32px;
}
.twitch-notes-settings-button {
z-index: var(--z-index-default) !important;
position: relative !important;
background-color: var(--color-background-button-primary-default);
color: var(--color-text-button-primary);
text-decoration: none;
cursor: pointer;
display: inline-flex;
-webkit-box-align: center;
align-items: center;
-webkit-box-pack: center;
justify-content: center;
vertical-align: middle;
overflow: hidden;
white-space: nowrap;
user-select: none;
font-weight: var(--font-weight-semibold);
border-radius: var(--border-radius-medium);
font-size: var(--button-text-default);
height: var(--button-size-default);
padding: 0 var(--button-padding-x);
}
.twitch-note-settings-container {
position: absolute;
z-index: var(--z-index-balloon);
inset: auto 0px 100% auto;
margin-bottom: 8px;
margin-right: -5.3rem;
}

View File

@@ -0,0 +1,223 @@
(function runTwitchNotes() {
let mousePosition = { x: 0, y: 0 };
let lastMousePosition = { x: 0, y: 0 };
let openContainers = {};
let isMouseDown = false;
let activeContainer = null;
let settingsWindowOpen = false;
let LS_UserList = "twitch-note-all-users-list";
let LS_Prefix = "twitch-note-";
document.addEventListener("mousemove", handleMouseMove);
document.addEventListener("mouseup", handleMouseUp);
function createSettingsButton(buttonContainer) {
const c1 = document.createElement("div");
c1.style.marginLeft = "0.5rem !important";
const c2 = document.createElement("div");
c2.style.display = "inline-flex !important";
const settingsButton = document.createElement("button");
settingsButton.classList.add("twitch-notes-settings-button");
settingsButton.innerHTML = "Notes";
settingsButton.addEventListener("click", () => {
console.log("TN Settings");
});
c2.appendChild(settingsButton);
c1.appendChild(c2);
buttonContainer.lastChild.insertBefore(
c1,
buttonContainer.lastChild.lastChild
);
}
function getSavedUserList() {
return JSON.parse(localStorage.getItem(LS_UserList) || "[]");
}
function addUserToSavedList(username) {
let userList = getSavedUserList();
if (!userList.includes(username)) {
userList.push(username);
localStorage.setItem(LS_UserList, JSON.stringify(userList));
}
}
function saveNote(username, note) {
addUserToSavedList(username);
localStorage.setItem(LS_Prefix + username, note);
}
function getNote(username) {
return localStorage.getItem(LS_Prefix + username) || "";
}
function handleMouseMove(event) {
event = event || window.event;
if (isMouseDown) {
if (activeContainer) {
const dx = mousePosition.x - lastMousePosition.x;
const dy = mousePosition.y - lastMousePosition.y;
openContainers[activeContainer].style.top =
parseInt(openContainers[activeContainer].style.top) + dy + "px";
openContainers[activeContainer].style.left =
parseInt(openContainers[activeContainer].style.left) + dx + "px";
}
}
updateMousePosition(event.clientX, event.clientY);
}
function handleMouseUp(event) {
activeContainer = null;
isMouseDown = false;
}
function updateMousePosition(x, y) {
lastMousePosition = { ...mousePosition };
mousePosition.x = x;
mousePosition.y = y;
}
function removeContainer(username) {
if (!openContainers[username]) return;
openContainers[username].remove();
delete openContainers[username];
}
function addContainer(username, container) {
if (openContainers[username]) return;
openContainers[username] = container;
document.body.appendChild(container);
}
function openTwitchNote(username) {
// CONTAINER
const container = document.createElement("div");
container.style.left = mousePosition.x + "px";
container.style.top = mousePosition.y + 10 + "px";
container.classList.add("twitch-note-container");
// HEADER
const header = document.createElement("div");
header.classList.add("twitch-note-header");
header.addEventListener("mousedown", function close() {
activeContainer = username;
isMouseDown = true;
});
const closeButton = document.createElement("span");
closeButton.classList.add("twitch-note-close-button");
closeButton.innerText = "X";
closeButton.addEventListener("click", function close() {
removeContainer(username);
});
header.appendChild(closeButton);
const title = document.createElement("span");
title.classList.add("twitch-note-title");
title.innerHTML = username;
header.appendChild(title);
container.appendChild(header);
// BODY
const content = document.createElement("div");
content.classList.add("twitch-note-content");
content.setAttribute("contentEditable", true);
content.innerHTML = getNote(username);
container.appendChild(content);
const saveButton = document.createElement("div");
saveButton.classList.add("twitch-note-save-button");
saveButton.innerText = "SAVE";
saveButton.addEventListener("click", function () {
saveNote(username, content.innerHTML);
removeContainer(username);
});
container.appendChild(saveButton);
addContainer(username, container);
}
let giveUpAt = Date.now() + 20000;
let changeInProgress = false;
let targetNode;
let buttonContainer;
do {
targetNode = document.getElementsByClassName(
"chat-scrollable-area__message-container"
)[0];
} while (!targetNode || giveUpAt < Date.now());
do {
buttonContainer = document.getElementsByClassName(
"chat-input__buttons-container"
)[0];
} while (!buttonContainer || giveUpAt < Date.now());
// createSettingsButton(buttonContainer);
// Options for the observer (which mutations to observe)
const config = { attributes: true, childList: true, subtree: true };
// Callback function to execute when mutations are observed
const callback = (mutationList, observer) => {
if (!changeInProgress) {
for (const mutation of mutationList) {
if (mutation.type === "childList") {
changeInProgress = true;
let nodes = document.getElementsByClassName("chat-line__message");
let users = [];
for (let node of nodes) {
const n = node.querySelector(".chat-author__display-name");
if (!n) continue;
const usernameContainer = node.querySelector(
".chat-line__username-container"
);
const username = n.attributes["data-a-user"].value;
if (username) {
let noteButton = usernameContainer.querySelector(".twitchnote");
if (!noteButton) {
const twitchNote = document.createElement("span");
twitchNote.classList.add("twitchnote");
twitchNote.style.cursor = "pointer";
twitchNote.addEventListener("click", () => {
openTwitchNote(username);
});
const img = document.createElement("img");
img.src = "https://cdn.rdarius.lt/icons/32-id-card.png";
img.style.height = "18px";
img.style.paddingRight = "4px";
twitchNote.appendChild(img);
usernameContainer.insertBefore(
twitchNote,
usernameContainer.firstChild
);
}
if (!users[username]) {
users[username] = 0;
}
users[username]++;
}
}
changeInProgress = false;
}
}
}
};
// Create an observer instance linked to the callback function
const observer = new MutationObserver(callback);
// Start observing the target node for configured mutations
observer.observe(targetNode, config);
})();