diff --git a/js/content.js b/js/content.js
index fd16787..9fa4abe 100644
--- a/js/content.js
+++ b/js/content.js
@@ -1299,6 +1299,7 @@ function applyOptionsChanges(changes) {
break;
case "todo_hr24":
case "todo_separate_scrollbar":
+ case "todo_hide_filter_notice":
case "num_todo_items":
case "hover_preview":
case "todo_timeframe":
@@ -3671,6 +3672,23 @@ async function createTodoSections(location) {
${todayString}
`;
+ // "Filtered by course" chip: visible while the list is scoped to one class
+ // (clicking a progress ring/line). Click it to clear the filter.
+ const filterIndicator = makeElement("div", location, { id: "better-todo-filter-indicator" });
+ filterIndicator.style.cssText = "display:none;align-items:center;flex-wrap:nowrap;gap:6px;margin-top:8px;padding:4px 10px;border-radius:999px;background:var(--bcbackground-2);color:var(--bctext-0);font-size:11.5px;font-weight:600;cursor:pointer;width:100%;box-sizing:border-box;white-space:nowrap;user-select:none;transition:background .15s ease;";
+ filterIndicator.title = getMsg("todo_filter_clear", "Show all courses again");
+ filterIndicator.innerHTML =
+ '' +
+ '' + getMsg("todo_filter_active", "Filtered by course") + ':' +
+ '' +
+ '✕';
+ filterIndicator.addEventListener("click", () => {
+ if (betterTodoProgressFilter == null) return;
+ betterTodoProgressFilter = null;
+ const loc = document.querySelector("#canvasrefined-todo-list");
+ if (loc) { clearTodoList(); createTodoSections(loc); }
+ });
+
// Timeframe pager: arrows (or arrow keys while hovering) page the timeframe window.
const timeframeNav = makeElement("div", location, { id: "better-todo-timeframe-nav" });
timeframeNav.style = "display:none;align-items:center;justify-content:center;width:100%;margin-top:8px;user-select:none;";
@@ -3885,6 +3903,7 @@ async function createTodoSections(location) {
}
refreshTodoSections();
+ updateTodoFilterIndicator();
const feedbackElement = location.querySelector(".recent_feedback");
@@ -4055,6 +4074,24 @@ function refreshTodoSections() {
});
}
+// "Filtered by course" chip: shows/hides and re-labels after every todo render.
+// Hidden entirely when "Hide course filter notice" is checked.
+function updateTodoFilterIndicator() {
+ const el = document.getElementById("better-todo-filter-indicator");
+ if (!el) return;
+ const active = betterTodoProgressFilter != null && options.todo_hide_filter_notice !== true;
+ el.style.display = active ? "flex" : "none";
+ const nameEl = el.querySelector(".cr-todo-filter-name");
+ if (active && nameEl) nameEl.textContent = todoFilterCourseName(betterTodoProgressFilter);
+}
+
+// The name the user knows the course by: their chosen card name first, then the
+// Canvas full name, then the defaults (same precedence as the Cards tab).
+function todoFilterCourseName(courseId) {
+ const card = options.custom_cards?.[String(courseId)] || options.custom_cards?.[courseId];
+ return card?.name || card?.fullName || card?.default || card?.code || `Course ${courseId}`;
+}
+
// "Alternate colors" (light mode only): icon fill goes white for lighter course strips.
const TODO_ALT_ICON_COLOR = "#ffffff";
let todoAltStyleEl = null;
diff --git a/js/popup.js b/js/popup.js
index 4dc72d0..19b25bd 100644
--- a/js/popup.js
+++ b/js/popup.js
@@ -56,6 +56,7 @@ const syncedSubOptions = [
"todo_hr24",
"todo_separate_scrollbar",
"todo_sections_persist",
+ "todo_hide_filter_notice",
"todo_alternate_colors",
"todo_ignore_card_colors",
"todo_remove_icons",
@@ -221,7 +222,7 @@ const exportCardColorToggles = ["gradient_cards", "disable_color_overlay"];
const exportCardStyles = ["customCardStyles", "imageSize", "cardRoundness", "imageRoundness", "cardSpacing", "cardWidth", "cardHeight", "cardPadding", "card_grid", "card_grid_columns", "card_grid_rows", "card_grid_column_gap", "card_grid_row_gap", "card_grid_center_rows", "card_grid_flex"];
const exportLayout = ["full_width", "center_cards", "condensed_cards", "equal_height_cards", "remlogo", "hide_new_canvas", "hide_navbar", "hide_sidebar", "tab_icons"];
const exportSidebar = ["better_sidebar", "sidebar_scale"];
-const exportTodo = ["better_todo", "todo_hide_feedback", "todo_hide_read", "todo_full_height", "todo_celebrations_enabled", "todo_celebrations", "todo_celebration_amount", "todo_progress_rings", "todo_timeframe", "todo_timeframe_custom_past", "todo_timeframe_custom_future", "todo_hr24", "todo_separate_scrollbar", "todo_alternate_colors", "todo_ignore_card_colors", "todo_remove_icons", "todo_show_scores", "hover_preview", "todo_sections_persist"];
+const exportTodo = ["better_todo", "todo_hide_feedback", "todo_hide_read", "todo_full_height", "todo_celebrations_enabled", "todo_celebrations", "todo_celebration_amount", "todo_progress_rings", "todo_timeframe", "todo_timeframe_custom_past", "todo_timeframe_custom_future", "todo_hr24", "todo_separate_scrollbar", "todo_alternate_colors", "todo_ignore_card_colors", "todo_remove_icons", "todo_show_scores", "hover_preview", "todo_sections_persist", "todo_hide_filter_notice"];
const exportGpa = ["gpa_calc", "gpa_calc_prepend", "gpa_calc_cumulative", "gpa_calc_weighted", "gpa_calc_show_on_hover", "gpa_calc_align"];
// Widgets tab: every dashboard widget's layout (toggles, positions, heights, row
// heights, order, timer presets, quick link sizing). Personal data (quick link items,
@@ -337,6 +338,7 @@ const defaultOptions = {
"card_blur": 8,
"todo_hr24": false,
"todo_sections_persist": false,
+ "todo_hide_filter_notice": false,
"anon_grade_level": "high",
"anon_grade_seed": 0,
"anon_fake_todo": false,
@@ -2097,6 +2099,7 @@ async function setup() {
"todo_hr24",
"todo_separate_scrollbar",
"todo_sections_persist",
+ "todo_hide_filter_notice",
"todo_alternate_colors",
"todo_ignore_card_colors",
"todo_remove_icons",