Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -235,6 +235,9 @@ export const fetchMarkNotificationAsRead = (notificationID, accessToken) =>
export const fetchMarkRepoNotificationAsRead = (repoFullName, accessToken) =>
v3.put(`/repos/${repoFullName}/notifications`, accessToken);

export const fetchMarkAllNotificationsAsRead = accessToken =>
v3.put('/notifications', accessToken);

export const fetchChangeStarStatusRepo = (owner, repo, starred, accessToken) =>
v3[starred ? 'delete' : 'put'](`/user/starred/${owner}/${repo}`, accessToken);

Expand Down
2 changes: 2 additions & 0 deletions src/config/colors.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ export const colors = {
purple: '#8e44ad',
orange: '#e67e22',
githubDark: '#1f2327',
mercury: '#e3e3e3',
shark: '#24292e',
};

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know those are official names, but they're not explicite at all.
Also, do we really need to add news colors?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As I understand it, we add all the colors to the configuration, or am I mistaken?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yes, new colors should be added in configuration.
I was asking if we could nor reuse existing colors instead

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay, I remove those colors


export const languageColors = {
Expand Down
1 change: 1 addition & 0 deletions src/locale/languages/en.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ export const en = {
allButton: 'All',
retrievingMessage: 'Retrieving notifications',
noneMessage: "You don't have any notifications of this type",
markAllAsRead: 'Mark all notifications as read',

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This sentence is too long for a button, + translations may be bigger.
Can we use "Mark all read" instead?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The size of the button allows, so I made a detailed description, well I'll remove the word "notifications".

},
},
search: {
Expand Down
1 change: 1 addition & 0 deletions src/locale/languages/fr.js
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ export const fr = {
allButton: 'Tous',
retrievingMessage: 'Récupération des notifications',
noneMessage: "Vous n'avez aucune notification de ce type",
markAllAsRead: 'Mark all notifications as read',
},
},
search: {
Expand Down
1 change: 1 addition & 0 deletions src/locale/languages/nl.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export const nl = {
allButton: 'Alles',
retrievingMessage: 'Notificaties ophalen',
noneMessage: 'Je hebt geen notificaties met dit type',
markAllAsRead: 'Mark all notifications as read',
},
},
search: {
Expand Down
1 change: 1 addition & 0 deletions src/locale/languages/pt-br.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export const ptBr = {
allButton: 'Todas',
retrievingMessage: 'Buscando notificações',
noneMessage: 'Você não tem notificações deste tipo',
markAllAsRead: 'Mark all notifications as read',
},
},
search: {
Expand Down
1 change: 1 addition & 0 deletions src/locale/languages/ru.js
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ export const ru = {
allButton: 'Все',
retrievingMessage: 'Получение уведомлений',
noneMessage: 'У вас нет уведомлений по этому типу',
markAllAsRead: 'Отметить все уведомления как прочитанные',
},
},
search: {
Expand Down
1 change: 1 addition & 0 deletions src/locale/languages/tr.js
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,7 @@ export const tr = {
allButton: 'Tümü',
retrievingMessage: 'Bildirim alınıyor',
noneMessage: 'Bu türde hiçbir bildirime sahip değilsiniz',
markAllAsRead: 'Mark all notifications as read',
},
},
search: {
Expand Down
23 changes: 23 additions & 0 deletions src/notifications/notifications.action.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import {
fetchNotifications,
fetchMarkNotificationAsRead,
fetchMarkRepoNotificationAsRead,
fetchMarkAllNotificationsAsRead,
} from 'api';
import {
GET_UNREAD_NOTIFICATIONS,
GET_PARTICIPATING_NOTIFICATIONS,
GET_ALL_NOTIFICATIONS,
MARK_NOTIFICATION_AS_READ,
MARK_REPO_AS_READ,
MARK_ALL_NOTIFICATIONS_AS_READ,
} from './notifications.type';

export const getUnreadNotifications = () => {
Expand Down Expand Up @@ -120,3 +122,24 @@ export const markRepoAsRead = repoFullName => {
});
};
};

export const markAllNotificationsAsRead = () => {
return (dispatch, getState) => {
const accessToken = getState().auth.accessToken;

dispatch({ type: MARK_ALL_NOTIFICATIONS_AS_READ.PENDING });

fetchMarkAllNotificationsAsRead(accessToken)
.then(() => {
dispatch({
type: MARK_ALL_NOTIFICATIONS_AS_READ.SUCCESS,
});
})
.catch(error => {
dispatch({
type: MARK_ALL_NOTIFICATIONS_AS_READ.ERROR,
payload: error,
});
});
};
};
18 changes: 18 additions & 0 deletions src/notifications/notifications.reducer.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
GET_ALL_NOTIFICATIONS,
MARK_NOTIFICATION_AS_READ,
MARK_REPO_AS_READ,
MARK_ALL_NOTIFICATIONS_AS_READ,
} from './notifications.type';

const initialState = {
Expand All @@ -15,6 +16,7 @@ const initialState = {
isPendingAll: false,
isPendingMarkNotificationAsRead: false,
isPendingRepoMarkAsRead: false,
isPendingMarkAllNotificationsAsRead: false,
error: '',
};

Expand Down Expand Up @@ -129,6 +131,22 @@ export const notificationsReducer = (state = initialState, action = {}) => {
error: action.payload,
isPendingRepoMarkAsRead: false,
};
case MARK_ALL_NOTIFICATIONS_AS_READ.PENDING:
return {
...state,
isPendingMarkAllNotificationsAsRead: true,
};
case MARK_ALL_NOTIFICATIONS_AS_READ.SUCCESS:
return {
...state,
isPendingMarkAllNotificationsAsRead: false,
};
case MARK_ALL_NOTIFICATIONS_AS_READ.ERROR:
return {
...state,
error: action.payload,
isPendingMarkAllNotificationsAsRead: false,
};
default:
return state;
}
Expand Down
3 changes: 3 additions & 0 deletions src/notifications/notifications.type.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,6 @@ export const MARK_NOTIFICATION_AS_READ = createActionSet(
'MARK_NOTIFICATION_AS_READ'
);
export const MARK_REPO_AS_READ = createActionSet('MARK_REPO_AS_READ');
export const MARK_ALL_NOTIFICATIONS_AS_READ = createActionSet(
'MARK_ALL_NOTIFICATIONS_AS_READ'
);
62 changes: 54 additions & 8 deletions src/notifications/screens/notifications.screen.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ import {
Image,
Platform,
} from 'react-native';
import { ButtonGroup, Card, Icon } from 'react-native-elements';
import { ButtonGroup, Card, Icon, Button } from 'react-native-elements';

import { v3 } from 'api';
import {
Expand All @@ -29,6 +29,7 @@ import {
getAllNotifications,
markAsRead,
markRepoAsRead,
markAllNotificationsAsRead,
} from '../index';

const mapStateToProps = state => ({
Expand All @@ -40,6 +41,8 @@ const mapStateToProps = state => ({
isPendingUnread: state.notifications.isPendingUnread,
isPendingParticipating: state.notifications.isPendingParticipating,
isPendingAll: state.notifications.isPendingAll,
isPendingMarkAllNotificationsAsRead:
state.notifications.isPendingMarkAllNotificationsAsRead,
});

const mapDispatchToProps = dispatch =>
Expand All @@ -50,17 +53,20 @@ const mapDispatchToProps = dispatch =>
getAllNotifications,
markAsRead,
markRepoAsRead,
markAllNotificationsAsRead,
},
dispatch
);

const styles = StyleSheet.create({
buttonGroupWrapper: {
backgroundColor: colors.greyLight,
paddingTop: Platform.OS === 'ios' ? 28 : 15,
paddingTop: Platform.OS === 'ios' ? 30 : 10,
paddingBottom: 10,
},
buttonGroupContainer: {
height: 30,
marginTop: 0,
},
buttonGroupText: {
...fonts.fontPrimaryBold,
Expand All @@ -70,7 +76,7 @@ const styles = StyleSheet.create({
},
repositoryContainer: {
padding: 0,
marginVertical: 25,
marginBottom: 15,
},
headerContainer: {
flexDirection: 'row',
Expand Down Expand Up @@ -110,6 +116,16 @@ const styles = StyleSheet.create({
textAlign: 'center',
...fonts.fontPrimary,
},
markAllAsReadButton: {
marginTop: 3,
paddingTop: 3,
paddingBottom: 3,
marginLeft: 11,
marginRight: 11,
borderColor: colors.mercury,
borderWidth: 1,
borderRadius: 3,
},
});

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not a fan of this button design, and it looks too different from the "Merge pull request" button we have :
screen shot 2017-09-27 at 6 52 55 pm

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hmm this is interesting... I agree that we should keep to a similar style in general, but I don't think a bulky button like this taking up a bunch of space is the best UI. I like how this style is more discrete at the top of the screen.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Absolutely! Right after commenting on this, I started implementing a standard component to be used everywhere (small/normal/big, info/danger/..) :)

@lex111 lex111 Sep 27, 2017

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe yes, we can not make this button fixed, then it will be before the first notification, how's this?

In style, I think this is the best option, I mean that the button is stretched to full width.


class Notifications extends Component {
Expand All @@ -119,13 +135,15 @@ class Notifications extends Component {
getAllNotifications: Function,
markAsRead: Function,
markRepoAsRead: Function,
markAllNotificationsAsRead: Function,
unread: Array,
participating: Array,
all: Array,
language: string,
isPendingUnread: boolean,
isPendingParticipating: boolean,
isPendingAll: boolean,
isPendingMarkAllNotificationsAsRead: boolean,
navigation: Object,
};

Expand All @@ -147,6 +165,16 @@ class Notifications extends Component {
this.props.getAllNotifications();
}

componentWillReceiveProps(nextProps) {
if (
!nextProps.isPendingMarkAllNotificationsAsRead &&
this.props.isPendingMarkAllNotificationsAsRead &&
!this.isLoading()
) {
this.getNotifications()();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

()() ?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because this function returns a function, it still needs to be called, so one more parentheses.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about rename getNotifications as getFuncForGettingNotifications, or something else?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is unlikely that the first name is fine (getFuncForGettingNotifications), because this function does two things: not only returns another function, but also updates the notification counter.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lex111 Sorry, I didn't quite get your words. Can you tell me where "updates the notification counter"?

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's you who excuse me 😄 , I mixed up with my other PR #360 - I'm doing a notification counter there and there's this function.
But we need to think more, we can be renamed.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think something like getNotificationsForCurrentTab or something along those lines will be okay

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@lex111 I prefer to keep getNotifications as simple as now, instead of mixing getNotificationsCount in it.

Because there is another place calls this function, which just expects a function. After #360 is merged, I guess getNotificationsCount will be called frequently by render.

}
}

getImage(repoName) {
const notificationForRepo = this.notifications().find(
notification => notification.repository.full_name === repoName
Expand Down Expand Up @@ -316,7 +344,7 @@ class Notifications extends Component {

render() {
const { type } = this.state;
const { language } = this.props;
const { language, markAllNotificationsAsRead } = this.props;

const repositories = [
...new Set(
Expand All @@ -330,6 +358,8 @@ class Notifications extends Component {
return a.toLowerCase() > b.toLowerCase() ? 1 : -1;
});

const isEmptyNotifications = this.notifications().length === 0;

return (
<ViewContainer>
<View style={styles.container}>
Expand All @@ -346,25 +376,41 @@ class Notifications extends Component {
selectedTextStyle={styles.buttonGroupTextSelected}
containerStyle={styles.buttonGroupContainer}
/>

<Button
icon={{
name: 'check',
size: 20,
type: 'octicon',
color: colors.shark,
}}
title={translate('notifications.main.markAllAsRead')}
buttonStyle={styles.markAllAsReadButton}
color={colors.shark}
backgroundColor={colors.white}
textStyle={styles.buttonGroupText}
onPress={() => markAllNotificationsAsRead()}
disabled={isEmptyNotifications}
/>
</View>

{this.isLoading() &&
this.notifications().length === 0 &&
isEmptyNotifications &&
<LoadingContainer
animating={this.isLoading() && this.notifications().length === 0}
animating={this.isLoading() && isEmptyNotifications}
text={translate('notifications.main.retrievingMessage', language)}
style={styles.marginSpacing}
/>}

{!this.isLoading() &&
this.notifications().length === 0 &&
isEmptyNotifications &&
<View style={styles.textContainer}>
<Text style={styles.noneTitle}>
{translate('notifications.main.noneMessage', language)}
</Text>
</View>}

{this.notifications().length > 0 &&
{!isEmptyNotifications &&
<FlatList
ref={ref => {
this.notificationsList = ref;
Expand Down