mirror of
https://github.com/GuySandler/CanvasRefined.git
synced 2026-11-03 13:57:17 +01:00
todo list section collapse
This commit is contained in:
parent
1533b7af61
commit
cb2867bbb0
@ -1877,6 +1877,9 @@
|
||||
"todo_separate_scrollbar": {
|
||||
"message": "Separate Scrollbar"
|
||||
},
|
||||
"todo_sections_persist": {
|
||||
"message": "Remember collapsed sections"
|
||||
},
|
||||
"todo_show_scores": {
|
||||
"message": "Show assignment scores"
|
||||
},
|
||||
|
||||
@ -103,6 +103,15 @@
|
||||
#canvasrefined-todo-list, #canvasrefined-announcement-list {font-size: 12px}
|
||||
.canvasrefined-todo-container, .canvasrefined-todo-container:hover {color:#777}
|
||||
.canvasrefined-todo-container p {margin: 0!important;}
|
||||
/* Better Todo: collapsible due-date sections (chevron + live item count) */
|
||||
.better-todo-section-header {display:flex;align-items:center;gap:6px;font-size:12px;color:var(--bctext-0);cursor:pointer;user-select:none;}
|
||||
.better-todo-section-header:hover {color:var(--bclinks);}
|
||||
.better-todo-section-header .better-todo-chevron {flex:none;transform:rotate(90deg);transition:transform .2s ease;}
|
||||
.better-todo-dueheader.better-todo-collapsed .better-todo-section-header .better-todo-chevron {transform:rotate(0deg);}
|
||||
.better-todo-dueheader.better-todo-collapsed .todo-group-list {display:none!important;}
|
||||
/* count badge: theme "Background Alt" surface with the theme's Text Main number;
|
||||
in light mode (no --bc vars) it falls back to the dark-mode palette pill */
|
||||
.better-todo-section-count {flex:none;margin-left:auto;background:var(--bcbackground-1,#161616);color:var(--bctext-0,#f5f5f5);border-radius:8px;padding:1px 7px;font-size:10.5px;font-weight:700;}
|
||||
.canvasrefined-todo-icon svg {height: 18px; width: 18px;margin:0}
|
||||
.canvasrefined-todoitem-course {overflow: hidden; text-overflow: ellipsis;white-space: nowrap;}
|
||||
.canvasrefined-todoitem-title {font-size: 14px;font-weight:bold;display:inline;margin-top:2px;}
|
||||
|
||||
@ -333,6 +333,10 @@
|
||||
<input type="checkbox" id="todo_remove_icons" name="todo_remove_icons">
|
||||
<label for="todo_remove_icons" class="sub-text" data-i18n="todo_remove_icons">Remove icons</label>
|
||||
</div>
|
||||
<div class="sub-option">
|
||||
<input type="checkbox" id="todo_sections_persist" name="todo_sections_persist">
|
||||
<label for="todo_sections_persist" class="sub-text" data-i18n="todo_sections_persist">Remember collapsed sections</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@ -1288,6 +1288,13 @@ function applyOptionsChanges(changes) {
|
||||
case "custom_cards_3":
|
||||
customizeCards();
|
||||
break;
|
||||
case "todo_sections_persist":
|
||||
// Persistence is opt-in: the moment it turns on, adopt the session's collapses;
|
||||
// turned off, stored state stays put but is simply not read on the next load.
|
||||
if (options.todo_sections_persist === true) {
|
||||
chrome.storage.sync.set({ "todo_collapsed_sections": { ...todoCollapsedSections } });
|
||||
}
|
||||
break;
|
||||
case "todo_hr24":
|
||||
case "todo_separate_scrollbar":
|
||||
case "num_todo_items":
|
||||
@ -3818,10 +3825,20 @@ async function createTodoSections(location) {
|
||||
else if (key >= 7 && key < 30) label = replaceCountPlaceholder(getMsg("due_weeks", "Due <strong>{{COUNT}} weeks</strong>"), Math.floor(key / 7));
|
||||
else if (key == "30") label = getMsg("due_one_month", "Due <strong>1 month</strong>");
|
||||
else label = "<strong>" + dueGroupLabel(key) + "</strong>";
|
||||
makeElement("div", wrapper, {
|
||||
innerHTML: "<span>" + label + "</span>",
|
||||
style: "display:flex;flex-direction:column;gap:10px;font-size:12px;color:var(--bctext-0);"
|
||||
})
|
||||
// Clickable section header: chevron + label + live item count (user suggestion:
|
||||
// collapsible due-date sections with a per-section item indicator).
|
||||
const sectionHeader = makeElement("div", wrapper, { "className": "better-todo-section-header" });
|
||||
sectionHeader.setAttribute("role", "button");
|
||||
sectionHeader.setAttribute("tabindex", "0");
|
||||
sectionHeader.setAttribute("aria-expanded", "true");
|
||||
sectionHeader.innerHTML =
|
||||
'<svg class="better-todo-chevron" viewBox="0 0 24 24" width="10" height="10" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true"><path d="M9 6l6 6-6 6"/></svg>' +
|
||||
'<span class="better-todo-section-label">' + label + '</span>' +
|
||||
'<span class="better-todo-section-count" aria-hidden="true"></span>';
|
||||
sectionHeader.addEventListener("click", () => toggleTodoSection(key, wrapper));
|
||||
sectionHeader.addEventListener("keydown", (e) => {
|
||||
if (e.key === "Enter" || e.key === " ") { e.preventDefault(); toggleTodoSection(key, wrapper); }
|
||||
});
|
||||
|
||||
let listContainer = makeElement("div", wrapper, { className: "todo-group-list" });
|
||||
listContainer.style = "display:flex;flex-direction:column;gap:10px;";
|
||||
@ -3840,6 +3857,8 @@ async function createTodoSections(location) {
|
||||
populateAssignments(true);
|
||||
}
|
||||
|
||||
refreshTodoSections();
|
||||
|
||||
const feedbackElement = location.querySelector(".recent_feedback");
|
||||
|
||||
// populate progress rings placeholder (respect user toggle)
|
||||
@ -3954,6 +3973,61 @@ function clearTodoList() {
|
||||
});
|
||||
}
|
||||
|
||||
/*
|
||||
Collapsible due-date sections
|
||||
|
||||
The collapse state is session-only by default: it lives in todoCollapsedSections and
|
||||
dies with the reload. "Remember collapsed sections" (todo_sections_persist, off by
|
||||
default) seeds the map from chrome.storage once per load and writes every toggle
|
||||
back, so collapses survive reloads only while that checkbox is on.
|
||||
*/
|
||||
let todoCollapsedSections = {};
|
||||
let todoCollapsedSeeded = false;
|
||||
|
||||
function seedTodoCollapsedSections() {
|
||||
if (todoCollapsedSeeded) return;
|
||||
todoCollapsedSeeded = true;
|
||||
if (options.todo_sections_persist === true && options.todo_collapsed_sections && typeof options.todo_collapsed_sections === "object") {
|
||||
todoCollapsedSections = { ...options.todo_collapsed_sections };
|
||||
}
|
||||
}
|
||||
|
||||
function toggleTodoSection(key, wrapper) {
|
||||
const collapsed = !wrapper.classList.contains("better-todo-collapsed");
|
||||
applyTodoSectionCollapsed(key, wrapper, collapsed);
|
||||
if (collapsed) todoCollapsedSections[key] = true;
|
||||
else delete todoCollapsedSections[key];
|
||||
if (options.todo_sections_persist === true) {
|
||||
chrome.storage.sync.set({ "todo_collapsed_sections": { ...todoCollapsedSections } });
|
||||
}
|
||||
}
|
||||
|
||||
function applyTodoSectionCollapsed(key, wrapper, collapsed) {
|
||||
wrapper.classList.toggle("better-todo-collapsed", collapsed);
|
||||
const header = wrapper.querySelector(".better-todo-section-header");
|
||||
if (header) header.setAttribute("aria-expanded", collapsed ? "false" : "true");
|
||||
}
|
||||
|
||||
// Re-apply collapse state and refresh the per-section item counts after each render.
|
||||
// Headers are rebuilt on every render, so this is what carries the state across the
|
||||
// clearTodoList/createTodoSections cycle.
|
||||
function refreshTodoSections() {
|
||||
seedTodoCollapsedSections();
|
||||
Object.keys(domContainers).forEach(key => {
|
||||
const entry = domContainers[key];
|
||||
if (!entry || !entry.wrapper || !entry.wrapper.isConnected) return;
|
||||
const collapsed = todoCollapsedSections[key] === true;
|
||||
applyTodoSectionCollapsed(key, entry.wrapper, collapsed);
|
||||
// Every row the section holds (hidden "view more" rows included). The rows are
|
||||
// created with a `class:` property assignment that never becomes a real class
|
||||
// attribute, so query the list's children instead of the row classes; the
|
||||
// celebration preview's disposable card must not bump the count.
|
||||
const count = [...entry.listContainer.children].filter(el => el.id !== "canvasrefined-celebration-preview").length;
|
||||
const countEl = entry.wrapper.querySelector(".better-todo-section-count");
|
||||
if (countEl) countEl.textContent = count > 0 ? String(count) : "";
|
||||
});
|
||||
}
|
||||
|
||||
// "Alternate colors" (light mode only): icon fill goes white for lighter course strips.
|
||||
const TODO_ALT_ICON_COLOR = "#ffffff";
|
||||
let todoAltStyleEl = null;
|
||||
@ -5026,9 +5100,12 @@ function runCelebrationPreview() {
|
||||
wrapper: todayContainer.wrapper,
|
||||
display: todayContainer.wrapper.style.display,
|
||||
hadVisible: todayContainer.wrapper.hasAttribute("data-has-visible"),
|
||||
wasCollapsed: todayContainer.wrapper.classList.contains("better-todo-collapsed"),
|
||||
};
|
||||
todayContainer.wrapper.style.display = "block";
|
||||
todayContainer.wrapper.setAttribute("data-has-visible", "true");
|
||||
// A collapsed section would hide the preview card; expand it for the run.
|
||||
todayContainer.wrapper.classList.remove("better-todo-collapsed");
|
||||
} else {
|
||||
card.style.cssText += "position:fixed;top:70px;right:16px;width:300px;z-index:2147483646;box-shadow:0 2px 10px rgba(0,0,0,.25);";
|
||||
document.body.appendChild(card);
|
||||
@ -5046,6 +5123,7 @@ function runCelebrationPreview() {
|
||||
if (restoreWrapper) {
|
||||
try {
|
||||
restoreWrapper.wrapper.style.display = restoreWrapper.display;
|
||||
restoreWrapper.wrapper.classList.toggle("better-todo-collapsed", restoreWrapper.wasCollapsed);
|
||||
if (!restoreWrapper.hadVisible) restoreWrapper.wrapper.removeAttribute("data-has-visible");
|
||||
} catch (e) { /* wrapper re-rendered away already */ }
|
||||
}
|
||||
|
||||
@ -55,6 +55,7 @@ const syncedSubOptions = [
|
||||
"assignment_date_format",
|
||||
"todo_hr24",
|
||||
"todo_separate_scrollbar",
|
||||
"todo_sections_persist",
|
||||
"todo_alternate_colors",
|
||||
"todo_ignore_card_colors",
|
||||
"todo_remove_icons",
|
||||
@ -220,7 +221,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"];
|
||||
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 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,
|
||||
@ -335,6 +336,7 @@ const defaultOptions = {
|
||||
"card_opacity": 80,
|
||||
"card_blur": 8,
|
||||
"todo_hr24": false,
|
||||
"todo_sections_persist": false,
|
||||
"anon_grade_level": "high",
|
||||
"anon_grade_seed": 0,
|
||||
"anon_fake_todo": false,
|
||||
@ -2055,6 +2057,7 @@ async function setup() {
|
||||
"custom_font_skip_p",
|
||||
"todo_hr24",
|
||||
"todo_separate_scrollbar",
|
||||
"todo_sections_persist",
|
||||
"todo_alternate_colors",
|
||||
"todo_ignore_card_colors",
|
||||
"todo_remove_icons",
|
||||
|
||||
Loading…
Reference in New Issue
Block a user