From 24de3d31401aed9fca5c1750c32b39e9a687b004 Mon Sep 17 00:00:00 2001 From: faraplay Date: Thu, 6 Jul 2023 16:30:44 +0100 Subject: [PATCH 01/12] remove VSCode preferences from repo --- .gitignore | 5 ++++- .vscode/tasks.json | 24 ------------------------ 2 files changed, 4 insertions(+), 25 deletions(-) delete mode 100644 .vscode/tasks.json diff --git a/.gitignore b/.gitignore index 92bfcba..72d4b6b 100644 --- a/.gitignore +++ b/.gitignore @@ -134,4 +134,7 @@ dist .yarn/unplugged .yarn/build-state.yml .yarn/install-state.gz -.pnp.* \ No newline at end of file +.pnp.* + +# VSCode preferences +.vscode/ \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json deleted file mode 100644 index c25dfef..0000000 --- a/.vscode/tasks.json +++ /dev/null @@ -1,24 +0,0 @@ -{ - "version": "2.0.0", - "tasks": [ - { - "type": "npm", - "script": "wp-build", - "group": { - "kind": "build", - "isDefault": true - }, - "problemMatcher": [], - "label": "npm: wp-build", - "detail": "webpack" - }, - { - "type": "npm", - "script": "install", - "group": "none", - "problemMatcher": [], - "label": "npm: install", - "detail": "install dependencies from package" - } - ] -} \ No newline at end of file From 6b612aaf70851a9853af3bf25a4aab4c026f2c0f Mon Sep 17 00:00:00 2001 From: faraplay Date: Thu, 6 Jul 2023 16:50:26 +0100 Subject: [PATCH 02/12] custom style loader --- dev/my_style_loader/index.js | 16 ++++++++++++++++ dev/my_style_loader/insertStyle.js | 17 +++++++++++++++++ webpack.config.js | 12 ++++++++++-- 3 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 dev/my_style_loader/index.js create mode 100644 dev/my_style_loader/insertStyle.js diff --git a/dev/my_style_loader/index.js b/dev/my_style_loader/index.js new file mode 100644 index 0000000..4f4b605 --- /dev/null +++ b/dev/my_style_loader/index.js @@ -0,0 +1,16 @@ +path = require("path"); + +module.exports = { + pitch: function (request) { + const insertStylePath = this.utils.contextify( + this.context, path.resolve(__dirname, "./insertStyle.js")); + const cssPath = this.utils.contextify(this.context, `!!${request}`); + + const outputJs = ` + import insertStyle from ${JSON.stringify(insertStylePath)}; + import content from ${JSON.stringify(cssPath)}; + insertStyle(content.toString()); + `; + return outputJs; + }, +}; diff --git a/dev/my_style_loader/insertStyle.js b/dev/my_style_loader/insertStyle.js new file mode 100644 index 0000000..b41659b --- /dev/null +++ b/dev/my_style_loader/insertStyle.js @@ -0,0 +1,17 @@ +export default function insertStyle(style) { + var element = document.createElement("style"); + element.innerText = style; + if (document.head) { + document.head.appendChild(element); + return; + } + var observer = new MutationObserver(function () { + if (document.head) { + observer.disconnect(); + document.head.appendChild(element); + } + }); + observer.observe(document.documentElement, { + childList: true, + }); +} diff --git a/webpack.config.js b/webpack.config.js index c0c1eb3..f2eafc7 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -84,7 +84,7 @@ module.exports = (env, argv) => { filename: "[name].js", path: __dirname + "/dist", clean: true, - publicPath: "extension://aaaa", + publicPath: "extension://placeholder_not_real_path", }, plugins: [ new CopyPlugin({ @@ -96,7 +96,7 @@ module.exports = (env, argv) => { rules: [ { test: /\.css$/i, - use: ["style-loader", "css-loader"], + use: ["my-style-loader", "css-loader"], }, { test: /\.(woff(2)?|ttf|eot)$/, @@ -107,6 +107,14 @@ module.exports = (env, argv) => { }, ], }, + resolveLoader: { + alias: { + "my-style-loader": path.resolve( + __dirname, + "./dev/my_style_loader/index.js" + ), + }, + }, resolve: { alias: { "~": path.resolve(__dirname, "."), From bdec317bc12caf3cf9f4021b5d174c1ac4bc8792 Mon Sep 17 00:00:00 2001 From: faraplay Date: Thu, 6 Jul 2023 16:53:41 +0100 Subject: [PATCH 03/12] move/rename some files --- js/cs.js | 4 ++-- js/{sidebars.js => sidebar/index.js} | 0 js/{ => sidebar}/subreddit_sidebar.js | 0 js/{ => sidebar}/user_sidebar.js | 0 js/{general.js => styling.js} | 0 js/user.js | 4 ++-- 6 files changed, 4 insertions(+), 4 deletions(-) rename js/{sidebars.js => sidebar/index.js} (100%) rename js/{ => sidebar}/subreddit_sidebar.js (100%) rename js/{ => sidebar}/user_sidebar.js (100%) rename js/{general.js => styling.js} (100%) diff --git a/js/cs.js b/js/cs.js index 095059a..c5fb56b 100644 --- a/js/cs.js +++ b/js/cs.js @@ -1,7 +1,7 @@ import "./setPublicPath.js"; -import "./general.js"; +import "./styling.js"; import "./header.js"; -import "./sidebars.js"; +import "./sidebar"; import "./posts"; import "./preferences.js"; console.log("Content script loaded."); diff --git a/js/sidebars.js b/js/sidebar/index.js similarity index 100% rename from js/sidebars.js rename to js/sidebar/index.js diff --git a/js/subreddit_sidebar.js b/js/sidebar/subreddit_sidebar.js similarity index 100% rename from js/subreddit_sidebar.js rename to js/sidebar/subreddit_sidebar.js diff --git a/js/user_sidebar.js b/js/sidebar/user_sidebar.js similarity index 100% rename from js/user_sidebar.js rename to js/sidebar/user_sidebar.js diff --git a/js/general.js b/js/styling.js similarity index 100% rename from js/general.js rename to js/styling.js diff --git a/js/user.js b/js/user.js index 3da5fdc..f97f41a 100644 --- a/js/user.js +++ b/js/user.js @@ -1,7 +1,7 @@ import "./viewport.js"; -import "./general.js"; +import "./styling.js"; import "./header.js"; -import "./sidebars.js"; +import "./sidebar"; import "./posts"; import "./preferences.js"; From a77e1db51572a073a2342afb07153bd54101c2b7 Mon Sep 17 00:00:00 2001 From: faraplay Date: Thu, 6 Jul 2023 16:29:21 +0100 Subject: [PATCH 04/12] edit meta viewport tag when it loads --- js/utility/querySelectorAsync.js | 7 ++++ js/utility/waitForElement.js | 58 ++++++++++++++++++++++++++++++++ js/viewport.js | 26 ++++---------- 3 files changed, 71 insertions(+), 20 deletions(-) create mode 100644 js/utility/querySelectorAsync.js create mode 100644 js/utility/waitForElement.js diff --git a/js/utility/querySelectorAsync.js b/js/utility/querySelectorAsync.js new file mode 100644 index 0000000..6490b64 --- /dev/null +++ b/js/utility/querySelectorAsync.js @@ -0,0 +1,7 @@ +import { waitForElement } from "./waitForElement"; + +export default function querySelectorAsync(selector) { + return new Promise((resolve, _reject) => { + waitForElement(selector, resolve); + }); +} diff --git a/js/utility/waitForElement.js b/js/utility/waitForElement.js new file mode 100644 index 0000000..d67737e --- /dev/null +++ b/js/utility/waitForElement.js @@ -0,0 +1,58 @@ +export function waitForElement(selector, callback) { + // see if element exists already + const element = document.querySelector(selector); + if (element) { + callback(element); + return; + } + // otherwise set up an observer + var observer = new MutationObserver(function (mutations) { + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { + if (node.nodeType === Node.ELEMENT_NODE) { + // new nodes have been added, check them + const element = document.querySelector(selector); + if (element) { + observer.disconnect(); + callback(element); + } + return; + } + } + } + }); + observer.observe(document.documentElement, { + childList: true, + subtree: true, + }); +} + +export function waitForAllElements(selector, callback) { + // perform callback on already existing elements + for (const element of document.querySelectorAll(selector)) { + callback(element); + } + // then set up an observer + var observer = new MutationObserver(function (mutations) { + const foundElements = new Set(); + for (const mutation of mutations) { + for (const node of mutation.addedNodes) { + if (node.nodeType === Node.ELEMENT_NODE) { + if (node.matches(selector)) { + foundElements.add(node); + } + for (const element of node.querySelectorAll(selector)) { + foundElements.add(element); + } + } + } + } + for (const element of foundElements) { + callback(element); + } + }); + observer.observe(document.documentElement, { + childList: true, + subtree: true, + }); +} diff --git a/js/viewport.js b/js/viewport.js index cd9b755..661bee2 100644 --- a/js/viewport.js +++ b/js/viewport.js @@ -1,25 +1,11 @@ -function setViewport() { - const viewportCfg = document.createElement("meta"); - viewportCfg.setAttribute("name", "viewport"); - viewportCfg.setAttribute( +import querySelectorAsync from "./utility/querySelectorAsync"; + +async function setViewport() { + const viewportElement = await querySelectorAsync('head > meta[name="viewport"]'); + viewportElement.setAttribute( "content", "width=device-width,initial-scale=1.0, maximum-scale=1.0, user-scalable=no" ); - document.head.appendChild(viewportCfg); } -// https://stackoverflow.com/questions/26324624/wait-for-document-body-existence -(function () { - "use strict"; - var observer = new MutationObserver(function () { - if (document.head) { - // It exists now - setViewport(); - observer.disconnect(); - } - }); - observer.observe(document.documentElement, { childList: true }); -})(); -document.addEventListener("DOMContentLoaded", function onDOMContentLoaded() { - setViewport(); -}); +setViewport(); From ca05cb163a85d8b5bbaf7f461c125fca371481a7 Mon Sep 17 00:00:00 2001 From: faraplay Date: Thu, 6 Jul 2023 18:58:47 +0100 Subject: [PATCH 05/12] update styling asynchronously --- js/styling.js | 26 ++++++++++++++------------ 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/js/styling.js b/js/styling.js index 250b90a..813b204 100644 --- a/js/styling.js +++ b/js/styling.js @@ -7,22 +7,24 @@ import "~/css/res-compat.css"; import "~/css/comments.css"; import "material-symbols/outlined.css"; -function neuterSubredditCss() { - try { - document - .querySelector("link[title=applied_subreddit_stylesheet]") - .remove(); - } catch (e) { - console.log("failed to remove subreddit stylesheet"); - } +import querySelectorAsync from "./utility/querySelectorAsync"; + +async function removeSubredditStyling() { + const element = await querySelectorAsync( + "link[title=applied_subreddit_stylesheet]" + ); + element.remove(); + console.log("Subreddit stylesheet removed"); } -function materialize() { - document.body.classList.add("background", "on-background-text"); +async function addBodyStyling() { + const body = await querySelectorAsync("body"); + body.classList.add("background", "on-background-text"); } -neuterSubredditCss(); -materialize(); +removeSubredditStyling(); +addBodyStyling(); + // over18 if (!document.cookie.includes("over18=1")) { console.log("over18 not set, setting"); From 6bf89bd2ef225e0b7e9280f098f6790a8c56e85b Mon Sep 17 00:00:00 2001 From: faraplay Date: Thu, 6 Jul 2023 22:16:34 +0100 Subject: [PATCH 06/12] move UserSidebar button code to header.js --- css/userSidebar.css | 3 --- js/header.js | 23 +++++++++++++++++++---- js/sidebar/user_sidebar.js | 9 --------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/css/userSidebar.css b/css/userSidebar.css index 466e8fb..9eabb39 100644 --- a/css/userSidebar.css +++ b/css/userSidebar.css @@ -31,9 +31,6 @@ display: block; width: 80%; } -#user-sidebar-open:before { - content: "menu"; -} #user-sidebar-open { width: 40px; height: 40px; diff --git a/js/header.js b/js/header.js index 613e2f4..c9ac53c 100644 --- a/js/header.js +++ b/js/header.js @@ -96,8 +96,10 @@ function setupOldLanderHeader() { // update previous scroll position prevScrollPos = currentScrollPos; }); + return header; } -function addSubSidebarButton() { + +function addSubSidebarButton(header) { const btn = document.createElement("button"); btn.innerText = "info"; btn.classList.add("material-symbols-outlined"); @@ -105,8 +107,21 @@ function addSubSidebarButton() { const evt = new Event("toggleSub"); document.dispatchEvent(evt); }; - document.querySelector("#ol-header .aux-buttons").appendChild(btn); + header.querySelector(".aux-buttons").appendChild(btn); } -setupOldLanderHeader(); +function addUserSidebarButton(header){ + const btn = document.createElement("button"); + btn.innerText = "menu"; + btn.classList.add("material-symbols-outlined"); + btn.id = "user-sidebar-open"; + btn.onclick = () => { + const evt = new Event("toggleUser"); + document.dispatchEvent(evt); + }; + header.prepend(btn); +} + +const header = setupOldLanderHeader(); makeSortSelector(); -addSubSidebarButton(); +addSubSidebarButton(header); +addUserSidebarButton(header); diff --git a/js/sidebar/user_sidebar.js b/js/sidebar/user_sidebar.js index a8d637b..98c826d 100644 --- a/js/sidebar/user_sidebar.js +++ b/js/sidebar/user_sidebar.js @@ -217,15 +217,6 @@ export default function setupSidebar() { } sidebar.classList.remove("showingup", "abouttodie"); }); - const sb_open = document.createElement("button"); - sb_open.classList.add("material-symbols-outlined"); - const sb_open_old = document.getElementById("user-sidebar-open"); - if (sb_open_old !== null) { - sb_open_old.remove(); - } - sb_open.id = "user-sidebar-open"; - sb_open.onclick = activeToggle; - document.getElementById("ol-header").prepend(sb_open); const sb_close = document.createElement("div"); sb_close.id = "user-sidebar-close"; From 029ce04344fcad059ef749128db68816f15ad6de Mon Sep 17 00:00:00 2001 From: faraplay Date: Thu, 6 Jul 2023 22:36:56 +0100 Subject: [PATCH 07/12] make header creation asynchronous --- js/header.js | 116 ++++++++++++++++++++++++++------------------------- js/modal.js | 10 +++-- 2 files changed, 67 insertions(+), 59 deletions(-) diff --git a/js/header.js b/js/header.js index c9ac53c..2422835 100644 --- a/js/header.js +++ b/js/header.js @@ -1,58 +1,16 @@ import "~/css/header.css"; import modal from "./modal"; -function makeSortSelector() { - // remove old selectors if exist - document - .querySelectorAll("#sortsel") - .forEach((el) => el.parentElement.removeChild(el)); - const options = {}; - const header = document.querySelector("#ol-header"); +import querySelectorAsync from "./utility/querySelectorAsync"; - for (const tab of document.querySelectorAll(".tabmenu li")) { - if ( - tab.innerText === "" || - tab.innerText.includes("show images") || - !tab.innerText.trim().length - ) { - continue; - } - console.log(tab.innerText); - let itemtext = tab.innerText[0].toUpperCase() + tab.innerText.slice(1); - options[itemtext] = tab.children[0].href; - if (tab.classList.contains("selected")) { - header.querySelector(".sort-mode").innerText = tab.innerText; - } - } - if (options.length <= 1) { - return; - } - const optionmenu = document.createElement("ul"); - for (const [option_text, option_link] of Object.entries(options)) { - const optel = document.createElement("li"); - const optel_link = document.createElement("a"); - optel_link.classList.add("sortmodeselector"); - optel_link.href = option_link; - optel_link.innerText = option_text; - optel.appendChild(optel_link); - optionmenu.appendChild(optel); - } - const btn = document.createElement("button"); - btn.id = "sortsel"; - btn.classList.add("material-symbols-outlined"); - btn.innerText = "sort"; - header.querySelector(".aux-buttons").appendChild(btn); - btn.onclick = () => { - modal("Sort mode", optionmenu, () => {}); - }; -} -function setupOldLanderHeader() { +async function createHeader() { const oldheader = document.getElementById("ol-header"); if (oldheader != null) { oldheader.remove(); } const header = document.createElement("div"); header.id = "ol-header"; - document.body.insertBefore(header, document.getElementById("header")); + const body = await querySelectorAsync("body"); + body.insertBefore(header, await querySelectorAsync("#header")); header.innerHTML = `

@@ -63,11 +21,8 @@ function setupOldLanderHeader() { pageName === null ? "Homepage" : pageName.innerText; let prevScrollPos = window.scrollY; - - window.addEventListener("scroll", function () { - // current scroll position + function onScroll() { const currentScrollPos = window.scrollY; - if (prevScrollPos > currentScrollPos) { // user has scrolled up let playAnim = true; @@ -92,13 +47,58 @@ function setupOldLanderHeader() { header.classList.remove("stick"); }); } - // update previous scroll position prevScrollPos = currentScrollPos; - }); + } + window.addEventListener("scroll", onScroll); + return header; } +function makeSortSelector(header) { + // remove old selectors if exist + document + .querySelectorAll("#sortsel") + .forEach((el) => el.parentElement.removeChild(el)); + + const options = {}; + for (const tab of document.querySelectorAll(".tabmenu li")) { + if ( + tab.innerText === "" || + tab.innerText.includes("show images") || + !tab.innerText.trim().length + ) { + continue; + } + let itemtext = tab.innerText[0].toUpperCase() + tab.innerText.slice(1); + options[itemtext] = tab.children[0].href; + if (tab.classList.contains("selected")) { + header.querySelector(".sort-mode").innerText = tab.innerText; + } + } + if (Object.keys(options).length <= 1) { + return; + } + const optionmenu = document.createElement("ul"); + for (const [option_text, option_link] of Object.entries(options)) { + const optel = document.createElement("li"); + const optel_link = document.createElement("a"); + optel_link.classList.add("sortmodeselector"); + optel_link.href = option_link; + optel_link.innerText = option_text; + optel.appendChild(optel_link); + optionmenu.appendChild(optel); + } + const btn = document.createElement("button"); + btn.id = "sortsel"; + btn.classList.add("material-symbols-outlined"); + btn.innerText = "sort"; + header.querySelector(".aux-buttons").appendChild(btn); + btn.onclick = () => { + modal("Sort mode", optionmenu, () => {}); + }; +} + function addSubSidebarButton(header) { const btn = document.createElement("button"); btn.innerText = "info"; @@ -121,7 +121,11 @@ function addUserSidebarButton(header){ header.prepend(btn); } -const header = setupOldLanderHeader(); -makeSortSelector(); -addSubSidebarButton(header); -addUserSidebarButton(header); +async function setupOldLanderHeader() { + const header = await createHeader(); + makeSortSelector(header); + addSubSidebarButton(header); + addUserSidebarButton(header); +} + +setupOldLanderHeader(); \ No newline at end of file diff --git a/js/modal.js b/js/modal.js index decb1c0..b8c9b5c 100644 --- a/js/modal.js +++ b/js/modal.js @@ -1,9 +1,11 @@ import "~/css/modal.css"; + export default function createModal(title, contents, callback) { const oldmodal = document.getElementById("modal"); if (oldmodal !== null) { oldmodal.remove(); } + const modal = document.createElement("div"); modal.id = "modal"; modal.innerHTML = ` @@ -28,16 +30,18 @@ export default function createModal(title, contents, callback) { duration: 250, } ); - anim.addEventListener("finish", () => { + const onFinish = () => { console.log(anim.playState); - modal.removeEventListener("animationend"); + modal.removeEventListener("animationend", onFinish); modal.classList.add("hide"); - }); + }; + anim.addEventListener("finish", onFinish); }) ); modal.querySelector(".olmodal-buttons button.ok").onclick = callback; document.body.appendChild(modal); } + window.testModal = () => { const modalContents = document.createElement("div"); modalContents.innerHTML = From 3641bfe4caedc1afe8d0443ae18de7f7ee2cd50f Mon Sep 17 00:00:00 2001 From: faraplay Date: Fri, 7 Jul 2023 00:31:03 +0100 Subject: [PATCH 08/12] make sidebars async + some refactoring too --- css/redditChanges.css | 2 +- css/subreddit_sidebar.css | 8 +- css/userSidebar.css | 1 + js/sidebar/buildSidebar.js | 41 ++++++++++ js/sidebar/index.js | 61 ++++++++++----- js/sidebar/subreddit_sidebar.js | 49 ++++-------- js/sidebar/user_sidebar.js | 134 ++++++++++++++------------------ 7 files changed, 164 insertions(+), 132 deletions(-) create mode 100644 js/sidebar/buildSidebar.js diff --git a/css/redditChanges.css b/css/redditChanges.css index 67e5792..754dee1 100644 --- a/css/redditChanges.css +++ b/css/redditChanges.css @@ -22,7 +22,7 @@ max-width: unset !important; } .midcol { - margin: 0; + margin: 0 !important; } .sitetable.linklisting > .thing:not(.comment) { display: flex; diff --git a/css/subreddit_sidebar.css b/css/subreddit_sidebar.css index 33994d6..4070fbd 100644 --- a/css/subreddit_sidebar.css +++ b/css/subreddit_sidebar.css @@ -16,7 +16,7 @@ padding-right: 10px; } -#sidebar-toggle { +#custom-sidebar-close { position: sticky; display: none; flex-direction: column; @@ -25,10 +25,10 @@ text-align: center; background-color: rgba(0, 0, 0, 0.5); } -#sidebar-toggle::before { +#custom-sidebar-close::before { font-size: 1.5em; } -#custom-sidebar.active #sidebar-toggle { +#custom-sidebar.active #custom-sidebar-close { display: flex; } #custom-sidebar.active { @@ -38,7 +38,7 @@ display: block; width: 80%; } -#custom-sidebar.active #sidebar-toggle { +#custom-sidebar.active #custom-sidebar-close { flex-grow: 1; } #custom-sidebar.showingup .side { diff --git a/css/userSidebar.css b/css/userSidebar.css index 9eabb39..f62d2ff 100644 --- a/css/userSidebar.css +++ b/css/userSidebar.css @@ -12,6 +12,7 @@ #user-sidebar .side { display: none; overflow-y: scroll; + background-color: var(--md-sys-color-surface); margin-left: 0px; margin-right: 0px; } diff --git a/js/sidebar/buildSidebar.js b/js/sidebar/buildSidebar.js new file mode 100644 index 0000000..6861c9b --- /dev/null +++ b/js/sidebar/buildSidebar.js @@ -0,0 +1,41 @@ +export default function buildSidebar( + innerSidebar, + sidebarId, + closeToggleId, + isOnLeft +) { + document.querySelectorAll(`#${sidebarId}`).forEach((el) => el.remove()); + + const sidebar = document.createElement("div"); + sidebar.id = sidebarId; + + innerSidebar.addEventListener("animationend", () => { + if (sidebar.classList.contains("abouttodie")) { + sidebar.classList.remove("active"); + } + sidebar.classList.remove("showingup", "abouttodie"); + }); + + function activeToggle() { + if (sidebar.classList.contains("active")) { + sidebar.classList.add("abouttodie"); + } else { + sidebar.classList.add("active", "showingup"); + } + } + const closeToggle = document.createElement("div"); + closeToggle.id = closeToggleId; + closeToggle.onclick = (e) => { + e.preventDefault(); + e.stopPropagation(); + activeToggle(); + }; + + if (isOnLeft) { + sidebar.append(innerSidebar, closeToggle); + } else { + sidebar.append(closeToggle, innerSidebar); + } + + return [activeToggle, sidebar]; +} diff --git a/js/sidebar/index.js b/js/sidebar/index.js index dbb9f69..daec838 100644 --- a/js/sidebar/index.js +++ b/js/sidebar/index.js @@ -1,31 +1,54 @@ -import setupSubredditSidebar from "./subreddit_sidebar.js"; -import setupUserSidebar from "./user_sidebar.js"; -function setupSidebars() { - const [toggleSub, subSide] = setupSubredditSidebar(); - const [toggleUser, userSide] = setupUserSidebar(); - document.addEventListener("toggleUser", toggleUser); +import "swiped-events"; +import buildSubredditSidebar from "./subreddit_sidebar.js"; +import buildUserSidebar from "./user_sidebar.js"; + +const eventListeners = { + toggleUser: [], + toggleSub: [], + "swiped-right": [], + "swiped-left": [], +}; +let toggleSub, toggleUser, subSide, userSide; + +function setEventListener(type, listener) { + for (const currentListener of eventListeners[type]) { + document.removeEventListener(type, currentListener); + } + document.addEventListener(type, listener); + eventListeners[type] = [listener]; +} + +async function setupSubredditSidebar() { + [toggleSub, subSide] = await buildSubredditSidebar(); + setSidebarEvents(); +} +async function setupUserSidebar() { + [toggleUser, userSide] = await buildUserSidebar(); + setSidebarEvents(); +} + +function setSidebarEvents() { if (toggleSub) { - document.addEventListener("toggleSub", toggleSub); + setEventListener("toggleSub", toggleSub); } - document.addEventListener("swiped-right", function (e) { - // sidebar.classList.remove("active"); + if (toggleUser) { + setEventListener("toggleUser", toggleUser); + } + setEventListener("swiped-right", function () { if (subSide && subSide.classList.contains("active")) { toggleSub(); - return; - } - if (!userSide.classList.contains("active")) { + } else if (userSide && !userSide.classList.contains("active")) { toggleUser(); } }); - document.addEventListener("swiped-left", function (e) { - // sidebar.classList.add("active"); - if (userSide.classList.contains("active")) { + setEventListener("swiped-left", function () { + if (userSide && userSide.classList.contains("active")) { toggleUser(); - return; - } - if (subSide && !subSide.classList.contains("active")) { + } else if (subSide && !subSide.classList.contains("active")) { toggleSub(); } }); } -setupSidebars(); + +setupSubredditSidebar(); +setupUserSidebar(); diff --git a/js/sidebar/subreddit_sidebar.js b/js/sidebar/subreddit_sidebar.js index 6487a61..0556675 100644 --- a/js/sidebar/subreddit_sidebar.js +++ b/js/sidebar/subreddit_sidebar.js @@ -1,36 +1,19 @@ -import "swiped-events"; import "~/css/subreddit_sidebar.css"; -export default function setupSidebar() { - const sidebar = document.createElement("div"); - const sidebarToggle = document.createElement("div"); - const actualSidebar = document.querySelector(".side"); - if (!actualSidebar) { - return [null, null]; - } - sidebarToggle.id = "sidebar-toggle"; - sidebar.id = "custom-sidebar"; - sidebar.appendChild(sidebarToggle); - sidebar.appendChild(actualSidebar); - document.querySelectorAll("#custom-sidebar").forEach((el) => el.remove()); - document.body.appendChild(sidebar); - function activeToggle() { - if (sidebar.classList.contains("active")) { - sidebar.classList.add("abouttodie"); - } else { - sidebar.classList.add("active", "showingup"); - } - } - sidebarToggle.onclick = (e) => { - e.preventDefault(); - // sidebar.classList.toggle("active"); - activeToggle(); - }; - actualSidebar.addEventListener("animationend", () => { - console.log("Animation ended", sidebar.classList); - if (sidebar.classList.contains("abouttodie")) { - sidebar.classList.remove("active"); - } - sidebar.classList.remove("showingup", "abouttodie"); - }); +import querySelectorAsync from "../utility/querySelectorAsync"; +import buildSidebar from "./buildSidebar"; + +export default async function buildSubredditSidebar() { + const body = await querySelectorAsync("body"); + const actualSidebar = await querySelectorAsync("body > .side"); + actualSidebar.remove(); + + const [activeToggle, sidebar] = buildSidebar( + actualSidebar, + "custom-sidebar", + "custom-sidebar-close", + false + ); + + body.appendChild(sidebar); return [activeToggle, sidebar]; } diff --git a/js/sidebar/user_sidebar.js b/js/sidebar/user_sidebar.js index 98c826d..ba042c7 100644 --- a/js/sidebar/user_sidebar.js +++ b/js/sidebar/user_sidebar.js @@ -1,5 +1,7 @@ import "~/css/userSidebar.css"; import localforage from "localforage"; +import querySelectorAsync from "../utility/querySelectorAsync"; +import buildSidebar from "./buildSidebar"; function createSidebarItem(text, link, icon, isActive) { const item = document.createElement("a"); @@ -27,22 +29,24 @@ function createSidebarItem(text, link, icon, isActive) { } return item; } -function createSidebarSep(text) { + +function createSidebarSubheading(text) { const item = document.createElement("p"); item.innerText = text; item.classList.add("sidebar-headline"); return item; } -function setupMultireddits(actualSidebar) { + +async function setupMultireddits(container) { + await querySelectorAsync(".multis"); const multis = document.querySelectorAll( '.multis > li > a:not([href="/r/multihub/"])' ); - console.log(multis); if (multis.length > 0) { - actualSidebar.appendChild(document.createElement("hr")); - actualSidebar.appendChild(createSidebarSep("Multireddits")); + container.appendChild(document.createElement("hr")); + container.appendChild(createSidebarSubheading("Multireddits")); for (const multi of multis) { - actualSidebar.appendChild( + container.appendChild( createSidebarItem( multi.innerText, multi.href, @@ -53,16 +57,11 @@ function setupMultireddits(actualSidebar) { } } } -async function setupSubreddits(actualSidebar) { + +async function setupSubreddits(container) { const age = parseInt(await localforage.getItem("subredditcache_age")); const now = Math.floor(Date.now() / 1000); const cached = JSON.parse(await localforage.getItem("subredditcache_act")); - console.log( - "cache test:", - age + 60 * 60 < now, - isNaN(age), - cached === null - ); let subs = []; if (age + 60 * 60 < now || isNaN(age) || cached === null) { console.log("Updating subreddit cache"); @@ -97,16 +96,16 @@ async function setupSubreddits(actualSidebar) { subs = cached; console.log("Subreddit cache is up to date, created at", age, subs); } - actualSidebar.appendChild(document.createElement("hr")); - actualSidebar.appendChild(createSidebarSep("Subreddits")); - actualSidebar.appendChild( + container.appendChild(document.createElement("hr")); + container.appendChild(createSidebarSubheading("Subreddits")); + container.appendChild( createSidebarItem("Random", "/r/random", "shuffle", false) ); - actualSidebar.appendChild( + container.appendChild( createSidebarItem("Random NSFW", "/r/randnsfw", "18_up_rating", false) ); for (const subreddit of subs) { - actualSidebar.appendChild( + container.appendChild( createSidebarItem( subreddit.data.display_name, subreddit.data.url, @@ -116,8 +115,12 @@ async function setupSubreddits(actualSidebar) { ); } } -function moveHeaderItems(actualSidebar) { - const rheader = document.getElementById("header-bottom-right"); + +async function buildHeaderItems(container) { + const rheader = await querySelectorAsync("#header-bottom-right"); + + container.appendChild(document.createElement("hr")); + const userlink = rheader.querySelector(".user a"); if (userlink.innerText.includes("Log in")) { const loginitem = createSidebarItem( @@ -127,14 +130,13 @@ function moveHeaderItems(actualSidebar) { false ); loginitem.addEventListener("click", () => { - const rheader = document.getElementById("header-bottom-right"); - const userlink = rheader.querySelector(".user a"); userlink.click(); }); - actualSidebar.appendChild(loginitem); + container.appendChild(loginitem); return; } - actualSidebar.appendChild( + + container.appendChild( createSidebarItem( userlink.text, userlink.href, @@ -142,12 +144,9 @@ function moveHeaderItems(actualSidebar) { location.href === userlink.href ) ); - const mail = document.getElementById("mail"); - let mailicon = "mark_email_unread"; - if (mail.classList.contains("nohavemail")) { - mailicon = "mail"; - } - actualSidebar.appendChild( + const mail = rheader.querySelector("#mail"); + let mailicon = mail.classList.contains("nohavemail") ? "mail" : "mark_email_unread"; + container.appendChild( createSidebarItem( "Messages", mail.href, @@ -156,7 +155,7 @@ function moveHeaderItems(actualSidebar) { ) ); const prefslink = "https://old.reddit.com/prefs/"; - actualSidebar.appendChild( + container.appendChild( createSidebarItem( "Preferences", prefslink, @@ -165,7 +164,7 @@ function moveHeaderItems(actualSidebar) { ) ); if (document.body.classList.contains("res")) { - actualSidebar.appendChild( + container.appendChild( createSidebarItem( "RES settings console", location.href + "#res:settings", @@ -181,56 +180,41 @@ function moveHeaderItems(actualSidebar) { false ); logoutItem.onclick = () => { - document.querySelector("form.logout a").click(); + rheader.querySelector("form.logout a").click(); }; - actualSidebar.appendChild(logoutItem); + container.appendChild(logoutItem); } -export default function setupSidebar() { - document.body.classList.remove("with-listing-chooser"); - const sidebar = document.createElement("div"); - const old_sidebar = document.getElementById("user_sidebar"); - if (old_sidebar !== null) { - old_sidebar.remove(); - } - document.body.appendChild(sidebar); - sidebar.id = "user-sidebar"; - function activeToggle(e) { - console.log("AT"); - if (e !== undefined) { - e.preventDefault(); - e.stopPropagation(); - } - if (sidebar.classList.contains("active")) { - sidebar.classList.add("abouttodie"); - } else { - sidebar.classList.add("active", "showingup"); - } - } - const actualSidebar = document.createElement("div"); - actualSidebar.innerHTML = ``; - sidebar.appendChild(actualSidebar); - actualSidebar.classList.add("side", "surface"); - actualSidebar.addEventListener("animationend", () => { - console.log("Animation ended", sidebar.classList); - if (sidebar.classList.contains("abouttodie")) { - sidebar.classList.remove("active"); - } - sidebar.classList.remove("showingup", "abouttodie"); - }); - const sb_close = document.createElement("div"); - sb_close.id = "user-sidebar-close"; - sb_close.onclick = activeToggle; - sidebar.appendChild(sb_close); +export default async function buildUserSidebar() { + const body = await querySelectorAsync("body"); + body.classList.remove("with-listing-chooser"); + + const innerSidebar = document.createElement("div"); + const [activeToggle, sidebar] = buildSidebar( + innerSidebar, + "user-sidebar", + "user-sidebar-close", + true + ); - actualSidebar.appendChild( + innerSidebar.innerHTML = ``; + innerSidebar.classList.add("side"); + innerSidebar.appendChild( createSidebarItem("Homepage", "/", "home", location.pathname == "/") ); - actualSidebar.appendChild(document.createElement("hr")); - moveHeaderItems(actualSidebar); + const headerItems = document.createElement("div"); + innerSidebar.appendChild(headerItems); + const multireddits = document.createElement("div"); + innerSidebar.appendChild(multireddits); + const subreddits = document.createElement("div"); + innerSidebar.appendChild(subreddits); + + // do not await, let the items load in in their own time + buildHeaderItems(headerItems); + setupMultireddits(multireddits); + setupSubreddits(subreddits); - setupMultireddits(actualSidebar); - setupSubreddits(actualSidebar); + body.appendChild(sidebar); return [activeToggle, sidebar]; } From 4f76511918dd6a2a01cc4709279b674c08ce6d1d Mon Sep 17 00:00:00 2001 From: faraplay Date: Fri, 7 Jul 2023 00:44:10 +0100 Subject: [PATCH 09/12] rename some sidebar files --- css/{subreddit_sidebar.css => subredditSidebar.css} | 0 js/sidebar/index.js | 4 ++-- js/sidebar/{subreddit_sidebar.js => subredditSidebar.js} | 2 +- js/sidebar/{user_sidebar.js => userSidebar.js} | 0 4 files changed, 3 insertions(+), 3 deletions(-) rename css/{subreddit_sidebar.css => subredditSidebar.css} (100%) rename js/sidebar/{subreddit_sidebar.js => subredditSidebar.js} (93%) rename js/sidebar/{user_sidebar.js => userSidebar.js} (100%) diff --git a/css/subreddit_sidebar.css b/css/subredditSidebar.css similarity index 100% rename from css/subreddit_sidebar.css rename to css/subredditSidebar.css diff --git a/js/sidebar/index.js b/js/sidebar/index.js index daec838..b2370e3 100644 --- a/js/sidebar/index.js +++ b/js/sidebar/index.js @@ -1,6 +1,6 @@ import "swiped-events"; -import buildSubredditSidebar from "./subreddit_sidebar.js"; -import buildUserSidebar from "./user_sidebar.js"; +import buildSubredditSidebar from "./subredditSidebar.js"; +import buildUserSidebar from "./userSidebar.js"; const eventListeners = { toggleUser: [], diff --git a/js/sidebar/subreddit_sidebar.js b/js/sidebar/subredditSidebar.js similarity index 93% rename from js/sidebar/subreddit_sidebar.js rename to js/sidebar/subredditSidebar.js index 0556675..abaa1ba 100644 --- a/js/sidebar/subreddit_sidebar.js +++ b/js/sidebar/subredditSidebar.js @@ -1,4 +1,4 @@ -import "~/css/subreddit_sidebar.css"; +import "~/css/subredditSidebar.css"; import querySelectorAsync from "../utility/querySelectorAsync"; import buildSidebar from "./buildSidebar"; diff --git a/js/sidebar/user_sidebar.js b/js/sidebar/userSidebar.js similarity index 100% rename from js/sidebar/user_sidebar.js rename to js/sidebar/userSidebar.js From 62e051786d6a168dee9992aed9f62bb3df18587b Mon Sep 17 00:00:00 2001 From: faraplay Date: Fri, 7 Jul 2023 01:06:45 +0100 Subject: [PATCH 10/12] make setupPosts wait for posts --- js/posts/index.js | 103 +++++++++++++++++++++++----------------------- 1 file changed, 51 insertions(+), 52 deletions(-) diff --git a/js/posts/index.js b/js/posts/index.js index 5ff7302..2d3a070 100644 --- a/js/posts/index.js +++ b/js/posts/index.js @@ -2,63 +2,62 @@ import setupNativeShare from "./nativeSharing.js"; import setupToggles from "./postToggles.js"; import expando from "./expando.js"; import "~/css/postIcons.css"; +import { waitForAllElements } from "../utility/waitForElement.js"; -export default function setupPosts() { - for (const post of document.querySelectorAll( - ".sitetable.linklisting > .thing:not(.riok)" - )) { - try { - setupNativeShare(post); - } catch (e) { - console.error("Failed to setup native share", e); - } - try { - setupToggles(post); - } catch (e) { - console.error("Failed to setup toggles", e); - } - // trim comments to only first word (comment count) - const comments = post.querySelector(".comments"); - if (comments !== null) { - comments.innerText = comments.innerText.split(" ")[0]; - if (comments.innerText.includes("comment")) { - comments.innerText = "0"; - } +function setupPost(post) { + try { + setupNativeShare(post); + } catch (e) { + console.error("Failed to setup native share", e); + } + try { + setupToggles(post); + } catch (e) { + console.error("Failed to setup toggles", e); + } + // trim comments to only first word (comment count) + const comments = post.querySelector(".comments"); + if (comments !== null) { + comments.innerText = comments.innerText.split(" ")[0]; + if (comments.innerText.includes("comment")) { + comments.innerText = "0"; } - const expando_btn = post.querySelector(".expando-button"); - if (expando_btn !== null) { - if ( - expando_btn.getAttribute("title") === "Expando is not yet ready" - ) { - const attrObserver = new MutationObserver((mutations) => { - mutations.forEach((mu) => { - if ( - mu.type !== "attributes" && - mu.attributeName !== "class" - ) - return; - console.log("class was modified!"); - expando(post); - attrObserver.disconnect(); - }); + } + const expando_btn = post.querySelector(".expando-button"); + if (expando_btn !== null) { + if (expando_btn.getAttribute("title") === "Expando is not yet ready") { + const attrObserver = new MutationObserver((mutations) => { + mutations.forEach((mu) => { + if ( + mu.type !== "attributes" && + mu.attributeName !== "class" + ) + return; + console.log("class was modified!"); + expando(post); + attrObserver.disconnect(); }); - console.log( - "Expando is not ready yet, setting up mutation observer for", - expando_btn - ); - attrObserver.observe(expando_btn, { attributes: true }); - } else { - expando(post); - } + }); + console.log( + "Expando is not ready yet, setting up mutation observer for", + expando_btn + ); + attrObserver.observe(expando_btn, { attributes: true }); + } else { + expando(post); } + } - // remove thumbnail no-image indicator. Could be done with CSS, but FF doesn't support :has. - const thumbnail = post.querySelector(".thumbnail"); - if (thumbnail !== null && thumbnail.children.length === 0) { - thumbnail.remove(); - } - post.classList.add("riok"); + // remove thumbnail no-image indicator. Could be done with CSS, but FF doesn't support :has. + const thumbnail = post.querySelector(".thumbnail"); + if (thumbnail !== null && thumbnail.children.length === 0) { + thumbnail.remove(); } + post.classList.add("riok"); +} + +export default function setupPosts() { + waitForAllElements(".sitetable.linklisting > .thing:not(.riok)", setupPost); } + setupPosts(); -window.addEventListener("neverEndingLoad", setupPosts); From 451dc2dfe64f7d1094ab3f25ab2c1353b93444c8 Mon Sep 17 00:00:00 2001 From: faraplay Date: Fri, 7 Jul 2023 01:17:34 +0100 Subject: [PATCH 11/12] make preferences formatting async --- js/preferences.js | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/js/preferences.js b/js/preferences.js index cae4a8c..191d2b6 100644 --- a/js/preferences.js +++ b/js/preferences.js @@ -1,12 +1,11 @@ -export function formatPrefTable() { - const table = document.querySelector("table.preftable"); - if (!table) { - return; - } +import querySelectorAsync from "./utility/querySelectorAsync"; + +export async function formatPrefTable() { + const table = await querySelectorAsync("table.preftable"); + const tableParent = table.parentNode; const prefDiv = document.createElement("div"); - tableParent.appendChild(prefDiv); - tableParent.removeChild(table); + tableParent.replaceChild(prefDiv, table); const tbody = table.firstChild; for (const row of tbody.childNodes) { const newRow = document.createElement("div"); @@ -22,4 +21,4 @@ export function formatPrefTable() { } } -formatPrefTable(); \ No newline at end of file +formatPrefTable(); From 1f7ac50aa184b601a76cfedfa149528ab0c36eef Mon Sep 17 00:00:00 2001 From: faraplay Date: Fri, 7 Jul 2023 01:25:09 +0100 Subject: [PATCH 12/12] run at document_start now that everything is async --- js/cs.js | 7 +------ webpack.config.js | 7 +------ 2 files changed, 2 insertions(+), 12 deletions(-) diff --git a/js/cs.js b/js/cs.js index c5fb56b..ebac246 100644 --- a/js/cs.js +++ b/js/cs.js @@ -1,7 +1,2 @@ import "./setPublicPath.js"; -import "./styling.js"; -import "./header.js"; -import "./sidebar"; -import "./posts"; -import "./preferences.js"; -console.log("Content script loaded."); +import "./user.js"; diff --git a/webpack.config.js b/webpack.config.js index f2eafc7..f6300b6 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -26,14 +26,10 @@ const manifest = { "https://raw.githubusercontent.com/OctoNezd/oldlander/chrome-ota/updates.xml", web_accessible_resources: ["riok_assets/*"], content_scripts: [ - { - matches: ["*://old.reddit.com/*"], - js: ["./viewport.js"], - run_at: "document_start", - }, { matches: ["*://old.reddit.com/*"], js: ["./cs.js", "./vendors.js"], + run_at: "document_start", }, ], browser_specific_settings: { @@ -78,7 +74,6 @@ module.exports = (env, argv) => { }, entry: { cs: "./js/cs.js", - viewport: "./js/viewport.js", }, output: { filename: "[name].js",