xuhcc / mindstream

Task management app, built on todo.txt.
GNU General Public License v3.0
41 stars 6 forks source link

Add option to sort "no due date" items above "due date in the future" items, or dual pane (dates, no dates)? #16

Closed codingthat closed 1 year ago

codingthat commented 2 years ago

Hi!

This idea (title says it all) occurred to me that would make #12 mostly unnecessary in my case, because I could avoid daily having to move things I didn't get to to another day, and could use due dates only for hard deadlines of single-day items.

Currently, no due date means they end up where I don't see them, way at the bottom of a huge list of annual reminders for the rest of the year.

What do you think?

codingthat commented 2 years ago

Or I can see that becoming a problem the other way around, if there are too many dateless tasks. Maybe a dual pane option would be the way to go here...

codingthat commented 2 years ago

Here's a userscript for anyone who wants to try it out; works in Chromium only though due to the orphans hack:

// ==UserScript==
// @name        mindstream dual-column layout and other tweaks - localhost
// @namespace   Violentmonkey Scripts
// @match       http://localhost:8080/*
// @grant       GM_addStyle
// ==/UserScript==

(function() {

  GM_addStyle(`
  ms-task-list > .page {
    display:inline-block !important; /* full-width task rows */
  }
  ms-task-list > .page > .task > .task-body > .task-checkbox {
    min-width: 20px; /* disallow overly long task descriptions from narrowing the checkbox */
  }
  ms-task-list > .page > .task > .task-body > .task-text {
    height: 100% !important; /* allow overly long task descriptions to make task rows taller */
  }
  ms-task-list > .page > .task.first_undated {
    break-before: column;
  }
  `);

  const split_on_first_undated = (a,b) => {
    const page = document.querySelector('ms-task-list > .page');
    if (!page) return;
    const tasks = page.querySelectorAll('.task');
    if (!tasks.length) return;
    // document.querySelectorAll('.first_undated').forEach(e => { e.classList.remove('first_undated'); }); // this doesn't appear to help when switching views... :(
    for (let task of tasks) {
      if (task.querySelector('.task-body > .tags > .due-date')) continue;
      task.classList.add('first_undated');
      page.style.cssText = `
        column-count: 2;
        break-inside: avoid-column;
        orphans: 1; /* Chromium-specific hack, but this suddenly makes the manual column break work */
      `;
      return;
    }
  };

  const config = { childList: true, subtree: true };
  let bootstrap_observer;

  bootstrap_observer = new MutationObserver(split_on_first_undated);
  bootstrap_observer.observe(document.body, config);

})();

Note, it's not perfect, e.g. switching between a tag view and the main view results in a horizontal scrollbar and 3 columns for some reason. Also, completed tasks go into the second column regardless of where they really belong.

xuhcc commented 2 years ago

I use priorities to organize dateless tasks. By default my task list is sorted by date, but I switch to ordering by priority whenever I need to review my "someday" tasks.

xuhcc commented 2 years ago

When tasks are ordered by priority, dated tasks appear at the end of the list because they usually don't have priority setting.

codingthat commented 2 years ago

Ah, that's maybe where I use it differently...many of my tasks have both a date and a priority within the day. Otherwise makes sense though, thanks for explaining!