diff --git a/README.md b/README.md index 4d2a20e..9437edf 100644 --- a/README.md +++ b/README.md @@ -60,7 +60,7 @@ Actually Better Canvas adds more with more to come! - Custom Background (by URL, theme compatible) - Popup UI revamp - NEW Better todo list -- better sidebar (beta) +- better sidebar ## Planned Features (by priority) - widgets (music, timer) @@ -89,6 +89,7 @@ Actually Better Canvas adds more with more to come! - flashcards - goals - Scheduled Reminder Popups +- simplified UI ## Community suggestions (maybe will be done at some point) - when opening assignments it will show you "if you get a 0 on this your grade will be _" diff --git a/js/content.js b/js/content.js index d248fac..cf0f656 100644 --- a/js/content.js +++ b/js/content.js @@ -16,6 +16,95 @@ function isGradesPage() { return /^\/courses\/\d+\/grades(?:\/|$)/.test(current_page); } +function getSubmissionAssignmentLink() { + const match = current_page.match(/^\/courses\/(\d+)\/assignments\/(\d+)\/submissions\/(\d+)(?:\/|$)/); + if (!match) return null; + return `${domain}/courses/${match[1]}/assignments/${match[2]}/`; +} + +let submissionPageButtonObserver = null; + +function addSubmissionPageButton() { + const assignmentLink = getSubmissionAssignmentLink(); + if (!assignmentLink) return; + const content = document.getElementById("content"); + if (!content || content.querySelector("#bettercanvas-assignment-return")) return; + + makeElement("a", content, { + id: "bettercanvas-assignment-return", + className: "bettercanvas-custom-btn", + href: assignmentLink, + textContent: "Back to Assignment", + style: "display:inline-flex;align-items:center;justify-content:center;align-self:flex-start;margin:0 0 12px 0;padding:10px 14px;text-decoration:none;font-weight:700;", + }, true); +} + +let sequenceFooterObserver = null; + +function isAssignmentPage() { + return /^\/courses\/\d+\/assignments(?:\/\d+)?(?:\/|$)/.test(current_page); +} + +function removeSequenceFooter() { + if (!isAssignmentPage()) return false; + const sequenceFooter = document.getElementById("sequence_footer"); + if (!sequenceFooter) return false; + sequenceFooter.remove(); + return true; +} + +function watchSequenceFooter() { + if (!isAssignmentPage()) return; + if (removeSequenceFooter()) return; + if (sequenceFooterObserver) return; + + sequenceFooterObserver = new MutationObserver(() => { + if (removeSequenceFooter() && sequenceFooterObserver) { + sequenceFooterObserver.disconnect(); + sequenceFooterObserver = null; + } + }); + + sequenceFooterObserver.observe(document.documentElement, { childList: true, subtree: true }); + setTimeout(() => { + if (sequenceFooterObserver) { + sequenceFooterObserver.disconnect(); + sequenceFooterObserver = null; + } + }, 10000); +} + +function ensureSubmissionPageButton() { + const assignmentLink = getSubmissionAssignmentLink(); + if (!assignmentLink) return false; + const content = document.getElementById("content"); + if (!content) return false; + if (content.querySelector("#bettercanvas-assignment-return")) return true; + addSubmissionPageButton(); + return Boolean(content.querySelector("#bettercanvas-assignment-return")); +} + +function watchSubmissionPageButton() { + if (!getSubmissionAssignmentLink()) return; + if (ensureSubmissionPageButton()) return; + if (submissionPageButtonObserver) return; + + submissionPageButtonObserver = new MutationObserver(() => { + if (ensureSubmissionPageButton() && submissionPageButtonObserver) { + submissionPageButtonObserver.disconnect(); + submissionPageButtonObserver = null; + } + }); + + submissionPageButtonObserver.observe(document.documentElement, { childList: true, subtree: true }); + setTimeout(() => { + if (submissionPageButtonObserver) { + submissionPageButtonObserver.disconnect(); + submissionPageButtonObserver = null; + } + }, 10000); +} + function getSidebarStateMode(mode = getSidebarLayoutMode()) { return mode === "course" ? "course" : "dashboard"; } @@ -306,6 +395,8 @@ function startExtension() { updateReminders(); applyCustomBackground(); ensureBetterSidebar(); + watchSequenceFooter(); + watchSubmissionPageButton(); //getClassAverages(); diff --git a/js/popup.js b/js/popup.js index 22b15ed..94976aa 100644 --- a/js/popup.js +++ b/js/popup.js @@ -30,6 +30,7 @@ const syncedSubOptions = [ "sidebar_scale", ]; const localSwitches = []; +const fontsDropdownStateKey = "fonts_dropdown_open"; //const apiurl = "http://localhost:3000"; const apiurl = "https://bettercanvas.diditupe.dev"; @@ -856,20 +857,29 @@ function setup() { sendFromPopup("updateBackground"); }); - document.getElementById("fontsDropdown").addEventListener("click", (e) => { + const applyFontsDropdownState = (isOpen) => { const el = document.getElementById("quick-fonts"); const el2 = document.getElementsByClassName("custom-font")[0]; const arrow = document.getElementById("fontsDropdownArrow"); - if (el.style.display === "none") { - el.style.display = "flex"; - el2.style.display = "block"; - arrow.style.transform = "rotate(180deg)"; + if (!el || !el2 || !arrow) return; + el.style.display = isOpen ? "flex" : "none"; + el2.style.display = isOpen ? "block" : "none"; + arrow.style.transform = isOpen ? "rotate(180deg)" : "rotate(0deg)"; + }; - } else { - el.style.display = "none"; - el2.style.display = "none"; - arrow.style.transform = "rotate(0deg)"; - } + chrome.storage.local.get([fontsDropdownStateKey], (storage) => { + const isOpen = storage[fontsDropdownStateKey] !== false; + applyFontsDropdownState(isOpen); + }); + + document.getElementById("fontsDropdown").addEventListener("click", () => { + const el = document.getElementById("quick-fonts"); + const el2 = document.getElementsByClassName("custom-font")[0]; + if (!el || !el2) return; + const isCurrentlyOpen = getComputedStyle(el).display !== "none" && getComputedStyle(el2).display !== "none"; + const nextOpen = !isCurrentlyOpen; + applyFontsDropdownState(nextOpen); + chrome.storage.local.set({ [fontsDropdownStateKey]: nextOpen }); }); }