ankidroid / Anki-Android

AnkiDroid: Anki flashcards on Android. Your secret trick to achieve superhuman information retention.
GNU General Public License v3.0
8.74k stars 2.24k forks source link

Browser chips #12554

Open oakkitten opened 2 years ago

oakkitten commented 2 years ago

This is a brief summary of my attempt to bring in chips to Browser. These chips behave similarly to chips in Gmail and replicate most of the functionality of the sidebar in Anki.

The implementation is here, see the few last commits. It's currently not PR quality, is presumably blocked by converting the card list to RecyclerView and might be split into several PRs.

I would love it if someone took a brief look at WizardAdapter and CheckableTreeAdapter and told me whether they like the general design of the thing.

Behavior

A single-line chip bar, horizontally scrollable, is placed just below the toolbar. Tapping on a chip opens the according bottom sheet, where you can select one or multiple items. When you select items, search is instantly re-done, and the chip changes its color and label to reflect the selection. For example, Decks may change to Cool deck if one deck is selected or Cool deck+1 if two are selected. In the latter case, Cool deck would be the one the user selected first.

The toolbar, along with the chip bar and the spinners bellow, is collapsed when the user scrolls down the list of cards.

The bottom sheets show lists of items with icons, text and checkboxes. To select items, you can:

All the bottom sheets have an item such as All decks without a checkbox. Tapping on it clears the selection and closes the dialog, effectively stopping filtering by this category.

The bottom sheets can display directory tree-like items. Items that have subitems can be collapsed to hide those and show a clickable chevron to indicate collapsed state (/). If there ara any chevrons, all items are shifted slightly to the right to make place for the leftmost chevrons.

If there are many items, a search input is visible. The hint says Search decks, or Search tags, etc. Tapping on it will expand the sheet to full screen (if enough items). Search input has a clear search button that appears when there is some text. When typing, items that do not contain the input are hidden, with the exception of any parent items, e.g., searching for foo would change

* abc         
* def                     * def
  * hello        to         * hello
     * foo                     * foo
     * bar                * foo fighters
* foo fighters

The bottom sheet survives rotation, preserving selection & scroll position.

Going forward

I would love to have a list of recent searches, and for the saved searches be more accessible. I imagine this could be done by not showing cards when opening the browser, but instead of showing something like this:

[ Toolbar & chips, etc. ]

  Show all cards in (current deck)
  Show all cards in all decks

Recent searches {not clickable, 5 recent items}
  Search A [chip1] [chip2] 🡔
  Search B [chip3]         🡔
  ...                      🡔
  Show more {shows, say, 20 recent items}

Saved searches {not clickable}
  Saved search A           🡔
  Saved search B           🡔

Caveats & considerations

Visuals

Pretty much what you can see from the screenshots. Some notes:

Caveats & considerations

Implementation

At the moment, the implementation is minimally wired into the app, which is to say I did the absolute minimum amound of changes in the existing code to make it work. The new code is like this:

Caveats & considerations

At the moment the design is not yet finalized, and I'm not even sure if some the ideas are good. Having a modular adapter seems nice but modularity drastically increases code size; collapsing CheckableTreeAdapter and WizardAdapter into a single class halves the code. But being modular should allow reusing the adapter in other places of the app, such as deck picker, etc. The above path from a set of chains to the adapter items is perhaps a bit too confusing and can be simplified. Some strings need to be extracted.

If the card list has few items, dragging the empty area does not collaps/uncollapse the toolbar. This is probably a problem with the ListView. Wrapping it in NestedScrollView doesn't seem to work. I hope that changing it to a RecyclerView will resolve the issue.

I didn't implement a chip with note types because I was lazy and because I'm not sure it's useful.

Currently, bottom sheet fragments are aware of the collection and that's where these get the data in sync. I think they should be able to get that data cached. This is simple and this ensures that the adapter has the latest data. However, this means that on view recreation the data can change. For the most part this is not an issue, but tags are strings and don't have intrinsic IDs, and tag position in tag list is used instead. In theory, if for instance the tags change between activity recreations, you can have RecyclerView restored to a wrong position. I don't think this can lead to any important issues, but just to be safe the IDs can be somewhat stabilized by keeping a static map of tag to id, or interning strings maybe. (Is string interning fast?)

The collapse state of items is not saved and vanishes on activity recreation, and I don't think it's worth saving it.

The new icons should be optimized.

Code reuse

If deemed good, the WizardAdapter may serve in other parts of the app, such as the deck picker, or notification preferences. It will have to be finalized first, and some of the code should be generalized more yet, e.g., currently the chain collection → deck bottom sheet is tied to bottom sheets and must be untied. This is not hard but is hard to do right. Also, if the bottom sheets are to be reused in different activities, these should be united from CardBrowser.

The WizardAdapter & pals may be an independent PR.

snowtimeglass commented 2 years ago

Though I have not yet thoroughly read and understood the whole thing, I like it as a whole. Thank you for your dedication to the work.

However, I am concerned about the icons of Card State. I maybe understand your intention to represent each development states of studying cards, but still it seems to be a leap of association to link "learning and review" to "young boy and matured man". Plus, Anki has already used the metaphor of growth in the classification of review cards ("Young" and "Mature"). It seems to be confusing to liken learning cards to young boy. Besides, I think it would be better to avoid gender-unneutral design as far as possible. Not a few people might resist the combination of review card and matured man (or matured woman) and feel it intrusive.

image image

I don't want to use colors because colored icons don't look very well and because the association between the color of the circles in the sidebar and the numbers in the deck browser is just too weak in my opinion. Yes, the colors are the same but I don't feel that my mind jumps to “yes, this means ‘new’” when I see a blue circle.

I sympathize with you to some extent, but even if the colored icons aren't perfect, I think it would be better to adopt them for the above reasons and also from the perspective of design consistency with Statistics page, the card counts in the other pages, and Anki Desktop.
image image image

oakkitten commented 2 years ago

Ah, very valid points. I never thought about young/mature stuff. I dunno.

On one hand, I think these icons look awesome (if I do say so myself) and make a clear progression, I think. Also, they are naturally round, which fits with the circle that represents “state” in Anki. A circle is a good as any representation of a state, so I wanted to stick with it for consistency.

On the other hand, as you are saying there are concepts of young and mature already. The thing about all of those concepts, it's so hard to think of suitable icons for them, especially for learning. Colors are a suitable alternative, but I just hate them so much. If I was to go with colour I'd want color non-filled circles for new/learning/review and current icons for suspended/buried, I don't think these should be colored. But I still don't like this. I dunno.

As for gender neutrality, I'm absolutely for inclusivity but I just don't see how this could be an issue. I only chose moustache since how would you even depict a “mature lady” on an icon?

snowtimeglass commented 2 years ago

I think these icons look awesome

Yes, they really look awesome. I applaud your talent and skills for creating icon. I hope you will continue to make use of them for AnkiDroid and help us.

As for gender neutrality, I'm absolutely for inclusivity but I just don't see how this could be an issue. I only chose moustache since how would you even depict a “mature lady” on an icon?

As you say, it is not so much an issue. By no means do I intend to say that male icon is a male-dominated or sexist design. I just think that gender-neutral icon like most of material icons would be more desirable since it would be more simple and universal (Yeah, that's easier said than done. I do not mean to belittle your dedication and the works. Please don't have any hard feelings). Perhaps, gender-neutral maturity might be expressed by elevating the position of eyes and adding vertical line of bridge of nose...?

BrayanDSO commented 2 years ago

TLDR (quite busy here), so I'll comment only what caught my attention

  1. The filtered deck link doesn't remember me of a funnel. Looks more like a lamp
  2. I've said on Discord, but I need to zoom a lot to discover that the "Bury" icon is a shovel
  3. I need to zoom to see that the "Mature" icon is a guy with a mustache. On a distance, it looks to me like a sad face
  4. FWIW, I like Anki colors for the states. The exceptions would be suspend and bury (when it had a good icon)
  5. Agreed with the "Reschedule" and "Overdue" removals and the other renames
  6. IME, Notetypes queries can be quite useful yes.
github-actions[bot] commented 1 year ago

Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically