diff --git a/package.json b/package.json
index 65b4575..23a7065 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "task-checklist",
- "version": "5.1.1",
+ "version": "5.2",
"description": "A Warframe Task Checklist to track daily, weekly, and other tasks. Built with HTML, CSS, and vanilla JavaScript, processed with Vite.",
"type": "module",
"scripts": {
diff --git a/sources/css/critical.css b/sources/css/critical.css
index 1671e44..87775de 100644
--- a/sources/css/critical.css
+++ b/sources/css/critical.css
@@ -196,7 +196,7 @@ h1 {
font-size: 1.75rem;
}
}
-h2 {
+#checklist-container h2 {
color: var(--text-header);
cursor: pointer;
display: flex;
@@ -210,10 +210,10 @@ h2 {
margin-bottom: 0.25rem;
border-bottom: 1px solid var(--border-color);
}
-h2 > span:first-of-type {
+#checklist-container h2 > span:first-of-type {
flex-grow: 1;
}
-h2 .reset-time-local {
+#checklist-container h2 .reset-time-local {
font-size: 0.75rem;
font-weight: 400;
color: var(--text-secondary);
diff --git a/sources/css/style.css b/sources/css/style.css
index 21da5b2..73bc67d 100644
--- a/sources/css/style.css
+++ b/sources/css/style.css
@@ -23,6 +23,10 @@
/* display: none; by default, JS will make one visible */
}
+:where(label) {
+ cursor: pointer;
+}
+
/* --- Content Box Element Styling (Non-Critical Parts) --- */
h2:hover {
background-color: var(--section-header-hover-bg);
@@ -219,12 +223,12 @@ input[type="checkbox"]:indeterminate::after {
content: "\1F512\FE0E"; /* LOCK + VARIATION SELECTOR-15 (text presentation) */
color: var(--checkbox-lock-color);
}
-li.task-item {
+.task-item {
display: flex;
align-items: start;
margin-bottom: 0.5rem;
}
-li.parent-task-container {
+.parent-task-container {
display: flex;
flex-direction: column;
align-items: stretch;
@@ -296,7 +300,8 @@ li.parent-task-container {
opacity: 1;
color: var(--menu-close-btn-hover-color);
}
-#options-menu .menu-btn {
+#options-menu :is(.menu-btn, .menu-item) {
+ font-weight: 600;
display: block;
width: 100%;
text-align: left;
@@ -304,9 +309,13 @@ li.parent-task-container {
margin-right: 0;
margin-bottom: 0.75rem;
}
-#options-menu .menu-btn:last-child {
+#options-menu :is(.menu-btn, .menu-item):last-child {
margin-bottom: 0;
}
+#options-menu .checkbox-option {
+ display: flex;
+ align-items: start;
+}
/* Dialogs */
dialog {
@@ -318,6 +327,12 @@ dialog::backdrop {
backdrop-filter: var(--backdrop-filter);
}
+dialog hr {
+ border: none;
+ border-top: 1px solid var(--menu-panel-border);
+ margin: 1rem 0;
+}
+
@media (prefers-reduced-motion: no-preference) {
dialog {
--dialog-anim-duration: 0.15s;
@@ -377,8 +392,9 @@ body:not(.light-mode) img.icon-filter {
margin: 0;
}
-/* Collapsible Extra Task Info */
-.task-info-expander {
+/* Collapsible Stuff */
+.task-info-expander,
+.task-autohide-expander {
display: grid;
grid-template-rows: 1fr;
overflow: hidden;
@@ -389,7 +405,8 @@ body:not(.light-mode) img.icon-filter {
.task-item .checked .task-info-expander {
grid-template-rows: 0fr;
}
-.task-info-expander > div {
+.task-info-expander > div,
+.task-autohide-expander > div {
min-height: 0;
}
@@ -523,3 +540,45 @@ body:not(.light-mode) img.icon-filter {
text-decoration: underline dotted;
cursor: pointer;
}
+
+/* Hide completed tasks */
+body.hide-completed-tasks .task-autohide-expander:has(> .task-item > .checked),
+body.hide-completed-tasks .task-autohide-expander:has(> .parent-task-container > .parent-task-header > .checked) {
+ grid-template-rows: 0fr;
+ @media (prefers-reduced-motion: no-preference) {
+ transition: grid-template-rows 200ms 5s;
+ }
+ @media (prefers-reduced-motion: reduce) {
+ transition: grid-template-rows 0s 5s;
+ }
+
+ &::after {
+ background-color: color(from var(--checkbox-checked-bg) srgb r g b / 0.25);
+ width: 0;
+ }
+}
+body.hide-completed-tasks .task-autohide-expander > .task-item:has(> .checked) {
+ margin: 0;
+ @media (prefers-reduced-motion: no-preference) {
+ transition: margin 200ms 5s;
+ }
+ @media (prefers-reduced-motion: reduce) {
+ transition: margin 0s 5s;
+ }
+}
+/* countdown bar */
+.task-autohide-expander {
+ position: relative;
+}
+.task-autohide-expander::after {
+ position: absolute;
+ top: 0.125rem;
+ left: 1.75rem;
+ width: 100%;
+ height: 0.25rem;
+ border-radius: 0.125rem;
+ background-color: transparent;
+ content: "";
+ z-index: -1;
+ transition: width 5s linear;
+}
diff --git a/sources/index.html b/sources/index.html
index 4ee4988..ca0ccc4 100644
--- a/sources/index.html
+++ b/sources/index.html
@@ -151,6 +151,11 @@
Options
+
+
diff --git a/sources/js/app.js b/sources/js/app.js
index 2a0353f..3deb0bb 100644
--- a/sources/js/app.js
+++ b/sources/js/app.js
@@ -31,10 +31,10 @@ const dailyBackgroundImageIds = [
'bg-image-4',
// Add more IDs if you add more background image divs in HTML
];
-const APP_VERSION = "5.1.1";
+const APP_VERSION = "5.2";
const GIT_COMMIT_HASH_LONG = import.meta.env.VITE_GIT_COMMIT_HASH;
const GIT_COMMIT_HASH = GIT_COMMIT_HASH_LONG.slice(0,7);
-const WARFRAME_VERSION = "43.0.2";
+const WARFRAME_VERSION = "43.0.3";
const THEME_STORAGE_KEY = 'warframeChecklistTheme';
// only update DATA_STORAGE_KEY when the data storage format changes
@@ -66,7 +66,8 @@ _prepTasks();
let bodyElement, themeToggleButton, hamburgerButton, optionsMenu, resetDailyButton, resetWeeklyButton, resetButton,
unhideTasksButton, lastSavedTimestampElement, saveStatusElement, sectionToggles, dailyResetTimeElement,
weeklyResetTimeElement, errorDisplayElement, errorMessageElement, errorCloseButton, errorCopyButton,
- appVersionElement, gitHashElement, wfVersionElement, scheduleDialog, moreInfoDialog, backgroundDivs = [];
+ appVersionElement, gitHashElement, wfVersionElement, scheduleDialog, moreInfoDialog, backgroundDivs,
+ hideCompletedToggle = [];
// --- State Variables ---
@@ -86,7 +87,8 @@ let checklistData = {
manuallyHiddenSections: {},
lastTaskResetTimes: {},
notificationPreferences: {},
- notificationsSent: {}
+ notificationsSent: {},
+ hideCompletedTasks: false
};
let currentTheme = 'dark';
@@ -118,6 +120,7 @@ function initializeDOMElements() {
wfVersionElement = document.querySelector('.warframe-version-text');
scheduleDialog = document.getElementById("cycle-schedule");
moreInfoDialog = document.getElementById("more-info");
+ hideCompletedToggle = document.getElementById("hide-completed");
backgroundDivs = [];
dailyBackgroundImageIds.forEach((id) => {
@@ -426,10 +429,13 @@ function showNotification(title, body) {
function createChecklistItem(task, isChecked, isSubtask = false) {
const isAvailable = calcTaskTimes(task, new Date()).isAvailable;
- const listItem = document.createElement('li');
- listItem.classList.add('task-item');
+ const listItem = document.createElement("li");
+ listItem.classList.add("task-autohide-expander");
+
+ const taskItem = document.createElement("div");
+ taskItem.classList.add("task-item");
if (checklistData.hiddenTasks[task.id]) {
- listItem.classList.add('hidden-task');
+ taskItem.classList.add("hidden-task");
}
// Checkbox
@@ -497,14 +503,14 @@ function createChecklistItem(task, isChecked, isSubtask = false) {
hideButton.addEventListener('click', (e) => {
e.stopPropagation();
checklistData.hiddenTasks[task.id] = true;
- listItem.classList.add('hidden-task');
- updateSectionControls(listItem.closest('section').id);
+ taskItem.classList.add("hidden-task");
+ updateSectionControls(taskItem.closest("section").id);
saveData(false);
});
controlsContainer.appendChild(hideButton);
if (task.subtasks) {
- listItem.classList.add('parent-task-container');
+ taskItem.classList.add("parent-task-container");
const parentHeaderDiv = document.createElement('div');
parentHeaderDiv.classList.add('parent-task-header');
@@ -533,7 +539,7 @@ function createChecklistItem(task, isChecked, isSubtask = false) {
parentHeaderDiv.appendChild(controlsContainer);
parentHeaderDiv.appendChild(collapseIcon);
- listItem.appendChild(parentHeaderDiv);
+ taskItem.appendChild(parentHeaderDiv);
// Subtasks
const subtaskCollapsible = document.createElement("div");
@@ -550,7 +556,7 @@ function createChecklistItem(task, isChecked, isSubtask = false) {
});
}
subtaskCollapsible.appendChild(subtaskList)
- listItem.appendChild(subtaskCollapsible);
+ taskItem.appendChild(subtaskCollapsible);
// On Click -> Collapse/Expand
parentHeaderDiv.addEventListener('click', (e) => {
@@ -613,10 +619,10 @@ function createChecklistItem(task, isChecked, isSubtask = false) {
// Info Line & Cycle Schedule
makeInfoLine(task, label);
- listItem.appendChild(checkbox);
- if (task.icon) { listItem.appendChild(icon); }
- listItem.appendChild(label);
- listItem.appendChild(controlsContainer);
+ taskItem.appendChild(checkbox);
+ if (task.icon) { taskItem.appendChild(icon); }
+ taskItem.appendChild(label);
+ taskItem.appendChild(controlsContainer);
// Checkbox Changed
checkbox.addEventListener("change", (event) => {
@@ -653,6 +659,7 @@ function createChecklistItem(task, isChecked, isSubtask = false) {
saveData();
});
}
+ listItem.appendChild(taskItem);
return listItem;
}
@@ -1079,11 +1086,12 @@ function loadData() {
checklistData.lastTaskResetTimes = parsedData.lastTaskResetTimes || {};
checklistData.notificationPreferences = parsedData.notificationPreferences || {};
checklistData.notificationsSent = parsedData.notificationsSent || {};
+ checklistData.hideCompletedTasks = parsedData.hideCompletedTasks || false;
} else { console.warn("Invalid data format found in localStorage. Starting fresh."); }
} catch (e) {
console.error("Error parsing saved data:", e);
displayError("Failed to load saved progress. Data might be corrupted.");
- checklistData = { progress: {}, lastSaved: null, lastDailyReset: null, lastWeeklyReset: null, hiddenTasks: {}, manuallyHiddenSections: {}, lastTaskResetTimes: {}, notificationPreferences: {}, notificationsSent: {} };
+ checklistData = { progress: {}, lastSaved: null, lastDailyReset: null, lastWeeklyReset: null, hiddenTasks: {}, manuallyHiddenSections: {}, lastTaskResetTimes: {}, notificationPreferences: {}, notificationsSent: {}, hideCompletedTasks: false };
}
}
}
@@ -1112,6 +1120,17 @@ export function loadAndInitializeApp() {
if (wfVersionElement) { wfVersionElement.textContent = `Warframe Version ${WARFRAME_VERSION}`; }
else { console.error("Warframe version element not found!"); }
+ if (hideCompletedToggle) {
+ hideCompletedToggle.addEventListener("change", (event) => {
+ bodyElement.classList.toggle("hide-completed-tasks", event.target.checked);
+ checklistData.hideCompletedTasks = event.target.checked;
+ saveData();
+ });
+ hideCompletedToggle.checked = checklistData.hideCompletedTasks;
+ bodyElement.classList.toggle("hide-completed-tasks", checklistData.hideCompletedTasks);
+ }
+ else { console.error("Hide Completed Toggle not found!"); }
+
if (resetDailyButton) { resetDailyButton.addEventListener('click', () => handleResetConfirmation(resetDailyButton, 'daily', 'Reset Daily Checks', resetDailyAction)); }
else { console.error("Reset Daily button element not found!"); }