popup organizing+2digit%+hide tasks when complete on card tasks

This commit is contained in:
Guy Sandler 2026-10-03 16:02:08 -07:00
parent 09b4ae61b0
commit d16a91e7c9
16 changed files with 171 additions and 71 deletions

View File

@ -75,7 +75,7 @@
"message": "Nur beim Hover anzeigen" "message": "Nur beim Hover anzeigen"
}, },
"card_letter": { "card_letter": {
"message": "Notenbuchstaben anzeigen" "message": "Notenbuchstaben anzeigen"
}, },
"due": { "due": {
"message": "Fällig" "message": "Fällig"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "Neues Canvas ausblenden" "message": "Neues Canvas ausblenden"
},
"hide_completed_cards": {
"message": "Abgeschlossene ausblenden"
} }
} }

View File

@ -337,5 +337,8 @@
}, },
"grade_analytics_zones": { "grade_analytics_zones": {
"message": "Colored grade zones" "message": "Colored grade zones"
},
"hide_completed_cards": {
"message": "Hide Completed"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "Mostrar solo al pasar el mouse" "message": "Mostrar solo al pasar el mouse"
}, },
"card_letter": { "card_letter": {
"message": "Mostrar letra de la nota" "message": "Mostrar letra de la nota"
}, },
"due": { "due": {
"message": "Pendiente" "message": "Pendiente"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "Ocultar nuevo Canvas" "message": "Ocultar nuevo Canvas"
},
"hide_completed_cards": {
"message": "Ocultar completadas"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "Afficher uniquement au survol" "message": "Afficher uniquement au survol"
}, },
"card_letter": { "card_letter": {
"message": "Afficher la note en lettres" "message": "Afficher la note en lettres"
}, },
"due": { "due": {
"message": "Exigible" "message": "Exigible"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "Masquer le nouveau Canvas" "message": "Masquer le nouveau Canvas"
},
"hide_completed_cards": {
"message": "Masquer les devoirs terminés"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "Mostra solo al passaggio del mouse" "message": "Mostra solo al passaggio del mouse"
}, },
"card_letter": { "card_letter": {
"message": "Mostra voto in lettere" "message": "Mostra voto in lettere"
}, },
"due": { "due": {
"message": "Dovuto" "message": "Dovuto"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "Nascondi nuovo Canvas" "message": "Nascondi nuovo Canvas"
},
"hide_completed_cards": {
"message": "Nascondi completati"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "ホバー時のみ表示" "message": "ホバー時のみ表示"
}, },
"card_letter": { "card_letter": {
"message": "成績をアルファベットで表示" "message": "成績をアルファベットで表示"
}, },
"due": { "due": {
"message": "期限" "message": "期限"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "新しい Canvas を非表示" "message": "新しい Canvas を非表示"
},
"hide_completed_cards": {
"message": "完了した課題を非表示"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "Mostrar apenas ao passar o mouse" "message": "Mostrar apenas ao passar o mouse"
}, },
"card_letter": { "card_letter": {
"message": "Mostrar nota em letra" "message": "Mostrar nota em letra"
}, },
"due": { "due": {
"message": "Devido" "message": "Devido"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "Ocultar novo Canvas" "message": "Ocultar novo Canvas"
},
"hide_completed_cards": {
"message": "Ocultar concluídas"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "Показывать только при наведении" "message": "Показывать только при наведении"
}, },
"card_letter": { "card_letter": {
"message": "Показывать буквенную оценку" "message": "Показывать буквенную оценку"
}, },
"due": { "due": {
"message": "Должный" "message": "Должный"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "Скрыть новый Canvas" "message": "Скрыть новый Canvas"
},
"hide_completed_cards": {
"message": "Скрыть выполненные"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "Visa endast vid svävning" "message": "Visa endast vid svävning"
}, },
"card_letter": { "card_letter": {
"message": "Visa bokstavsbetyg" "message": "Visa bokstavsbetyg"
}, },
"due": { "due": {
"message": "Förfaller" "message": "Förfaller"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "Dölj ny Canvas" "message": "Dölj ny Canvas"
},
"hide_completed_cards": {
"message": "Dölj färdiga"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "仅在悬停时显示" "message": "仅在悬停时显示"
}, },
"card_letter": { "card_letter": {
"message": "显示字母成绩" "message": "显示字母成绩"
}, },
"due": { "due": {
"message": "到期的" "message": "到期的"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "隐藏新版 Canvas" "message": "隐藏新版 Canvas"
},
"hide_completed_cards": {
"message": "隐藏已完成的作业"
} }
} }

View File

@ -75,7 +75,7 @@
"message": "仅在悬停时显示" "message": "仅在悬停时显示"
}, },
"card_letter": { "card_letter": {
"message": "顯示字母成績" "message": "顯示字母成績"
}, },
"due": { "due": {
"message": "到期的" "message": "到期的"
@ -253,5 +253,8 @@
}, },
"hide_new_canvas": { "hide_new_canvas": {
"message": "隱藏新版 Canvas" "message": "隱藏新版 Canvas"
},
"hide_completed_cards": {
"message": "隱藏已完成的作業"
} }
} }

View File

@ -84,6 +84,16 @@ h2 {margin-top: 20px;font-weight:600}
#todo_timeframe option {background:#1e1e1e;color:#e2e2e2;} #todo_timeframe option {background:#1e1e1e;color:#e2e2e2;}
#todo_timeframe option:checked, #todo_timeframe option:checked,
#todo_timeframe option:hover {background:#2e2e2e;color:#fff;} #todo_timeframe option:hover {background:#2e2e2e;color:#fff;}
/* Collapsible "More options" section for the Better Todo List sub-options */
.todo-more-options {margin-top: 7px;}
.todo-more-toggle {display: flex;align-items:center;gap:5px;font-size:12px;color:#a7a7a7;cursor:pointer;user-select:none;padding:3px 0;border-radius:5px;transition:color .1s;}
.todo-more-toggle:hover {color:#e2e2e2;}
.todo-more-toggle svg {flex:none;transition:transform .15s ease;}
.todo-more-options.expanded .todo-more-toggle svg {transform: rotate(90deg);}
.todo-more-toggle .todo-expanded-label {display:none;}
.todo-more-options.expanded .todo-expanded-label {display:inline;}
.todo-more-items {display:none;flex-direction:column;}
.todo-more-options.expanded .todo-more-items {display:flex;padding-left:2px;}
#advanced-settings, #gpa-bounds-btn, #custom-font-btn, #customize-dark-btn, #card-colors-btn {width: 100%;} #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} .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} .big-button {border: none;border-radius: 7px;background: var(--containerbg);color: #fff;font-family: inherit;padding: 12px 10px;font-weight:600}

View File

@ -122,6 +122,10 @@
<input type="checkbox" id="card_overdues" name="card_overdues"> <input type="checkbox" id="card_overdues" name="card_overdues">
<label for="card_overdues" class="sub-text" data-i18n="show_past_due">Show past due</label> <label for="card_overdues" class="sub-text" data-i18n="show_past_due">Show past due</label>
</div> </div>
<div class="sub-option">
<input type="checkbox" id="hide_completed_cards" name="hide_completed_cards">
<label for="hide_completed_cards" class="sub-text" data-i18n="hide_completed_cards">Hide completed</label>
</div>
<div class="sub-option"> <div class="sub-option">
<input type="checkbox" id="relative_dues" name="relative_dues"> <input type="checkbox" id="relative_dues" name="relative_dues">
<label for="relative_dues" class="sub-text" data-i18n="relative_due_dates">Relative due dates</label> <label for="relative_dues" class="sub-text" data-i18n="relative_due_dates">Relative due dates</label>
@ -268,26 +272,7 @@
<span class="option-name" data-i18n="better_todo">Better Todo List</span> <span class="option-name" data-i18n="better_todo">Better Todo List</span>
</div> </div>
<div class="sub-options"> <div class="sub-options">
<div class="sub-option"> <!-- Frequently-changed options stay visible; rarer ones live in the collapsible "More options" section below -->
<input type="checkbox" id="todo_separate_scrollbar" name="todo_separate_scrollbar">
<label for="todo_separate_scrollbar" class="sub-text" data-i18n="todo_separate_scrollbar">Separate Scrollbar</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_hr24" name="todo_hr24">
<label for="todo_hr24" class="sub-text" data-i18n="24hrformat">Use 24hr format</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_full_height" name="todo_full_height">
<label for="todo_full_height" class="sub-text" data-i18n="todo_full_height">Force Full Height</label> <!-- TO REMOVE and replace with full height -->
</div>
<div class="sub-option">
<input type="checkbox" id="hover_preview" name="hover_preview">
<label for="hover_preview" class="sub-text" data-i18n="hover_preview">Previews on hover</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_hide_feedback" name="todo_hide_feedback">
<label for="todo_hide_feedback" class="sub-text" data-i18n="todo_hide_feedback">Hide Recent Feedback</label>
</div>
<div class="sub-option" style="flex-direction:column;align-items:stretch;gap:4px;"> <div class="sub-option" style="flex-direction:column;align-items:stretch;gap:4px;">
<label for="todo_progress_rings" class="sub-text">Progress display</label> <label for="todo_progress_rings" class="sub-text">Progress display</label>
<select id="todo_progress_rings" name="todo_progress_rings"> <select id="todo_progress_rings" name="todo_progress_rings">
@ -309,34 +294,62 @@
</select> </select>
</div> </div>
<div class="sub-option"> <div class="sub-option">
<input type="checkbox" id="todo_confetti" name="todo_confetti"> <input type="checkbox" id="hover_preview" name="hover_preview">
<label for="todo_confetti" class="sub-text">Show confetti on complete</label> <label for="hover_preview" class="sub-text" data-i18n="hover_preview">Previews on hover</label>
</div>
<div class="sub-option" id="todo_alternate_colors_wrap" style="display:none;">
<input type="checkbox" id="todo_alternate_colors" name="todo_alternate_colors">
<label for="todo_alternate_colors" class="sub-text" data-i18n="todo_alternate_colors">Alternate colors</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_ignore_card_colors" name="todo_ignore_card_colors">
<label for="todo_ignore_card_colors" class="sub-text">Ignore card colors</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_hide_read" name="todo_hide_read">
<label for="todo_hide_read" class="sub-text">Hide read announcements</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_remove_icons" name="todo_remove_icons">
<label for="todo_remove_icons" class="sub-text">Remove icons</label>
</div> </div>
<div class="sub-option"> <div class="sub-option">
<input type="checkbox" id="todo_show_scores" name="todo_show_scores"> <input type="checkbox" id="todo_show_scores" name="todo_show_scores">
<label for="todo_show_scores" class="sub-text">Show assignment scores</label> <label for="todo_show_scores" class="sub-text">Show assignment scores</label>
</div> </div>
<div class="sub-option">
<input type="checkbox" id="todo_confetti" name="todo_confetti">
<label for="todo_confetti" class="sub-text">Show confetti on complete</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_hide_read" name="todo_hide_read">
<label for="todo_hide_read" class="sub-text">Hide read announcements</label>
</div>
<div style="margin-top: 5px"> <div style="margin-top: 5px">
<span class="sub-text" data-i18n="max_items">Max items to show: </span><span <span class="sub-text" data-i18n="max_items">Max items to show: </span><span
id="numTodoItems"></span> id="numTodoItems"></span>
<input type="range" min="1" max="12" id="numTodoItemsSlider"> <input type="range" min="1" max="12" id="numTodoItemsSlider">
</div> </div>
<div class="todo-more-options" id="todo-more-options">
<div class="todo-more-toggle" id="todo-more-toggle" role="button" tabindex="0" aria-expanded="false" aria-controls="todo-more-items">
<svg xmlns="http://www.w3.org/2000/svg" width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"><path stroke="none" d="M0 0h24v24H0z" fill="none"/><path d="M9 6l6 6l-6 6" /></svg>
<span data-i18n="more_options">More options</span>
</div>
<div class="todo-more-items" id="todo-more-items">
<div class="sub-option">
<input type="checkbox" id="todo_separate_scrollbar" name="todo_separate_scrollbar">
<label for="todo_separate_scrollbar" class="sub-text" data-i18n="todo_separate_scrollbar">Separate Scrollbar</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_hr24" name="todo_hr24">
<label for="todo_hr24" class="sub-text" data-i18n="24hrformat">Use 24hr format</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_full_height" name="todo_full_height">
<label for="todo_full_height" class="sub-text" data-i18n="todo_full_height">Force Full Height</label> <!-- TO REMOVE and replace with full height -->
</div>
<div class="sub-option">
<input type="checkbox" id="todo_hide_feedback" name="todo_hide_feedback">
<label for="todo_hide_feedback" class="sub-text" data-i18n="todo_hide_feedback">Hide Recent Feedback</label>
</div>
<div class="sub-option" id="todo_alternate_colors_wrap" style="display:none;">
<input type="checkbox" id="todo_alternate_colors" name="todo_alternate_colors">
<label for="todo_alternate_colors" class="sub-text" data-i18n="todo_alternate_colors">Alternate colors</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_ignore_card_colors" name="todo_ignore_card_colors">
<label for="todo_ignore_card_colors" class="sub-text">Ignore card colors</label>
</div>
<div class="sub-option">
<input type="checkbox" id="todo_remove_icons" name="todo_remove_icons">
<label for="todo_remove_icons" class="sub-text">Remove icons</label>
</div>
</div>
</div>
</div> </div>
</div> </div>
<div class="option-container"> <div class="option-container">

View File

@ -53,6 +53,7 @@ chrome.runtime.onInstalled.addListener(function () {
"grade_hover": false, "grade_hover": false,
"card_letter": true, "card_letter": true,
// "hide_completed": false, // "hide_completed": false,
"hide_completed_cards": false,
"num_todo_items": 10, "num_todo_items": 10,
"custom_font": { "link": "", "family": "" }, "custom_font": { "link": "", "family": "" },
"hover_preview": true, "hover_preview": true,

View File

@ -1071,6 +1071,10 @@ function applyOptionsChanges(changes) {
// Stretch or reset card heights in place instead of rebuilding rows. // Stretch or reset card heights in place instead of rebuilding rows.
equalizeCardHeights(); equalizeCardHeights();
break; break;
case "hide_completed_cards":
// Assignment elements are already preloaded; just re-filter the render.
loadCardAssignments();
break;
case "custom_cards": case "custom_cards":
customizeCards(); customizeCards();
// Hiding/unhiding a card changes which courses appear in the todo // Hiding/unhiding a card changes which courses appear in the todo
@ -9374,9 +9378,9 @@ function renderGaStats() {
// graded assignments (green climbing, red falling, grey steady). // graded assignments (green climbing, red falling, grey steady).
let trendVal = "-", trendColor = "var(--bctext-0)"; let trendVal = "-", trendColor = "var(--bctext-0)";
if (gaData.trend != null) { if (gaData.trend != null) {
if (gaData.trend > 0.05) { trendVal = "\u25B2 +" + gaData.trend.toFixed(1) + "%"; trendColor = "#16a34a"; } if (gaData.trend > 0.05) { trendVal = "\u25B2 +" + gaData.trend.toFixed(2) + "%"; trendColor = "#16a34a"; }
else if (gaData.trend < -0.05) { trendVal = "\u25BC " + gaData.trend.toFixed(1) + "%"; trendColor = "#dc2626"; } else if (gaData.trend < -0.05) { trendVal = "\u25BC " + gaData.trend.toFixed(2) + "%"; trendColor = "#dc2626"; }
else { trendVal = "\u25BA " + gaData.trend.toFixed(1) + "%"; trendColor = "var(--bctext-1)"; } else { trendVal = "\u25BA " + gaData.trend.toFixed(2) + "%"; trendColor = "var(--bctext-1)"; }
} }
// Grade goal card from the Final Calculator tab: the score needed on the // Grade goal card from the Final Calculator tab: the score needed on the
// final to hit the stored target grade. // final to hit the stored target grade.
@ -9387,11 +9391,11 @@ function renderGaStats() {
let val, color; let val, color;
if (needed <= 0) { val = "\u2713 Secured"; color = "#16a34a"; } if (needed <= 0) { val = "\u2713 Secured"; color = "#16a34a"; }
else if (needed > 100) { val = "Out of reach"; color = "#dc2626"; } else if (needed > 100) { val = "Out of reach"; color = "#dc2626"; }
else { val = "\u2265 " + needed.toFixed(1) + "%"; color = gaNeededColor(needed); } else { val = "\u2265 " + needed.toFixed(2) + "%"; color = gaNeededColor(needed); }
goalStat = stat("Final Exam", val, color); goalStat = stat("Final Exam", val, color);
} }
stats.innerHTML = stats.innerHTML =
stat("Overall grade", gaData.current == null ? "-" : gaData.current.toFixed(1) + "%") + stat("Overall grade", gaData.current == null ? "-" : gaData.current.toFixed(2) + "%") +
stat("Grade trend (last 5)", trendVal, trendColor) + stat("Grade trend (last 5)", trendVal, trendColor) +
stat("Graded", gaData.graded) + stat("Graded", gaData.graded) +
stat("Ungraded", gaData.ungraded) + stat("Ungraded", gaData.ungraded) +
@ -9511,12 +9515,12 @@ function renderGaCalculator() {
let head, sub; let head, sub;
if (needed <= 0) { if (needed <= 0) {
head = `<span style="font-size:20px;font-weight:700;color:#16a34a;">You're already there!</span>`; head = `<span style="font-size:20px;font-weight:700;color:#16a34a;">You're already there!</span>`;
sub = `Even a 0 on the final leaves you at <b>${withZero.toFixed(1)}%</b>, which is above your <b>${target}%</b> goal.`; sub = `Even a 0 on the final leaves you at <b>${withZero.toFixed(2)}%</b>, which is above your <b>${target}%</b> goal.`;
} else if (needed > 100) { } else if (needed > 100) {
head = `<span style="font-size:20px;font-weight:700;color:#dc2626;">Out of reach</span>`; head = `<span style="font-size:20px;font-weight:700;color:#dc2626;">Out of reach</span>`;
sub = `Even a perfect final only gets you to <b>${withPerfect.toFixed(1)}%</b>, which is below your <b>${target}%</b> goal.`; sub = `Even a perfect final only gets you to <b>${withPerfect.toFixed(2)}%</b>, which is below your <b>${target}%</b> goal.`;
} else { } else {
head = `<span style="font-size:20px;font-weight:700;color:${gaNeededColor(needed)};">You need ≥ ${needed.toFixed(1)}% on the final</span>`; head = `<span style="font-size:20px;font-weight:700;color:${gaNeededColor(needed)};">You need ≥ ${needed.toFixed(2)}% on the final</span>`;
sub = `You got this!`; sub = `You got this!`;
} }
box.innerHTML = head + `<div style="margin-top:6px;color:var(--bctext-1);font-size:13px;">${sub}</div>`; box.innerHTML = head + `<div style="margin-top:6px;color:var(--bctext-1);font-size:13px;">${sub}</div>`;
@ -9626,8 +9630,8 @@ function gaBuildHeatmapData() {
function gaHeatmapShowTip(tip, e, cell, avg) { function gaHeatmapShowTip(tip, e, cell, avg) {
const d = cell.date; const d = cell.date;
const rows = cell.items.map(p => const rows = cell.items.map(p =>
`<div style="margin-top:2px;color:var(--bctext-1);">${gaEscHtml(p.title)} — <b style="color:${gaHeatmapColor(p.pct)};">${p.pct.toFixed(1)}%</b></div>`).join(""); `<div style="margin-top:2px;color:var(--bctext-1);">${gaEscHtml(p.title)} — <b style="color:${gaHeatmapColor(p.pct)};">${p.pct.toFixed(2)}%</b></div>`).join("");
tip.innerHTML = `<b>${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}</b> — avg <b style="color:${gaHeatmapColor(avg)};">${avg.toFixed(1)}%</b><div style="margin-top:4px;font-size:11px;color:var(--bctext-1);">${cell.items.length} assignment${cell.items.length === 1 ? "" : "s"}:</div>${rows}`; tip.innerHTML = `<b>${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()}</b> — avg <b style="color:${gaHeatmapColor(avg)};">${avg.toFixed(2)}%</b><div style="margin-top:4px;font-size:11px;color:var(--bctext-1);">${cell.items.length} assignment${cell.items.length === 1 ? "" : "s"}:</div>${rows}`;
tip.style.display = "block"; tip.style.display = "block";
const host = tip.offsetParent || tip.parentNode; const host = tip.offsetParent || tip.parentNode;
const hostRect = host.getBoundingClientRect(); const hostRect = host.getBoundingClientRect();
@ -9850,7 +9854,7 @@ function gaDrawLine(canvas, tooltip) {
} }
// Y grid: 5 evenly spaced lines across the current range. // Y grid: 5 evenly spaced lines across the current range.
ctx.textAlign = "right"; ctx.textBaseline = "middle"; ctx.textAlign = "right"; ctx.textBaseline = "middle";
const decimals = (yMax - yMin) <= 10 ? 1 : 0; const decimals = (yMax - yMin) <= 1 ? 2 : (yMax - yMin) <= 10 ? 1 : 0;
for (let i = 0; i <= 5; i++) { for (let i = 0; i <= 5; i++) {
const v = yMin + (yMax - yMin) * (i / 5); const v = yMin + (yMax - yMin) * (i / 5);
const y = pad.t + (1 - (v - yMin) / (yMax - yMin)) * (h - pad.t - pad.b); const y = pad.t + (1 - (v - yMin) / (yMax - yMin)) * (h - pad.t - pad.b);
@ -10001,7 +10005,7 @@ function gaDrawLine(canvas, tooltip) {
} }
const p = pts[best]; const p = pts[best];
gaShowTooltip(tooltip, X(best), Y(p.grade), gaShowTooltip(tooltip, X(best), Y(p.grade),
`<b>${p.title}</b><br>Overall: ${p.grade == null ? "-" : p.grade.toFixed(1) + "%"}<br>This: ${p.score}/${p.points} (${p.pct.toFixed(1)}%)${p.due ? `<br>Due: ${p.due}` : ""}`); `<b>${p.title}</b><br>Overall: ${p.grade == null ? "-" : p.grade.toFixed(2) + "%"}<br>This: ${p.score}/${p.points} (${p.pct.toFixed(2)}%)${p.due ? `<br>Due: ${p.due}` : ""}`);
}; };
canvas._gaLeave = () => { canvas._gaLeave = () => {
tooltip.style.display = "none"; tooltip.style.display = "none";
@ -10149,7 +10153,7 @@ function gaComputeImagineTotal() {
// restates the real grade. // restates the real grade.
function gaImagineTotalHtml(pct) { function gaImagineTotalHtml(pct) {
const letter = gaLetterFor(pct); const letter = gaLetterFor(pct);
const pctText = pct == null || !isFinite(pct) ? "—" : pct.toFixed(1) + "%"; const pctText = pct == null || !isFinite(pct) ? "—" : pct.toFixed(2) + "%";
// The wrapper is an inline-flex row with align-items:center so the // The wrapper is an inline-flex row with align-items:center so the
// badge pill sits vertically centered with the grade text. No // badge pill sits vertically centered with the grade text. No
// flex-wrap: the narrow score cell would stack the items instead. // flex-wrap: the narrow score cell would stack the items instead.

View File

@ -11,6 +11,7 @@ const syncedSubOptions = [
"device_dark", "device_dark",
"relative_dues", "relative_dues",
"card_overdues", "card_overdues",
"hide_completed_cards",
"equal_height_cards", "equal_height_cards",
// "todo_overdues", // "todo_overdues",
"gpa_calc_prepend", "gpa_calc_prepend",
@ -174,6 +175,7 @@ const defaultOptions = {
}, },
// "todo_overdues": false, // "todo_overdues": false,
"card_overdues": false, "card_overdues": false,
"hide_completed_cards": false,
"relative_dues": false, "relative_dues": false,
"equal_height_cards": false, "equal_height_cards": false,
"hide_new_canvas": true, "hide_new_canvas": true,
@ -188,6 +190,7 @@ const defaultOptions = {
"todo_full_height": false, "todo_full_height": false,
"todo_progress_rings": "rings", "todo_progress_rings": "rings",
"todo_timeframe": "all", "todo_timeframe": "all",
"todo_more_expanded": false,
"todo_confetti": true, "todo_confetti": true,
"device_dark": false, "device_dark": false,
"cumulative_gpa": { "name": "Cumulative GPA", "hidden": false, "weight": "dnc", "credits": 999, "gr": 3.21 }, "cumulative_gpa": { "name": "Cumulative GPA", "hidden": false, "weight": "dnc", "credits": 999, "gr": 3.21 },
@ -375,6 +378,31 @@ function setupProgressRingsSelect(initial) {
}); });
} }
// Collapsible "More options" section for the Better Todo List sub-options.
// Persists whether it's expanded so the popup reopens in the same state.
function setupTodoMoreOptions(initial) {
const wrap = document.getElementById("todo-more-options");
const toggle = document.getElementById("todo-more-toggle");
if (!wrap || !toggle) return;
const setExpanded = (expanded) => {
wrap.classList.toggle("expanded", expanded === true);
toggle.setAttribute("aria-expanded", expanded === true ? "true" : "false");
};
setExpanded(initial === true);
const flip = () => {
const expanded = !wrap.classList.contains("expanded");
setExpanded(expanded);
chrome.storage.sync.set({ "todo_more_expanded": expanded });
};
toggle.addEventListener("click", flip);
toggle.addEventListener("keydown", (e) => {
if (e.key === "Enter" || e.key === " ") {
e.preventDefault();
flip();
}
});
}
// Timeframe dropdown for the upcoming Tasks tab. Persisted so the Better Todo // Timeframe dropdown for the upcoming Tasks tab. Persisted so the Better Todo
// List remembers the selected range across sessions. // List remembers the selected range across sessions.
function setupTimeframeSelect(initial) { function setupTimeframeSelect(initial) {
@ -857,6 +885,12 @@ function setupFeatureSearch(menu) {
if (node.style && node.style.display === "none") node.style.display = ""; if (node.style && node.style.display === "none") node.style.display = "";
node = node.parentElement; node = node.parentElement;
} }
// Expand the Better Todo "More options" collapsible if the target lives inside it.
const moreWrap = el.closest ? el.closest("#todo-more-options") : null;
if (moreWrap && !moreWrap.classList.contains("expanded")) {
const toggle = document.getElementById("todo-more-toggle");
if (toggle) toggle.click();
}
} }
function highlight(el) { function highlight(el) {
@ -1125,6 +1159,7 @@ function setup() {
"device_dark", "device_dark",
"relative_dues", "relative_dues",
"card_overdues", "card_overdues",
"hide_completed_cards",
"equal_height_cards", "equal_height_cards",
// "todo_overdues", // "todo_overdues",
"gpa_calc_prepend", "gpa_calc_prepend",
@ -1304,6 +1339,10 @@ function setup() {
identifier: "todo_timeframe", identifier: "todo_timeframe",
setup: (initial) => setupTimeframeSelect(initial), setup: (initial) => setupTimeframeSelect(initial),
}, },
{
identifier: "todo_more_expanded",
setup: (initial) => setupTodoMoreOptions(initial),
},
], ],
}; };