-
-
Notifications
You must be signed in to change notification settings - Fork 673
home screen: Add ability to mark messages in bulk, mute topics. #4194
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Conversation
// eslint-disable-next-line no-unused-vars | ||
handleTopicSelect, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This comment is present here because although handleTopicSelect
is unused, I don't want it going into restProps
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Makes sense. Let's put that in the code comment, though. 😉
todo (Done)
|
Adds the 'check-circle' MaterialIcon to our icons list, to be used later as a checkbox status indicator.
While icon buttons are great for conveying purpose without text, it can sometimes be confusing what they actually do. Most apps allow long-pressing them to show a toast with their textual equivalent. This commit adds the ability to pass a 'title' prop to 'NavButton'. On long pressing it, a toast is shown with this title string.
Implements a new UI to select multiple topics in the home tab screen with the ability to mute them or mark them as read. Fixes: zulip#3175
I've removed the [wip] marker. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool, this will be really handy!
A few comments below.
Another thought I just had is, do we also want streams to be selectable? If we do, we'll have to think about how we want to treat topics for a stream that has been selected. My first thought was that selecting a stream should auto-select all of its visible topics. But that's no good: for the muting case, muting a stream isn't the same thing as muting all of its topics, and it's definitely not the same thing as muting all of its topics that currently have unread messages. Best, I guess, to not touch the selected/deselected state of its topics, and maybe disable selecting/deselecting the topics (maybe).
const color = BRAND_COLOR; | ||
const countText = _.intl.formatMessage( | ||
{ | ||
id: '{count} topics selected', |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to have an entry in static/translations/messages_en.json.
const apiPromises = []; | ||
|
||
if (type === 'mute') { | ||
showToast(_('Muting selected topics')); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be good to announce the success of the action in a toast, once it's succeeded, as something like "Muted selected topics".
It's good to tell the user that their request has been acknowledged, as this "Muting..." / "Marking..." toast does. Unfortunately, our toast library doesn't handle the case where we have multiple toasts in quick succession. One way it might handle that is to move any still-present toasts upwards, to make room for a new one. But it doesn't; ah, well.
Still, even if it did, I think there's a better way to tell the user that their request has been acknowledged, and using fewer words. How about using the component's state
to track whether the request is in progress, being sure to set it appropriately when the request starts, and when it fails or succeeds. Then, we can show the loading state graphically through the duration of the request, perhaps by disabling the button they pressed. (This would have the nice benefit of making sure they don't accidentally duplicate the request, which could lead to confusing behavior or bugs.)
<View style={commonStyles.navWrapper}> | ||
<Label text={countText} style={styles.selectionCountText} /> | ||
</View> | ||
<NavButton |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a little confusing to use a "nav" button here, where the action isn't to navigate somewhere, but to execute an action on selected topics.
Still, it is in the nav bar, and there's not an obvious other place it could go.
title={_('Mute')} | ||
/> | ||
<NavButton | ||
name="check" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, I'm not sure a checkmark really conveys the meaning "mark as read". A checkmark is also used to indicate selecting a topic on the same screen, for one thing.
It looks like Gmail uses an open envelope icon, in both the mobile app (iOS) and in the browser. The situation there is slightly different, though; email threads appear whether they've been read or not, and the button changes to a closed envelope when you select only threads that have been read. That's a bit of extra context that helps solidify the meaning of the open envelope (that and the fact that their product is email).
Still, I think an open envelope icon might be recognizable enough, in our app, or at least more so than a checkmark? What do you think?
edit: Huh, though, looks like the web app uses fa-book for "mark as read" in at least one place:
); | ||
} | ||
|
||
if (inBulkSelectionMode) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The empty circle is just a bit bigger than the circular checkmark icon; they should be exactly the same size, I think.
I wonder if there's a pair of icons that are meant to complement each other? Like this and this, although that particular pair uses a rounded square, and it seems unavailable in the latest version of Font Awesome, hmm.
If we can find two icons, from the same icon set, that are explicitly meant to complement each other, then we don't even have to think about inconsistencies between them.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Not all the icons present online are actually present in the RN library. For example, the empty circle icon is missing from most icon sets while it's present in the online list.
handleBackPress = (): boolean => { | ||
if (this.state.bulkSelection !== null) { | ||
this.setState({ bulkSelection: null }); | ||
return true; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's the meaning of returning true or false from this function? That would be good to answer in a code comment.
class HomeTab extends PureComponent<Props, State> { | ||
static contextType = TranslationContext; | ||
backHandler; | ||
context: GetText; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's have context
directly follow static contextType
. From the JSDoc on GetText
in src/types.js:
* To use, put these two lines at the top of a React component's body:
*
* static contextType = TranslationContext;
* context: GetText;
Then a blank line after those, to set them apart.
For backHandler
, it looks like it's just sitting there; is there a type annotation we can give it?
Fixes: #3175