diff --git a/css/popup.css b/css/popup.css index 95ad7d7..d305027 100644 --- a/css/popup.css +++ b/css/popup.css @@ -69,6 +69,10 @@ h2 {margin-top: 20px;font-weight:600} #todo_progress_rings option {background:#1e1e1e;color:#e2e2e2;} #todo_progress_rings option:checked, #todo_progress_rings option:hover {background:#2e2e2e;color:#fff;} +#todo_timeframe {font-size: 12px;background: var(--inputbg);color:#e2e2e2;border:none;border-radius:7px;padding:6px 8px;font-family:inherit;width:100%;box-sizing:border-box;margin-top:2px;color-scheme:dark;} +#todo_timeframe option {background:#1e1e1e;color:#e2e2e2;} +#todo_timeframe option:checked, +#todo_timeframe option:hover {background:#2e2e2e;color:#fff;} #advanced-settings, #gpa-bounds-btn, #custom-font-btn, #customize-dark-btn, #card-colors-btn {width: 100%;} .back-btn {width: 120px;height:100%;margin-top:0} .big-button {border: none;border-radius: 7px;background: var(--containerbg);color: #fff;font-family: inherit;padding: 12px 10px;font-weight:600} diff --git a/html/popup.html b/html/popup.html index 10ac9e2..5c06f82 100644 --- a/html/popup.html +++ b/html/popup.html @@ -259,6 +259,16 @@ +
+ + +
diff --git a/js/content.js b/js/content.js index 578e52c..79c71a0 100644 --- a/js/content.js +++ b/js/content.js @@ -671,6 +671,10 @@ function applyOptionsChanges(changes) { ) setupCardAssignments(); loadCardAssignments(); + // The card overflow fix in applyAestheticChanges() depends on + // assignments_due, so re-run it when that option toggles to keep + // the overflow rule in sync without a page reload. + applyAestheticChanges(); break; case "custom_assignments": case "assignment_date_format": @@ -692,6 +696,7 @@ function applyOptionsChanges(changes) { case "todo_separate_scrollbar": case "num_todo_items": case "hover_preview": + case "todo_timeframe": // case "todo_overdues": case "todo_hide_feedback": case "todo_full_height": @@ -1524,6 +1529,17 @@ function updateIndicator(element) { } // better todo html betterTodoFilter = "tasks"; +// Timeframe filter for the upcoming Tasks tab. "all" = no limit; otherwise +// items are limited to those due on/before now+range (which also keeps +// overdue items). Only affects the Tasks (upcoming) tab; announcements and +// completed are unaffected because their dates are in the past. +let betterTodoTimeframe = "all"; +const BETTER_TODO_TIMEFRAME_DAYS = { + "1week": 7, + "2week": 14, + "month": 30, + "2month": 60, +}; // null = show every class; a string courseId = only that class's tasks. let betterTodoProgressFilter = null; let domContainers = {}; @@ -2656,6 +2672,15 @@ async function createTodoSections(location) { announcements = displayData.filter(item => item.plannable_type == "announcement"); assignmentsDue = displayData.filter(item => (item.plannable_type == "assignment" || item.plannable_type == "planner_note") && !item.submissions?.submitted && !item.planner_override?.marked_complete); completed = displayData.filter(item => (item.plannable_type == "assignment" || item.plannable_type == "planner_note") && (item.submissions?.submitted || item.planner_override?.marked_complete)); + // The timeframe is a persisted Better Todo List sub-option set in the + // popup. Read the current value each render so popup changes apply on + // the next render. Keeps items due on/before now+range (overdue items + // are before now, so they are kept too). Only the Tasks tab is affected. + betterTodoTimeframe = (options.todo_timeframe && Object.prototype.hasOwnProperty.call(BETTER_TODO_TIMEFRAME_DAYS, options.todo_timeframe)) ? options.todo_timeframe : "all"; + if (betterTodoTimeframe !== "all") { + const cutoff = Date.now() + (BETTER_TODO_TIMEFRAME_DAYS[betterTodoTimeframe] * 24 * 60 * 60 * 1000); + assignmentsDue = assignmentsDue.filter(item => new Date(item.plannable_date).getTime() <= cutoff); + } // console.log("assignments", assignmentsDue); // console.log("announcements", announcements); // console.log("completed", completed); @@ -5188,7 +5213,16 @@ function applyAestheticChanges() { // Content-sized cards plus the dashboard reflow loop trigger Firefox scroll // anchoring to yank the viewport back up while scrolling. A fixed height // (even the default 250px) keeps layout stable. - if (options.cardHeight !== undefined && options.cardHeight !== null && options.cardHeight !== "") style.textContent += `.ic-DashboardCard {height: ${options.cardHeight}px!important;}`; + if (options.cardHeight !== undefined && options.cardHeight !== null && options.cardHeight !== "") { + style.textContent += `.ic-DashboardCard {height: ${options.cardHeight}px!important;}`; + // Canvas sets overflow:hidden on .ic-DashboardCard. With a fixed + // height that clips the appended .canvasrefined-card-assignment area + // (the assignment rows live at the bottom of the card), making the + // .canvasrefined-assignment-link anchors unclickable for users with + // custom card styles enabled. Allow overflow so those rows stay + // visible and interactive when card assignments are shown. + if (options.assignments_due === true) style.textContent += `.ic-DashboardCard {overflow: visible!important;}`; + } } style.textContent += ".ic-app-nav-toggle-and-crumbs{display:none!important}"; diff --git a/js/popup.js b/js/popup.js index cb9de34..62d72c8 100644 --- a/js/popup.js +++ b/js/popup.js @@ -4,6 +4,7 @@ const syncedSubOptions = [ "todo_full_height", "todo_confetti", "todo_progress_rings", + "todo_timeframe", "device_dark", "relative_dues", "card_overdues", @@ -49,7 +50,7 @@ const exportCardColorToggles = ["gradient_cards", "disable_color_overlay"]; const exportCardStyles = ["customCardStyles", "imageSize", "cardRoundness", "cardSpacing", "cardWidth", "cardHeight"]; const exportLayout = ["full_width", "center_cards", "condensed_cards", "equal_height_cards", "remlogo", "hide_new_canvas", "hide_feedback", "tab_icons"]; const exportSidebar = ["better_sidebar", "sidebar_scale"]; -const exportTodo = ["better_todo", "todo_hide_feedback", "todo_full_height", "todo_confetti", "todo_progress_rings", "todo_hr24", "todo_separate_scrollbar", "todo_alternate_colors", "hover_preview"]; +const exportTodo = ["better_todo", "todo_hide_feedback", "todo_full_height", "todo_confetti", "todo_progress_rings", "todo_timeframe", "todo_hr24", "todo_separate_scrollbar", "todo_alternate_colors", "hover_preview"]; const exportGpa = ["gpa_calc", "gpa_calc_prepend", "gpa_calc_cumulative", "gpa_calc_weighted"]; const exportBackground = ["customBackgroundLink", "customBackgroundScale", "customBackgroundDaily", "customBackgroundNasaDaily", "fitImageToScreen", "bg_opacity", "sidebar_opacity", "bg_blur", "sidebar_blur"]; // Master "On/off toggles" = every visual toggle (no GPA, no dark-mode schedule, @@ -147,6 +148,7 @@ const defaultOptions = { "todo_hide_feedback": false, "todo_full_height": false, "todo_progress_rings": "rings", + "todo_timeframe": "all", "todo_confetti": true, "device_dark": false, "cumulative_gpa": { "name": "Cumulative GPA", "hidden": false, "weight": "dnc", "credits": 999, "gr": 3.21 }, @@ -308,6 +310,19 @@ function setupProgressRingsSelect(initial) { }); } +// Timeframe dropdown for the upcoming Tasks tab. Persisted so the Better Todo +// List remembers the selected range across sessions. +function setupTimeframeSelect(initial) { + const el = document.querySelector("#todo_timeframe"); + if (!el) return; + const allowed = ["all", "1week", "2week", "month", "2month"]; + let value = allowed.includes(initial) ? initial : "all"; + el.value = value; + el.addEventListener("change", function () { + chrome.storage.sync.set({ "todo_timeframe": this.value }); + }); +} + function setupAutoDarkInput(initial, time) { let el = document.querySelector('#' + time); el.value = initial.hour + ":" + initial.minute; @@ -963,6 +978,10 @@ function setup() { identifier: "todo_progress_rings", setup: (initial) => setupProgressRingsSelect(initial), }, + { + identifier: "todo_timeframe", + setup: (initial) => setupTimeframeSelect(initial), + }, ], }; @@ -1658,6 +1677,7 @@ function saveCurrentTheme() { "todo_full_height": current["todo_full_height"], "todo_confetti": current["todo_confetti"], "todo_progress_rings": current["todo_progress_rings"], + "todo_timeframe": current["todo_timeframe"], "todo_hr24": current["todo_hr24"], "todo_separate_scrollbar": current["todo_separate_scrollbar"], "better_sidebar": current["better_sidebar"],