Skip to content

Add action menu to meal categories#920

Open
Frylen wants to merge 22 commits intodavidhealey:masterfrom
Frylen:CategoryOptions
Open

Add action menu to meal categories#920
Frylen wants to merge 22 commits intodavidhealey:masterfrom
Frylen:CategoryOptions

Conversation

@Frylen
Copy link
Copy Markdown
Contributor

@Frylen Frylen commented Jul 18, 2025

This adds an action menu to the meal categories. It currently holds these actions:

  • Remove all items from meal: deletes all items in a meal category. This is a great time saver when planning meals and needing to remove items when the meal is not reaching specific goals and starting with a clean slate.
  • Move items to another meal: allows items of a meal category to be moved to another meal category. Especially useful when adding a lot of items to the wrong meal category. The user gets prompted with all their meal categories to move the items to.
  • Update timestamps: Allows to manually set the timestamps of the items in the meal category (all at once, no granular selection possible). This is also great for users who pre-plan their meal or add the items while cooking. Now these can be adjusted to better plan/time the breaks between meals. The pre-selected time is the current time and all hour cycles are supported.

All of these features are only enabled when there is at least one item in the meal category. The timestamp action is only visible when the user enabled "Show Timestamp" in the settings. Since the date part of the timestamp is retrieved from the entry timestamp instead of the item timestamp, this should also work when there was no timestamp saved (due to having the setting turned off).

The action menu can be opened with a button in the title bar of the accordion. Why a button? I tried to handle this with a taphold event, but the accordion opening/closing while holding results in a touchend event and thus never reaching the timeout for the taphold. The icon used is "MenuOpen" which seems fitting, but I am open to suggestions if anything seems like a better fit.

Some images pic_move pic_time_de pic_time_en pic_action_icon pic_action_disabled pic_action

Frylen added 2 commits July 18, 2025 15:03
Add an action menu icon to the meal category accordion. Clicking the icon opens an F7 action sheet with options to either remove all entries from the meal category or to move them to another meal category.
Add a new action menu item to let the user manually set the timestamp (hour & minute only) of all items in a meal category. This supports all hour cycles and thus different locales. The option does not exist if the user does not have "Show Timestamps" turned on and it is disabled when there are no items in the meal category.
@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 18, 2025

@davidhealey
Copy link
Copy Markdown
Owner

davidhealey commented Jul 18, 2025

This sounds very useful, thanks!

I don't like the use of the out-dent icon though. What about 3 dots instead?

more_horiz_24dp_E8EAED_FILL0_wght400_GRAD0_opsz24

Or the vertical version if that looks better

@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 18, 2025

I think the 3 dots look better than the vertical ones, but I'll add the one you prefer.
dots

@davidhealey
Copy link
Copy Markdown
Owner

Yeah I think it looks better, something still feels off to me though. I think it's a ux thing. @EmilJunker Any suggestions?

@EmilJunker
Copy link
Copy Markdown
Contributor

A also think the horizontal three dots look best.
The code looks good too, although I haven't tested it.
Good job making that custom time picker. It's a shame Framework7 doesn't seem to provide any built-in component for that.

I have two minor suggestions though:

  1. Instead of disabling the actions when there are no entries in the meal, maybe it would be better to not show the three dots button in the first place.
  2. Perhaps the button would be better placed next to the + button of each meal, but I don't feel strongly about that.

@EmilJunker
Copy link
Copy Markdown
Contributor

One more idea: many users have said they find it unintuitive that long pressing the + button invokes the quick add feature, or that they didn't even know this feature existed. So maybe we could put an additional quick add button in the three dot menu to make it easier to discover?

@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 19, 2025

I moved the three dots next to the + icon (see pic below) and only show them when there are items in the group now. I'll commit these changes if they get your approval. I'll also take a look at the quick add functionality.

hide_dots

However, a question: I took a look at a few other PRs and I guess I would need to update the settings version and write some migration code due to recently having added settings for showing a trend line in the statistics (#918) and showing the total portion size (#916). If so: shall I add that code to this PR or create a new one?

@EmilJunker
Copy link
Copy Markdown
Contributor

I guess I would need to update the settings version and write some migration code

As long as the new settings are just booleans and false by default, you shouldn't need to implement any migration logic.

and only show them when there are items in the group now

If you choose to add the quick add feature to the action menu, you would of course need to revert that change and always show the three dots button. Sorry, my bad.

Frylen added 3 commits July 19, 2025 12:01
Moves the action menu button (switch from menu_open to more_horiz) from the right side of the accordion title bar next to the + sign in the footer of the meal category.
@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 19, 2025

The 3 dots are now a little closer to the + sign than before (15px margin-left to + button):
2025-07-19_12-11

@EmilJunker
Copy link
Copy Markdown
Contributor

I just built and the app in in the browser and noticed a couple of problems:

  1. The "remove all item from meal" feature doesn't work for me. When I select it and confirm, nothing happens (not even an error message in the console, just nothing).
  2. The "update timestamps" feature doesn't work when the app locale is set to "auto" because this line of code throws an error ("Invalid language tag: auto" at new DateTimeFormat).
  3. The "move items to another meal" feature works, but I noticed there is currently no good way to cancel the process. I can press outside of the menu to close it, but there is no backdrop area, so whatever element I press on (like a button) is invoked. And when I first select a meal and then try to cancel by pressing outside, the items still get moved to that meal. Also, it would be good to be able to cancel by pressing the Android OS back button (for this, you might need to add another case to the "backbutton" event listener in index.js).
  4. I don't really like how the disabled action menu options are transparent. It looks a bit weird, and I think it would be better to simply not include the disabled options in the menu in the first place. What do you think?

@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 19, 2025

The "remove all item from meal" feature doesn't work for me.

Yes, you are correct. I tested it yesterday, and it did work at that point. I'll take a look at that.

I don't really like how the disabled action menu options are transparent.

I agree. I'll change that.

@EmilJunker
Copy link
Copy Markdown
Contributor

EmilJunker commented Jul 19, 2025

Two more things:

When using a right-to-left language like Hebrew, the placement of the buttons looks wrong because the 15px margin-left is on the wrong side.

image image

On a related note, it looks like the + button and the three dots button are actually in the same div container, and therefore the long-press handler from the + button that opens the quick add feature now also applies to the three dots button.

Please put the two buttons in separate containers and make sure there is a margin between them in both LTR and RTL layouts.

Furthermore, I noticed that the "update timestamp" feature doesn't seem to work either. When I select a time and confirm, nothing happens.

@davidhealey
Copy link
Copy Markdown
Owner

davidhealey commented Jul 19, 2025

@EmilJunker Does it feel natural/intuitive that pressing the 3 dots opens the action menu?

@EmilJunker
Copy link
Copy Markdown
Contributor

Does it feel natural/intuitive that pressing the 3 dots opens the action menu?

Yes, I think the UX feels alright.

Frylen added 5 commits July 19, 2025 15:33
Bug was: removing elements while in a foreach
Unfortunately F7 does not seem to offer classes with the css `gap` to space flex items from each other. To still have a margin between the buttons we add a basic margin class to the action menu button. This might conflict with very long meal category macro summaries.
@Frylen Frylen closed this Jul 19, 2025
@Frylen Frylen reopened this Jul 19, 2025
@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 19, 2025

Furthermore, I noticed that the "update timestamp" feature doesn't seem to work either. When I select a time and confirm, nothing happens.

I could not reproduce that. Can you try again with these changes?

Although there is still a bug with the time and RTL languages. The picker for hour and minutes gets also shown from right to left, but as far as I know, the time is still read from left to right in an RTL language.

there is currently no good way to cancel the process.

I'll see if I can implement cancelling the smart select (same issue applies to the picker), but at first glance F7 does not offer a way to only handle the input when the user clicks on the sheet close link.

Add a backdrop to prevent clicks from propagating in the background elements.
@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 19, 2025

Well, this would be a workaround:

  let mealSelection = app.f7.smartSelect.create({
      el: smartSelect,
      openIn: "sheet",
      sheetBackdrop: true,
      closeOnSelect: true,  // <-- 
      sheetCloseLinkText: app.strings.dialogs["cancel"] || "Cancel",  // using cancel instead of default "Done"
      on: {
        closed: (selection) => {
          let selectedMealName = validMealNames[selection.$selectEl.val()];
          selection.destroy();
          smartSelect.remove();
          app.Group.updateItemGroup(self, mealNames, selectedMealName);
        }
      }
    });

This closes the smart select sheet when a selection is done. Thus, clicking anywhere else/closing the smart select means that no change could've been made.

@EmilJunker
Copy link
Copy Markdown
Contributor

Can you try again with these changes?

I'll try to test it again tomorrow if I have time.

Although there is still a bug with the time and RTL languages. The picker for hour and minutes gets also shown from right to left, but as far as I know, the time is still read from left to right in an RTL language.

That's true. I'm sure there is a way to fix this, but it's been a while since I implemented the RTL layout (in #363) and I don't remember that many details.

Well, this would be a workaround

I don't know if this would work, but you can try it. If Framework7 really doesn't offer any way to do it then it can stay as it is.

@EmilJunker
Copy link
Copy Markdown
Contributor

I just tested the app again in the browser and everything looks and feels pretty good. The bugs I listed above seem to have been fixed.

I also tried the workaround you suggested with the closeOnSelect: true and it works quite well in my opinion. The only problem is that currently the first category is always selected by default, so if you try to cancel it actually moves the items to the first category.

Another related problem is there is currently no way to cancel updating the timestamps. Hence, if you accidentally press on the "update timestamps" button, you are forced to update all the timestamps in that category and there is no way to prevent it (except for closing the whole app, but that's obviously not very user friendly).

Also, there ist still the bug that you mentioned where the hours and minutes are incorrectly swapped in the RTL layout. I attempted a quick fix it by setting the direction: ltr css property on the sheet container. This almost worked, but for some reason it messed up the swipe interactions on the two columns. I'm not sure how this can be fixed.

@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 21, 2025

I also tried the workaround you suggested with the closeOnSelect: true and it works quite well in my opinion.

I am currently working on that. I add a button to the smart select on open that sets a flag so it is clear the user canceled the selection. On any change, I set the flag that there was a user change. With that, it would be possible to cancel the selection.

Another related problem is there is currently no way to cancel updating the timestamps.

I guess it would be possible to do the same thing here, however, I thought about using the F7 calendar instead. That one has a time picker as well, but I would need to manually remove the calendar element. Another option would be to use a F7 dialog and use an <input type="time"/> and let the OS/browser handle the picker. That would always set a h23 time (0-23) though, and there is no way to set the locale. The OS/browser would decide on the locale and thus the app locale will be ignored. Also, depending on the support it might require the user to type the time (e.g. in my firefox there is no selection pop-up).

E:

The only problem is that currently the first category is always selected by default

I assume this was caused by the check if the option for the meal name has the same name as the group. When the name gets localized (the default names) this check fails and the first option gets selected per default. I'll change it to select based on the index and the group ID.

Frylen added 8 commits July 21, 2025 11:49
Introduces a custom cancel button to the meal selection smart select sheet and ensures that group updates only occur if the user changes the selection and does not cancel.
Instead of setting the pre-selected meal category by name, we set it based on index. This way we prevent issues with the localized names of the default meal category names.
Switch from a custom time picker to a modified F7 time picker by hiding other calendar elements.
Instead of letting the user open the time picker from the calendar we call the method to open the time picker when the calendar opens and close the calendar when the time picker closes. That way we can hide the calendar (assuming the device isn't very slow and shows the calendar for a frame).
Sets the direction of the time picker columns to left-to-right to ensure hours and minutes are displayed correctly in the time picker.
Set the time picker value to the diary entry's date with the current time, ensuring the selected date matches the diary entry context. This way users who update their timestamps on another day will not have wrong date info when exporting the data. Inside the app it does not make a difference as the displayed time does not include the date.
Updates class assignments for picker columns to ensure correct scroll behavior.
@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Jul 22, 2025

Okay, I think the mentioned bugs should be fixed now. Feel free to test the changes when you have some time and let me know if you encounter any issues or inconsistencies.

@EmilJunker
Copy link
Copy Markdown
Contributor

I don't have time to test it thoroughly right now, but I just built and ran the app in the browser and at first glance it looks and feels quite good. I only noticed one bug that affects both the "move items to another meal" and "update timestamps" operations: when I try to cancel them by pressing the Android back button [document.dispatchEvent(new Event('backbutton'))] or by tapping on the backdrop area, the respective operation gets executed instead of being canceled (or in the case of "update timestamps", it updates all timestamps with the current time instead of cancelling). On the other hand, cancelling via the "cancel" buttons always works as expected.

Instead of using flags for a changed selection and a not cancelled selection, we now track only if the user has explicitly confirmed the action. That way any sort of exit made are now handled as there will be no user confirmation flag set.
@Frylen
Copy link
Copy Markdown
Contributor Author

Frylen commented Oct 16, 2025

Any news? ^^

@EmilJunker
Copy link
Copy Markdown
Contributor

I still haven't tested the latest changes, but if you tested everything and are confident and satisfied with it, I'd say it can be merged.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants