thombruce / toodles

βœ… A super simple todo app
https://toodles.thombruce.com/
GNU General Public License v3.0
0 stars 0 forks source link

Interactive tags #117

Closed thombruce closed 1 month ago

thombruce commented 1 month ago

closes #115 with some changes

We've gone with count: and time: as key values for our interactive tags, and we've gone with every: for now for defining repetition rules (but this is not yet implemented - will handle on separate issue).

This all feels the most semantically clear when parsing the text with your own eyes...

! Send out invites count:12
(A) Add interactive tags to #Toodles estimate:3h time:2h37m
Take out the recycling every:Wednesday

Note that time: tag does not respect the presence of an estimate: tag (maybe one day it will) and we still haven't implemented a target value for the count: tag either (e.g. count:12/30). But you could, as with my example including estimate: above, just denote this with your own custom tag:

! Send out invites count:12 of:30

We can't determine anyway whether your target value is a hard limit or a soft target, so doing anything additional to style the count: tag based on proximity may not be desirable. Still, we might implement support for a target value of the form count:12/30 in the near future, even if we don't do anything in response to exceeding that value.

As for every:, as I said we'll handle that separately. every: needs to trigger a response when the item is checked off. The item should probably also have a due date. Our rules will be pretty basic... When you check an item off, if that item has every: tag find the next valid date and create a new item that is a clone of this one with the due date updated for that future date.

But we still need to settle on a schedule syntax before handling that. I do like the idea of supporting... every:Tuesday (which finds the next Tuesday), every:Week (which finds the date one week from the current due date), but then we get to months and things get a little more complex... so maybe those are just conveniences I add in, and the more expansive syntax is one which already exists and fits the spec. Maybe.

By submitting this pull request, you agree to follow our Code of Conduct: https://github.com/thombruce/.github/blob/main/CODE_OF_CONDUCT.md


Internal use. Do not delete.

netlify[bot] commented 1 month ago

Deploy Preview for toodles canceled.

Name Link
Latest commit bc46f80875c4b1ad1bcd4597d7aa0d0791c3f9a0
Latest deploy log https://app.netlify.com/sites/toodles/deploys/66b659240e0bc100080f5bb8
github-actions[bot] commented 1 month ago

Coverage Summary for `./packages/web`

Status Category Percentage Covered / Total
🟒 Lines 69.78% / 60% 432 / 619
🟒 Statements 69.78% / 60% 432 / 619
🟒 Functions 62.5% / 60% 25 / 40
🟒 Branches 69.84% / 60% 44 / 63
File Coverage
File Stmts % Branch % Funcs % Lines Uncovered Lines
packages/web/src/components/ContextTag.vue 100% 100% 100% 100%
packages/web/src/components/HashTag.vue 20% 100% 0% 20% 4-15
packages/web/src/components/ProgressBar.vue 70.17% 66.66% 100% 70.17% 16-23, 26-34
packages/web/src/components/ProjectTag.vue 20% 100% 0% 20% 4-15
packages/web/src/components/TagTag.vue 71.42% 100% 0% 71.42% 6-7
packages/web/src/components/TodoItem.vue 80.7% 40% 28.57% 80.7% 21, 26-27, 33-40
packages/web/src/components/TodoList.vue 73.68% 100% 100% 73.68% 11-15
packages/web/src/components/TodoPriority.vue 20% 100% 0% 20% 4-15
packages/web/src/components/TodoText.vue 68.08% 60% 85.71% 68.08% 15-18, 21-25, 34-36, 40-42
packages/web/src/models/Todo.ts 89.65% 76.92% 100% 89.65% 35-41, 55-56
packages/web/src/plugins/dexie.ts 55.12% 100% 66.66% 55.12% 38-41, 45-55, 59-78
packages/web/src/plugins/lunr.ts 78.57% 100% 0% 78.57% 10-12
packages/web/src/plugins/timepiece.ts 71.42% 60% 50% 71.42% 14-19
packages/web/src/stores/todos.ts 72.57% 90% 83.33% 72.57% 21, 25, 29-31, 35-37, 41-43, 47-49, 53-55, 59-61, 65-67, 71-73, 77-79, 83-85, 89-91, 95-97, 103, 107-115
thombruce commented 1 month ago

Another problem...

If a timer is running, and we toggle focus... the timer is stopped and progress is lost. Technically I think an interval remains running which our instance becomes decoupled from.

We can infer that the same will happen when we toggle done or make any other changes to the todo item. It gets updated, the description is re-rendered and our timer appears to stop and lose our progress.

What we want is...

  1. Timer should just keep running when toggle is focused - it should not affect timing
  2. Timer should UPDATE and stop when we toggle done - it's a convenience; you've been tracking time, but this is done now - we record that time and stop the timer for you

How might we solve this?

I think it would be a good idea to move the timer logic (and counter logic too) onto the model. The model may need to validate that it contains only 0 or 1 timer tags, but if it did have one then a toggleTimer() function could activate the timer on the model, and we could check that it has an active timer when rendering the timer element.

This would also allow us to stopTimer() when we deleteTodo(), and the timer should then also stay active when we toggleFocus(). If it doesn't... we should be in a better place to try and fix it anyway.

This would also be a step in the right direction in terms of support for the every: tag, since that tags handling must be handled by the model anyway (it explicitly concerns other attributes).

thombruce commented 1 month ago

This is now working to a satisfactory standard. Timer and Count are both moved to the Todo model but mutated via the store... and these changes do seem to be reactive and reflected in the view. And I can now toggle todos done or focused, with the timers behaving appropriately...

Handling every: shouldn't be too hard... When a todo is toggled done, we create a clone with a new due date. This is going to have to be done by the store, since that's where we need to insert the new todo. So...

toggleTodoDone() needs to be aware of whether or not the todo is repeatable and/or respond to that information as given by the class. On the class, we toggleDone() and this stops the timer and updates the todo's state. It could yield an .every property, maybe even a .next which would provide the contextual clues that we need to clone it fresh with a new date. But that cloning does still need to be handled somehow.

Don't forget static methods exist too which can be called directly from the class. Could be useful for adding the cloning logic. Something like Todo.clone(otherTodo).

Figuring that out is going to be straightforward but fiddly, so I leave it to another issue.