mirror of https://github.com/Siphonay/mastodon
Count unread notifications when window loses focus
This commit is contained in:
parent
c8875b4d8a
commit
d315f1dc02
|
@ -28,6 +28,8 @@ export const NOTIFICATIONS_SCROLL_TOP = 'NOTIFICATIONS_SCROLL_TOP';
|
||||||
export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT';
|
export const NOTIFICATIONS_MOUNT = 'NOTIFICATIONS_MOUNT';
|
||||||
export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT';
|
export const NOTIFICATIONS_UNMOUNT = 'NOTIFICATIONS_UNMOUNT';
|
||||||
|
|
||||||
|
export const NOTIFICATIONS_SET_VISIBILITY = 'NOTIFICATIONS_SET_VISIBILITY';
|
||||||
|
|
||||||
defineMessages({
|
defineMessages({
|
||||||
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
|
mention: { id: 'notification.mention', defaultMessage: '{name} mentioned you' },
|
||||||
});
|
});
|
||||||
|
@ -231,3 +233,10 @@ export function unmountNotifications() {
|
||||||
type: NOTIFICATIONS_UNMOUNT,
|
type: NOTIFICATIONS_UNMOUNT,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export function notificationsSetVisibility(visibility) {
|
||||||
|
return {
|
||||||
|
type: NOTIFICATIONS_SET_VISIBILITY,
|
||||||
|
visibility: visibility,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
|
@ -10,7 +10,7 @@ import { isMobile } from 'flavours/glitch/util/is_mobile';
|
||||||
import { debounce } from 'lodash';
|
import { debounce } from 'lodash';
|
||||||
import { uploadCompose, resetCompose } from 'flavours/glitch/actions/compose';
|
import { uploadCompose, resetCompose } from 'flavours/glitch/actions/compose';
|
||||||
import { expandHomeTimeline } from 'flavours/glitch/actions/timelines';
|
import { expandHomeTimeline } from 'flavours/glitch/actions/timelines';
|
||||||
import { expandNotifications } from 'flavours/glitch/actions/notifications';
|
import { expandNotifications, notificationsSetVisibility } from 'flavours/glitch/actions/notifications';
|
||||||
import { fetchFilters } from 'flavours/glitch/actions/filters';
|
import { fetchFilters } from 'flavours/glitch/actions/filters';
|
||||||
import { clearHeight } from 'flavours/glitch/actions/height_cache';
|
import { clearHeight } from 'flavours/glitch/actions/height_cache';
|
||||||
import { WrappedSwitch, WrappedRoute } from 'flavours/glitch/util/react_router_helpers';
|
import { WrappedSwitch, WrappedRoute } from 'flavours/glitch/util/react_router_helpers';
|
||||||
|
@ -206,7 +206,27 @@ export default class UI extends React.Component {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleVisibilityChange = () => {
|
||||||
|
const visibility = !document[this.visibilityHiddenProp];
|
||||||
|
this.props.dispatch(notificationsSetVisibility(visibility));
|
||||||
|
}
|
||||||
|
|
||||||
componentWillMount () {
|
componentWillMount () {
|
||||||
|
if (typeof document.hidden !== 'undefined') { // Opera 12.10 and Firefox 18 and later support
|
||||||
|
this.visibilityHiddenProp = 'hidden';
|
||||||
|
this.visibilityChange = 'visibilitychange';
|
||||||
|
} else if (typeof document.msHidden !== 'undefined') {
|
||||||
|
this.visibilityHiddenProp = 'msHidden';
|
||||||
|
this.visibilityChange = 'msvisibilitychange';
|
||||||
|
} else if (typeof document.webkitHidden !== 'undefined') {
|
||||||
|
this.visibilityHiddenProp = 'webkitHidden';
|
||||||
|
this.visibilityChange = 'webkitvisibilitychange';
|
||||||
|
}
|
||||||
|
if (this.visibilityChange !== undefined) {
|
||||||
|
document.addEventListener(this.visibilityChange, this.handleVisibilityChange, false);
|
||||||
|
this.handleVisibilityChange();
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('beforeunload', this.handleBeforeUnload, false);
|
window.addEventListener('beforeunload', this.handleBeforeUnload, false);
|
||||||
window.addEventListener('resize', this.handleResize, { passive: true });
|
window.addEventListener('resize', this.handleResize, { passive: true });
|
||||||
document.addEventListener('dragenter', this.handleDragEnter, false);
|
document.addEventListener('dragenter', this.handleDragEnter, false);
|
||||||
|
@ -250,6 +270,10 @@ export default class UI extends React.Component {
|
||||||
}
|
}
|
||||||
|
|
||||||
componentWillUnmount () {
|
componentWillUnmount () {
|
||||||
|
if (this.visibilityChange !== undefined) {
|
||||||
|
document.removeEventListener(this.visibilityChange, this.handleVisibilityChange);
|
||||||
|
}
|
||||||
|
|
||||||
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
window.removeEventListener('beforeunload', this.handleBeforeUnload);
|
||||||
window.removeEventListener('resize', this.handleResize);
|
window.removeEventListener('resize', this.handleResize);
|
||||||
document.removeEventListener('dragenter', this.handleDragEnter);
|
document.removeEventListener('dragenter', this.handleDragEnter);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import {
|
import {
|
||||||
NOTIFICATIONS_MOUNT,
|
NOTIFICATIONS_MOUNT,
|
||||||
NOTIFICATIONS_UNMOUNT,
|
NOTIFICATIONS_UNMOUNT,
|
||||||
|
NOTIFICATIONS_SET_VISIBILITY,
|
||||||
NOTIFICATIONS_UPDATE,
|
NOTIFICATIONS_UPDATE,
|
||||||
NOTIFICATIONS_EXPAND_SUCCESS,
|
NOTIFICATIONS_EXPAND_SUCCESS,
|
||||||
NOTIFICATIONS_EXPAND_REQUEST,
|
NOTIFICATIONS_EXPAND_REQUEST,
|
||||||
|
@ -31,6 +32,7 @@ const initialState = ImmutableMap({
|
||||||
lastReadId: '0',
|
lastReadId: '0',
|
||||||
isLoading: false,
|
isLoading: false,
|
||||||
cleaningMode: false,
|
cleaningMode: false,
|
||||||
|
isTabVisible: true,
|
||||||
// notification removal mark of new notifs loaded whilst cleaningMode is true.
|
// notification removal mark of new notifs loaded whilst cleaningMode is true.
|
||||||
markNewForDelete: false,
|
markNewForDelete: false,
|
||||||
});
|
});
|
||||||
|
@ -44,7 +46,7 @@ const notificationToMap = (state, notification) => ImmutableMap({
|
||||||
});
|
});
|
||||||
|
|
||||||
const normalizeNotification = (state, notification) => {
|
const normalizeNotification = (state, notification) => {
|
||||||
const top = state.get('top') && state.get('mounted') > 0;
|
const top = !shouldCountUnreadNotifications(state);
|
||||||
|
|
||||||
if (top) {
|
if (top) {
|
||||||
state = state.set('lastReadId', notification.id);
|
state = state.set('lastReadId', notification.id);
|
||||||
|
@ -62,7 +64,7 @@ const normalizeNotification = (state, notification) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const expandNormalizedNotifications = (state, notifications, next) => {
|
const expandNormalizedNotifications = (state, notifications, next) => {
|
||||||
const top = state.get('top') && state.get('mounted') > 0;
|
const top = !(shouldCountUnreadNotifications(state));
|
||||||
const lastReadId = state.get('lastReadId');
|
const lastReadId = state.get('lastReadId');
|
||||||
let items = ImmutableList();
|
let items = ImmutableList();
|
||||||
|
|
||||||
|
@ -112,7 +114,9 @@ const clearUnread = (state) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const updateTop = (state, top) => {
|
const updateTop = (state, top) => {
|
||||||
if (top && state.get('mounted') > 0) {
|
state = state.set('top', top);
|
||||||
|
|
||||||
|
if (!shouldCountUnreadNotifications(state)) {
|
||||||
state = clearUnread(state);
|
state = clearUnread(state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -120,7 +124,7 @@ const updateTop = (state, top) => {
|
||||||
};
|
};
|
||||||
|
|
||||||
const deleteByStatus = (state, statusId) => {
|
const deleteByStatus = (state, statusId) => {
|
||||||
const top = state.get('top') && state.get('mounted') > 0;
|
const top = !(shouldCountUnreadNotifications(state));
|
||||||
if (!top) {
|
if (!top) {
|
||||||
const lastReadId = state.get('lastReadId');
|
const lastReadId = state.get('lastReadId');
|
||||||
const deletedUnread = state.get('items').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0);
|
const deletedUnread = state.get('items').filter(item => item !== null && item.get('status') === statusId && compareId(item.get('id'), lastReadId) > 0);
|
||||||
|
@ -157,14 +161,36 @@ const deleteMarkedNotifs = (state) => {
|
||||||
return state.update('items', list => list.filterNot(item => item.get('markedForDelete')));
|
return state.update('items', list => list.filterNot(item => item.get('markedForDelete')));
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const updateMounted = (state) => {
|
||||||
|
state = state.update('mounted', count => count + 1);
|
||||||
|
if (!shouldCountUnreadNotifications(state)) {
|
||||||
|
state = clearUnread(state);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateVisibility = (state, visibility) => {
|
||||||
|
state = state.set('isTabVisible', visibility);
|
||||||
|
if (!shouldCountUnreadNotifications(state)) {
|
||||||
|
state = clearUnread(state);
|
||||||
|
}
|
||||||
|
return state;
|
||||||
|
};
|
||||||
|
|
||||||
|
const shouldCountUnreadNotifications = (state) => {
|
||||||
|
return !(state.get('isTabVisible') && state.get('top') && state.get('mounted') > 0);
|
||||||
|
};
|
||||||
|
|
||||||
export default function notifications(state = initialState, action) {
|
export default function notifications(state = initialState, action) {
|
||||||
let st;
|
let st;
|
||||||
|
|
||||||
switch(action.type) {
|
switch(action.type) {
|
||||||
case NOTIFICATIONS_MOUNT:
|
case NOTIFICATIONS_MOUNT:
|
||||||
return (state.get('top') ? clearUnread(state) : state).update('mounted', count => count + 1);
|
return updateMounted(state);
|
||||||
case NOTIFICATIONS_UNMOUNT:
|
case NOTIFICATIONS_UNMOUNT:
|
||||||
return state.update('mounted', count => count - 1);
|
return state.update('mounted', count => count - 1);
|
||||||
|
case NOTIFICATIONS_SET_VISIBILITY:
|
||||||
|
return updateVisibility(state, action.visibility);
|
||||||
case NOTIFICATIONS_EXPAND_REQUEST:
|
case NOTIFICATIONS_EXPAND_REQUEST:
|
||||||
case NOTIFICATIONS_DELETE_MARKED_REQUEST:
|
case NOTIFICATIONS_DELETE_MARKED_REQUEST:
|
||||||
return state.set('isLoading', true);
|
return state.set('isLoading', true);
|
||||||
|
|
Loading…
Reference in New Issue