diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..3c3629e --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +node_modules diff --git a/.todo b/.todo deleted file mode 100644 index 6aefcd7..0000000 --- a/.todo +++ /dev/null @@ -1 +0,0 @@ -☐ Add button next to message \ No newline at end of file diff --git a/extension/background.js b/extension/background.js new file mode 100644 index 0000000..32d02cf --- /dev/null +++ b/extension/background.js @@ -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(); diff --git a/extension/icon.png b/extension/icon.png new file mode 100644 index 0000000..04a1927 Binary files /dev/null and b/extension/icon.png differ diff --git a/extension/manifest.json b/extension/manifest.json new file mode 100644 index 0000000..ecf172f --- /dev/null +++ b/extension/manifest.json @@ -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", + "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.1", + "web_accessible_resources": ["twitchnotes.js", "twitchnotes.css"] +} diff --git a/extension/notes-notepad-svgrepo-com.svg b/extension/notes-notepad-svgrepo-com.svg new file mode 100644 index 0000000..cdacaba --- /dev/null +++ b/extension/notes-notepad-svgrepo-com.svg @@ -0,0 +1,46 @@ + + + diff --git a/extension/run.js b/extension/run.js new file mode 100644 index 0000000..99be010 --- /dev/null +++ b/extension/run.js @@ -0,0 +1,110 @@ +(function twitchnotes() { + if (document.querySelector("script#twitchnotes")) { + return; + } + + const script = document.createElement("script"); + script.type = "text/javascript"; + script.src = chrome.runtime.getURL("twitchnotes.js"); + script.id = "twitchnotes"; + const head = document.getElementsByTagName("head")[0]; + if (!head) { + return; + } + + head.appendChild(script); + + const style = document.createElement("style"); + style.innerHTML = ` + :root { + --window-close: #f77669; + --window-minify: #ffcb6b; + --window-expand: #c3e88d; + + --background-header: #393d3e; + --background-code: #1f1e1e; + } + + .twitchnote img { + height: 18px; + padding: 0 4px 0; + } + + .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; + } +`; + head.appendChild(style); +})(); diff --git a/extension/settings.html b/extension/settings.html new file mode 100644 index 0000000..841d051 --- /dev/null +++ b/extension/settings.html @@ -0,0 +1,3 @@ +