From 25d8e738b90c9ed349064b982d532ba240ada128 Mon Sep 17 00:00:00 2001 From: Guy Sandler Date: Wed, 20 May 2026 22:42:59 -0700 Subject: [PATCH] progress on modules --- js/content.js | 343 ++++++++++++++++++++++++++++++++------------------ js/popup.js | 4 +- 2 files changed, 224 insertions(+), 123 deletions(-) diff --git a/js/content.js b/js/content.js index 615ae76..417b664 100644 --- a/js/content.js +++ b/js/content.js @@ -6,6 +6,31 @@ function getCurrentCourseId() { return match ? parseInt(match[1]) : null; } +function getSidebarLayoutMode() { + if (current_page.match(/^\/courses\/(\d+)(?:\/|$)/)) return "course"; + if (current_page === "/" || current_page === "") return "dash"; + return "general"; +} + +function getSidebarStateMode(mode = getSidebarLayoutMode()) { + return mode === "course" ? "course" : "dashboard"; +} + +function getSidebarStateKey(mode = getSidebarLayoutMode()) { + return `better_sidebar_expanded_${getSidebarStateMode(mode)}`; +} + +async function getSidebarExpandedState(mode = getSidebarLayoutMode()) { + const key = getSidebarStateKey(mode); + const storage = await chrome.storage.local.get(key); + if (typeof storage[key] === "boolean") return storage[key]; + return mode === "course"; +} + +function setSidebarExpandedState(mode, expanded) { + chrome.storage.local.set({ [getSidebarStateKey(mode)]: expanded }); +} + let assignments = null; let grades = null; let announcements = []; @@ -14,6 +39,7 @@ let assignmentsDue = []; let options = {}; let timeCheck = null; let reminderCheck = null; +let betterSidebarLoading = false; //let assignmentData = null; /* @@ -269,6 +295,7 @@ function startExtension() { changeFavicon(); updateReminders(); applyCustomBackground(); + ensureBetterSidebar(); //getClassAverages(); @@ -403,20 +430,17 @@ function applyOptionsChanges(changes) { window.location.reload(); } case "better_sidebar": - if (options.better_sidebar) setupBetterSidebar(); - // else window.location.reload(); - else { - document.getElementById("header").style.display = "block"; - document.querySelector(".ic-Layout-wrapper")?.style.setProperty("margin-left", "54px"); - document.getElementById("better-sidebar-container").remove(); - } + if (options.better_sidebar) { + ensureBetterSidebar(); + } else { + resetBetterSidebarLayout(); + } break; case "sidebar_scale": { const existingSidebar = document.getElementById("better-sidebar-container"); if (existingSidebar) { - existingSidebar.remove(); - const mode = current_page.match(/^\/courses\/(\d+)\/?$/) ? "course" : "dash"; - setupBetterSidebar(mode); + const expander = existingSidebar.querySelector(".better-sidebar-expander"); + updateSidebar(existingSidebar.dataset.expanded === "true", existingSidebar, expander); } break; } @@ -424,6 +448,27 @@ function applyOptionsChanges(changes) { }); } +function resetBetterSidebarLayout() { + document.getElementById("header")?.style.removeProperty("display"); + document.querySelector(".ic-Layout-wrapper")?.style.removeProperty("margin-left"); + document.querySelector("#main")?.style.removeProperty("margin-left"); + document.querySelector(".ic-app-nav-toggle-and-crumbs")?.style.removeProperty("display"); + document.querySelector(".ic-Layout-contentWrapper")?.style.removeProperty("display"); + document.querySelector(".ic-Layout-contentWrapper")?.style.removeProperty("align-items"); + document.querySelector(".ic-Layout-contentWrapper")?.style.removeProperty("min-width"); + document.querySelector(".ic-Layout-contentMain")?.style.removeProperty("flex"); + document.querySelector(".ic-Layout-contentMain")?.style.removeProperty("min-width"); + document.getElementById("left-side")?.style.removeProperty("display"); + document.getElementById("better-sidebar-container")?.remove(); +} + +function ensureBetterSidebar() { + if (!options.better_sidebar) return; + if (document.querySelector("#better-sidebar-container")) return; + if (!document.querySelector("#wrapper") || !document.querySelector(".ic-Layout-contentWrapper")) return; + setupBetterSidebar(getSidebarLayoutMode()); +} + function applyCustomBackground() { // let style = document.querySelector("#DashboardCard_Container") let style = document.querySelector("#bettercanvas-background") || document.createElement('style'); @@ -446,6 +491,52 @@ function applyCustomBackground() { backdrop-filter: blur(10px) !important; border-radius: 5px; } + .header-bar, + .item-group-condensed, + .item-group-container { + background: transparent !important; + background-color: transparent !important; + backdrop-filter: blur(14px) saturate(120%) !important; + -webkit-backdrop-filter: blur(14px) saturate(120%) !important; + border-radius: 12px !important; + box-shadow: 0 8px 24px rgba(0, 0, 0, 0.12) !important; + } + .item-group-condensed .ig-header, + .item-group-condensed .ig-row, + .item-group-container .ig-header, + .item-group-container .ig-row, + .item-group-condensed .header, + .item-group-container .header { + background: transparent !important; + background-color: transparent !important; + backdrop-filter: blur(14px) saturate(120%) !important; + -webkit-backdrop-filter: blur(14px) saturate(120%) !important; + } + .item-group-condensed .context_module_item, + .item-group-container .context_module_item { + background: transparent !important; + background-color: transparent !important; + backdrop-filter: blur(10px) saturate(115%) !important; + -webkit-backdrop-filter: blur(10px) saturate(115%) !important; + } + .item-group-condensed .context_module_item:hover, + .item-group-container .context_module_item:hover, + .item-group-condensed .context_module_item.context_module_item_hover, + .item-group-container .context_module_item.context_module_item_hover { + background: transparent !important; + background-color: transparent !important; + backdrop-filter: blur(16px) saturate(130%) !important; + -webkit-backdrop-filter: blur(16px) saturate(130%) !important; + border-radius: 10px !important; + } + .item-group-container { + background: transparent !important; + background-color: transparent !important; + backdrop-filter: blur(10px) !important; + -webkit-backdrop-filter: blur(10px) !important; + border-radius: 12px !important; + border: 1px solid color-mix(in srgb, var(--bcborders) 75%, transparent) !important; + } .bettercanvas-gpa-card {background: var(--bcbackground-0) !important;} .bettercanvas-gpa {background: var(--bcbackground-0) !important;} .ic-DashboardCard {background: var(--bcbackground-0) !important;}`; // todo: liquid glass? @@ -472,49 +563,47 @@ function resetTimer() { } function checkDashboardReady() { - let callback; - if (current_page == "/" || current_page == "") { - console.log("I am dashboard"); - callback = (mutationList) => { - for (const mutation of mutationList) { - if (mutation.type === "childList") { - if (mutation.target == document.querySelector("#DashboardCard_Container")) { - let cards = document.querySelectorAll('.ic-DashboardCard'); - changeGradientCards(); - setupCardAssignments(); - loadCardAssignments(); - customizeCards(cards); - insertGrades(); - loadDashboardNotes(); - setupGPACalc(); - showUpdateMsg(); - } else if (mutation.target == document.querySelector('#right-side')) { - if (!mutation.target.querySelector(".bettercanvas-todosidebar")) { - setupBetterTodo(); - setupBetterSidebar(); - // loadBetterTodo(); - } - } - } - } - }; - } - // else return; - else { // all outside dashboard - console.log("I am outside", current_page); - if (current_page.match(/^\/courses\/(\d+)\/?$/)) { // course main pages - callback = (mutationList) => { - for (const mutation of mutationList) { - if (mutation.target == document.querySelector('#right-side')) { - if (!mutation.target.querySelector(".bettercanvas-todosidebar")) { - setupBetterTodo(); - setupBetterSidebar("course"); - } - } - } - }; - } - } + const callback = (mutationList) => { + for (const mutation of mutationList) { + if (mutation.type !== "childList") continue; + if (current_page == "/" || current_page == "") { + console.log("I am dashboard"); + if (mutation.target == document.querySelector("#DashboardCard_Container")) { + let cards = document.querySelectorAll('.ic-DashboardCard'); + changeGradientCards(); + setupCardAssignments(); + loadCardAssignments(); + customizeCards(cards); + insertGrades(); + loadDashboardNotes(); + setupGPACalc(); + showUpdateMsg(); + } else if (mutation.target == document.querySelector('#right-side')) { + if (!mutation.target.querySelector(".bettercanvas-todosidebar")) { + setupBetterTodo(); + setupBetterSidebar(); + // loadBetterTodo(); + } + } + } else if (current_page.match(/^\/courses\/(\d+)(?:\/|$)/)) { + if (mutation.target == document.querySelector('#right-side')) { + if (!mutation.target.querySelector(".bettercanvas-todosidebar")) { + setupBetterTodo(); + setupBetterSidebar(getSidebarLayoutMode()); + } + } + } else { + console.log("I am outside", current_page); + if (options.better_sidebar) { + ensureBetterSidebar(); + } + } + + if (options.better_sidebar) { + ensureBetterSidebar(); + } + } + }; const observer = new MutationObserver(callback); observer.observe(document.querySelector('html'), { childList: true, subtree: true }); @@ -1362,83 +1451,90 @@ function applySidebarScaleStyles(sidebarList) { sidebarList.style.setProperty("--bc-sidebar-label-size", `${Math.round(14 * scale)}px`); } -function setupBetterSidebar(mode = "dash") { +async function setupBetterSidebar(mode = getSidebarLayoutMode()) { if (!options.better_sidebar) return; if (document.querySelector('#better-sidebar-container')) return; let wrapper = document.querySelector("#wrapper"); - if (!wrapper) return; + if (!wrapper || betterSidebarLoading) return; + betterSidebarLoading = true; try { - const mainWrapper = document.querySelector(".ic-Layout-contentWrapper"); - let courseLinks; - let expanded = false; - if (mode == "dash") { - document.getElementById("header").style.display = "none"; - document.querySelector(".ic-Layout-wrapper")?.style.setProperty("margin-left", "0"); - mainWrapper.style.display = "flex"; - } - else if (mode == "course") { - document.getElementById("header").style.display = "none"; - document.querySelector(".ic-Layout-wrapper")?.style.setProperty("margin-left", "0"); - document.querySelector("#main")?.style.setProperty("margin-left", "0"); - // document.getElementById("not_right_side").style.display = "flex"; - mainWrapper.style.display = "flex"; - document.querySelector(".ic-Layout-contentMain").style.flex = "1"; - document.querySelector(".ic-Layout-contentMain").style.minWidth = "0"; - courseLinks = getCourseLinks(); - document.querySelector(".ic-app-nav-toggle-and-crumbs").style.display = "none"; - const leftSide = document.getElementById("left-side"); - if (leftSide) leftSide.style.display = "none"; - expanded = true; - } + const layoutMode = mode === "course" || mode === "dash" ? mode : getSidebarLayoutMode(); + const mainWrapper = document.querySelector(".ic-Layout-contentWrapper"); + if (!mainWrapper) return; + let courseLinks; + let expanded = await getSidebarExpandedState(layoutMode); + mainWrapper.style.display = "flex"; + mainWrapper.style.alignItems = "stretch"; + mainWrapper.style.minWidth = "0"; + if (layoutMode == "dash") { + document.getElementById("header")?.style.setProperty("display", "none"); + document.querySelector(".ic-Layout-wrapper")?.style.setProperty("margin-left", "0"); + } + else if (layoutMode == "course") { + document.getElementById("header")?.style.setProperty("display", "none"); + document.querySelector(".ic-Layout-wrapper")?.style.setProperty("margin-left", "0"); + document.querySelector("#main")?.style.setProperty("margin-left", "0"); + const contentMain = document.querySelector(".ic-Layout-contentMain"); + if (contentMain) { + contentMain.style.flex = "1"; + contentMain.style.minWidth = "0"; + } + courseLinks = getCourseLinks(); + document.querySelector(".ic-app-nav-toggle-and-crumbs")?.style.setProperty("display", "none"); + const leftSide = document.getElementById("left-side"); + if (leftSide) leftSide.style.display = "none"; + } let sidebarList = makeElement("div", mainWrapper, { id: "better-sidebar-container", style: `display:flex;flex-direction:column;width:50px;justify-content:center;align-items:center;box-sizing:border-box;position:relative;background-color:var(--bcbackground-0);height:100vh;position:sticky;top:0;left:0;` }, true); - let sidebarContent = makeElement("div", sidebarList, { - style: "display:flex;flex-direction:column;gap:20px;width:100%;flex:1;justify-content:flex-start;align-items:center;margin:40px;" - }); + let sidebarContent = makeElement("div", sidebarList, { + style: "display:flex;flex-direction:column;gap:20px;width:100%;flex:1;justify-content:flex-start;align-items:center;margin:40px;" + }); applySidebarScaleStyles(sidebarList); - // Populate sidebar from Canvas navigation menu dynamically - populateSidebarFromNav(sidebarContent); + sidebarList.dataset.expanded = expanded ? "true" : "false"; + // Populate sidebar from Canvas navigation menu dynamically + populateSidebarFromNav(sidebarContent); - if (mode == "course") { - const courseLinksContainer = makeElement("div", sidebarContent, { - id: "better-course-links", - style: "display:flex;flex-direction:column;gap:12px;width:calc(100% - 16px);align-items:stretch;margin:15px 8px 0;padding:12px;border-radius:8px;background:linear-gradient(135deg, rgba(var(--bc-primary-rgb), 0.08) 0%, rgba(var(--bc-primary-rgb), 0.04) 100%);border:1px solid rgba(var(--bc-primary-rgb), 0.15);" - }); + if (layoutMode == "course") { + const courseLinksContainer = makeElement("div", sidebarContent, { + id: "better-course-links", + style: "display:flex;flex-direction:column;gap:12px;width:calc(100% - 16px);align-items:stretch;margin:15px 8px 0;padding:12px;border-radius:8px;background:linear-gradient(135deg, rgba(var(--bc-primary-rgb), 0.08) 0%, rgba(var(--bc-primary-rgb), 0.04) 100%);border:1px solid rgba(var(--bc-primary-rgb), 0.15);" + }); - if (courseLinks && courseLinks.length > 0) { - makeElement("div", courseLinksContainer, { - id: "better-course-links-title", - textContent: "Course Pages", - style: "font-size:11px;color:var(--bctext-0);margin:0;font-weight:600;white-space:nowrap;text-align:center;display:block;letter-spacing:0.5px;text-transform:uppercase;opacity:0.8;" - }) - makeElement("div", courseLinksContainer, { - style: "height:1px;background:linear-gradient(90deg, transparent, rgba(var(--bctext-0-rgb), 0.2), transparent);margin:2px 0;" - }) - courseLinks.forEach((link) => { - createSidebarButton( - link.name, - domain + link.url, - courseLinksContainer, - ` - - - - - - - - ` - ); - }); - } - } + if (courseLinks && courseLinks.length > 0) { + makeElement("div", courseLinksContainer, { + id: "better-course-links-title", + textContent: "Course Pages", + style: "font-size:11px;color:var(--bctext-0);margin:0;font-weight:600;white-space:nowrap;text-align:center;display:block;letter-spacing:0.5px;text-transform:uppercase;opacity:0.8;" + }) + makeElement("div", courseLinksContainer, { + style: "height:1px;background:linear-gradient(90deg, transparent, rgba(var(--bctext-0-rgb), 0.2), transparent);margin:2px 0;" + }) + courseLinks.forEach((link) => { + createSidebarButton( + link.name, + domain + link.url, + courseLinksContainer, + ` + + + + + + + + ` + ); + }); + } + } let expander = makeElement("div", sidebarList, { - style: "display:flex;flex-direction:column;gap:0px;margin-top:auto;width:100%;justify-content:center;align-items:center;cursor:pointer;", - }); + className: "better-sidebar-expander", + style: "display:flex;flex-direction:column;gap:0px;margin-top:auto;width:100%;justify-content:center;align-items:center;cursor:pointer;", + }); expander.innerHTML = ` @@ -1448,15 +1544,20 @@ function setupBetterSidebar(mode = "dash") { ` - updateSidebar(expanded, sidebarList, expander); - // const labels = document.querySelectorAll(".better-sidebar-label"); - // labels.forEach(label => label.style.display = "none"); - expander.addEventListener("click", () => { - expanded = !expanded; + updateSidebar(expanded, sidebarList, expander); + setSidebarExpandedState(layoutMode, expanded); + // const labels = document.querySelectorAll(".better-sidebar-label"); + // labels.forEach(label => label.style.display = "none"); + expander.addEventListener("click", () => { + expanded = !expanded; + sidebarList.dataset.expanded = expanded ? "true" : "false"; + setSidebarExpandedState(layoutMode, expanded); updateSidebar(expanded, sidebarList, expander); }) } catch (e) { logError(e); + } finally { + betterSidebarLoading = false; } } function createSidebarButton(text, url, parent, icon) { diff --git a/js/popup.js b/js/popup.js index ef799d1..22b15ed 100644 --- a/js/popup.js +++ b/js/popup.js @@ -55,7 +55,7 @@ const defaultOptions = { }, "new_install": true, "assignments_due": true, - "gpa_calc": true, + "gpa_calc": false, "dark_mode": true, "gradent_cards": false, "disable_color_overlay": false, @@ -65,7 +65,7 @@ const defaultOptions = { "num_assignments": 4, "custom_domain": [""], "assignments_done": [], - "dashboard_grades": true, + "dashboard_grades": false, "assignment_date_format": false, "dashboard_notes": false, "dashboard_notes_text": "",