bring in 'notifications' state from lbry-redux

This commit is contained in:
Sean Yesmunt 2020-06-12 16:44:25 -04:00
parent 5a219c7b4b
commit 7138fe54bc
28 changed files with 231 additions and 98 deletions

View file

@ -2,11 +2,11 @@ import { connect } from 'react-redux';
import { import {
selectChannelIsBlocked, selectChannelIsBlocked,
doToggleBlockChannel, doToggleBlockChannel,
doToast,
makeSelectClaimIsMine, makeSelectClaimIsMine,
makeSelectShortUrlForUri, makeSelectShortUrlForUri,
makeSelectPermanentUrlForUri, makeSelectPermanentUrlForUri,
} from 'lbry-redux'; } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import BlockButton from './view'; import BlockButton from './view';
const select = (state, props) => ({ const select = (state, props) => ({
@ -16,10 +16,7 @@ const select = (state, props) => ({
permanentUrl: makeSelectPermanentUrlForUri(props.uri)(state), permanentUrl: makeSelectPermanentUrlForUri(props.uri)(state),
}); });
export default connect( export default connect(select, {
select, toggleBlockChannel: doToggleBlockChannel,
{ doToast,
toggleBlockChannel: doToggleBlockChannel, })(BlockButton);
doToast,
}
)(BlockButton);

View file

@ -1,14 +1,12 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { makeSelectCanonicalUrlForUri, doToast } from 'lbry-redux'; import { makeSelectCanonicalUrlForUri } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import ClaimUri from './view'; import ClaimUri from './view';
const select = (state, props) => ({ const select = (state, props) => ({
shortUrl: makeSelectCanonicalUrlForUri(props.uri)(state), shortUrl: makeSelectCanonicalUrlForUri(props.uri)(state),
}); });
export default connect( export default connect(select, {
select, doToast,
{ })(ClaimUri);
doToast,
}
)(ClaimUri);

View file

@ -1,10 +1,7 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import CopyableText from './view'; import CopyableText from './view';
export default connect( export default connect(null, {
null, doToast,
{ })(CopyableText);
doToast,
}
)(CopyableText);

View file

@ -1,10 +1,7 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import EmbedTextArea from './view'; import EmbedTextArea from './view';
export default connect( export default connect(null, {
null, doToast,
{ })(EmbedTextArea);
doToast,
}
)(EmbedTextArea);

View file

@ -4,9 +4,9 @@ import {
selectIsStillEditing, selectIsStillEditing,
makeSelectPublishFormValue, makeSelectPublishFormValue,
doUpdatePublishForm, doUpdatePublishForm,
doToast,
doClearPublish, doClearPublish,
} from 'lbry-redux'; } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import { selectFfmpegStatus } from 'redux/selectors/settings'; import { selectFfmpegStatus } from 'redux/selectors/settings';
import PublishPage from './view'; import PublishPage from './view';

View file

@ -6,7 +6,7 @@ import {
doUserPasswordSet, doUserPasswordSet,
doClearPasswordEntry, doClearPasswordEntry,
} from 'lbryinc'; } from 'lbryinc';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import UserSignIn from './view'; import UserSignIn from './view';
const select = state => ({ const select = state => ({

View file

@ -2,7 +2,7 @@ import { connect } from 'react-redux';
import * as SETTINGS from 'constants/settings'; import * as SETTINGS from 'constants/settings';
import { doSetAutoLaunch } from 'redux/actions/settings'; import { doSetAutoLaunch } from 'redux/actions/settings';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import SettingAutoLaunch from './view'; import SettingAutoLaunch from './view';
const select = state => ({ const select = state => ({
@ -14,7 +14,4 @@ const perform = dispatch => ({
setAutoLaunch: value => dispatch(doSetAutoLaunch(value)), setAutoLaunch: value => dispatch(doSetAutoLaunch(value)),
}); });
export default connect( export default connect(select, perform)(SettingAutoLaunch);
select,
perform
)(SettingAutoLaunch);

View file

@ -1,17 +1,14 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions'; import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions';
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import ShareButton from './view'; import ShareButton from './view';
const select = (state, props) => ({}); const select = (state, props) => ({});
export default connect( export default connect(select, {
select, doChannelSubscribe,
{ doChannelUnsubscribe,
doChannelSubscribe, doOpenModal,
doChannelUnsubscribe, doToast,
doOpenModal, })(ShareButton);
doToast,
}
)(ShareButton);

View file

@ -1,5 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { selectToast, doDismissToast } from 'lbry-redux'; import { doDismissToast } from 'redux/actions/notifications';
import { selectToast } from 'redux/selectors/notifications';
import SnackBar from './view'; import SnackBar from './view';
const perform = dispatch => ({ const perform = dispatch => ({
@ -10,7 +11,4 @@ const select = state => ({
snack: selectToast(state), snack: selectToast(state),
}); });
export default connect( export default connect(select, perform)(SnackBar);
select,
perform
)(SnackBar);

View file

@ -4,7 +4,8 @@ import { selectDaemonVersionMatched, selectModal } from 'redux/selectors/app';
import { doCheckDaemonVersion, doOpenModal, doHideModal } from 'redux/actions/app'; import { doCheckDaemonVersion, doOpenModal, doHideModal } from 'redux/actions/app';
import { doSetClientSetting, doClearDaemonSetting } from 'redux/actions/settings'; import { doSetClientSetting, doClearDaemonSetting } from 'redux/actions/settings';
import * as settings from 'constants/settings'; import * as settings from 'constants/settings';
import { doToast, DAEMON_SETTINGS } from 'lbry-redux'; import { DAEMON_SETTINGS } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import SplashScreen from './view'; import SplashScreen from './view';
import { makeSelectClientSetting } from 'redux/selectors/settings'; import { makeSelectClientSetting } from 'redux/selectors/settings';
@ -25,7 +26,4 @@ const perform = dispatch => ({
doShowSnackBar: message => dispatch(doToast({ isError: true, message })), doShowSnackBar: message => dispatch(doToast({ isError: true, message })),
}); });
export default connect( export default connect(select, perform)(SplashScreen);
select,
perform
)(SplashScreen);

View file

@ -2,7 +2,8 @@ import { connect } from 'react-redux';
import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions'; import { doChannelSubscribe, doChannelUnsubscribe } from 'redux/actions/subscriptions';
import { doOpenModal } from 'redux/actions/app'; import { doOpenModal } from 'redux/actions/app';
import { selectSubscriptions, makeSelectIsSubscribed, selectFirstRunCompleted } from 'redux/selectors/subscriptions'; import { selectSubscriptions, makeSelectIsSubscribed, selectFirstRunCompleted } from 'redux/selectors/subscriptions';
import { doToast, makeSelectPermanentUrlForUri } from 'lbry-redux'; import { makeSelectPermanentUrlForUri } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import SubscribeButton from './view'; import SubscribeButton from './view';
const select = (state, props) => ({ const select = (state, props) => ({
@ -12,12 +13,9 @@ const select = (state, props) => ({
permanentUrl: makeSelectPermanentUrlForUri(props.uri)(state), permanentUrl: makeSelectPermanentUrlForUri(props.uri)(state),
}); });
export default connect( export default connect(select, {
select, doChannelSubscribe,
{ doChannelUnsubscribe,
doChannelSubscribe, doOpenModal,
doChannelUnsubscribe, doToast,
doOpenModal, })(SubscribeButton);
doToast,
}
)(SubscribeButton);

View file

@ -7,7 +7,7 @@ import {
selectUser, selectUser,
selectResendingVerificationEmail, selectResendingVerificationEmail,
} from 'lbryinc'; } from 'lbryinc';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import UserEmailVerify from './view'; import UserEmailVerify from './view';
const select = state => ({ const select = state => ({

View file

@ -8,7 +8,7 @@ import {
doClearEmailEntry, doClearEmailEntry,
selectEmailToVerify, selectEmailToVerify,
} from 'lbryinc'; } from 'lbryinc';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import UserSignIn from './view'; import UserSignIn from './view';
const select = state => ({ const select = state => ({

View file

@ -1,6 +1,6 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doClearEmailEntry, doUserFetch } from 'lbryinc'; import { doClearEmailEntry, doUserFetch } from 'lbryinc';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import UserSignIn from './view'; import UserSignIn from './view';
const select = state => ({ const select = state => ({

View file

@ -3,11 +3,11 @@ import {
doFocusSearchInput, doFocusSearchInput,
doBlurSearchInput, doBlurSearchInput,
doUpdateSearchQuery, doUpdateSearchQuery,
doToast,
selectSearchValue, selectSearchValue,
selectSearchSuggestions, selectSearchSuggestions,
selectSearchBarFocused, selectSearchBarFocused,
} from 'lbry-redux'; } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import analytics from 'analytics'; import analytics from 'analytics';
import Wunderbar from './view'; import Wunderbar from './view';
import { withRouter } from 'react-router-dom'; import { withRouter } from 'react-router-dom';
@ -36,9 +36,4 @@ const perform = (dispatch, ownProps) => ({
doBlur: () => dispatch(doBlurSearchInput()), doBlur: () => dispatch(doBlurSearchInput()),
}); });
export default withRouter( export default withRouter(connect(select, perform)(Wunderbar));
connect(
select,
perform
)(Wunderbar)
);

View file

@ -198,3 +198,13 @@ export const DO_PREPARE_EDIT = 'DO_PREPARE_EDIT';
// media // media
export const MEDIA_PLAY = 'MEDIA_PLAY'; export const MEDIA_PLAY = 'MEDIA_PLAY';
export const MEDIA_PAUSE = 'MEDIA_PAUSE'; export const MEDIA_PAUSE = 'MEDIA_PAUSE';
// Notifications
export const CREATE_NOTIFICATION = 'CREATE_NOTIFICATION';
export const EDIT_NOTIFICATION = 'EDIT_NOTIFICATION';
export const DELETE_NOTIFICATION = 'DELETE_NOTIFICATION';
export const DISMISS_NOTIFICATION = 'DISMISS_NOTIFICATION';
export const CREATE_TOAST = 'CREATE_TOAST';
export const DISMISS_TOAST = 'DISMISS_TOAST';
export const CREATE_ERROR = 'CREATE_ERROR';
export const DISMISS_ERROR = 'DISMISS_ERROR';

View file

@ -14,7 +14,7 @@ import React, { Fragment, useState, useEffect } from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import { Provider } from 'react-redux'; import { Provider } from 'react-redux';
import { doDaemonReady, doAutoUpdate, doOpenModal, doHideModal, doToggle3PAnalytics } from 'redux/actions/app'; import { doDaemonReady, doAutoUpdate, doOpenModal, doHideModal, doToggle3PAnalytics } from 'redux/actions/app';
import { Lbry, doToast, isURIValid, setSearchApi, apiCall } from 'lbry-redux'; import { Lbry, isURIValid, setSearchApi, apiCall } from 'lbry-redux';
import { doSetLanguage, doFetchLanguage, doUpdateIsNightAsync } from 'redux/actions/settings'; import { doSetLanguage, doFetchLanguage, doUpdateIsNightAsync } from 'redux/actions/settings';
import { Lbryio, rewards, doBlackListedOutpointsSubscribe, doFilteredOutpointsSubscribe } from 'lbryinc'; import { Lbryio, rewards, doBlackListedOutpointsSubscribe, doFilteredOutpointsSubscribe } from 'lbryinc';
import { store, persistor, history } from 'store'; import { store, persistor, history } from 'store';
@ -24,6 +24,7 @@ import { ConnectedRouter, push } from 'connected-react-router';
import { formatLbryUrlForWeb, formatInAppUrl } from 'util/url'; import { formatLbryUrlForWeb, formatInAppUrl } from 'util/url';
import { PersistGate } from 'redux-persist/integration/react'; import { PersistGate } from 'redux-persist/integration/react';
import analytics from 'analytics'; import analytics from 'analytics';
import { doToast } from 'redux/actions/notifications';
import { import {
getAuthToken, getAuthToken,
setAuthToken, setAuthToken,

View file

@ -1,6 +1,7 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doHideModal } from 'redux/actions/app'; import { doHideModal } from 'redux/actions/app';
import { doToast, doUploadThumbnail } from 'lbry-redux'; import { doUploadThumbnail } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import ModalAutoGenerateThumbnail from './view'; import ModalAutoGenerateThumbnail from './view';
const perform = dispatch => ({ const perform = dispatch => ({
@ -9,7 +10,4 @@ const perform = dispatch => ({
showToast: options => dispatch(doToast(options)), showToast: options => dispatch(doToast(options)),
}); });
export default connect( export default connect(null, perform)(ModalAutoGenerateThumbnail);
null,
perform
)(ModalAutoGenerateThumbnail);

View file

@ -1,12 +1,9 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doDismissError } from 'lbry-redux'; import { doDismissError } from 'redux/actions/notifications';
import ModalError from './view'; import ModalError from './view';
const perform = dispatch => ({ const perform = dispatch => ({
closeModal: () => dispatch(doDismissError()), closeModal: () => dispatch(doDismissError()),
}); });
export default connect( export default connect(null, perform)(ModalError);
null,
perform
)(ModalError);

View file

@ -9,10 +9,10 @@ import {
selectRepostError, selectRepostError,
selectRepostLoading, selectRepostLoading,
doClearRepostError, doClearRepostError,
doToast,
selectMyClaimsWithoutChannels, selectMyClaimsWithoutChannels,
doCheckPublishNameAvailability, doCheckPublishNameAvailability,
} from 'lbry-redux'; } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import ModalRepost from './view'; import ModalRepost from './view';
const select = (state, props) => ({ const select = (state, props) => ({

View file

@ -1,7 +1,7 @@
import React, { Fragment } from 'react'; import React, { Fragment } from 'react';
import Button from 'component/button'; import Button from 'component/button';
import { FormField } from 'component/common/form'; import { FormField } from 'component/common/form';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import { Lbryio } from 'lbryinc'; import { Lbryio } from 'lbryinc';
import Page from 'component/page'; import Page from 'component/page';
import Card from 'component/common/card'; import Card from 'component/common/card';

View file

@ -1,5 +1,5 @@
import { connect } from 'react-redux'; import { connect } from 'react-redux';
import { doToast } from 'lbry-redux'; import { doToast } from 'redux/actions/notifications';
import SignInVerifyPage from './view'; import SignInVerifyPage from './view';
const select = () => ({}); const select = () => ({});
@ -7,7 +7,4 @@ const perform = {
doToast, doToast,
}; };
export default connect( export default connect(select, perform)(SignInVerifyPage);
select,
perform
)(SignInVerifyPage);

View file

@ -11,18 +11,17 @@ import {
Lbry, Lbry,
doBalanceSubscribe, doBalanceSubscribe,
doFetchFileInfos, doFetchFileInfos,
doError,
makeSelectClaimForUri, makeSelectClaimForUri,
makeSelectClaimIsMine, makeSelectClaimIsMine,
doPopulateSharedUserState, doPopulateSharedUserState,
doFetchChannelListMine, doFetchChannelListMine,
doClearPublish, doClearPublish,
doPreferenceGet, doPreferenceGet,
doToast,
doClearSupport, doClearSupport,
selectFollowedTagsList, selectFollowedTagsList,
// SHARED_PREFERENCES, // SHARED_PREFERENCES,
} from 'lbry-redux'; } from 'lbry-redux';
import { doToast, doError } from 'redux/actions/notifications';
import Native from 'native'; import Native from 'native';
import { import {
doFetchDaemonSettings, doFetchDaemonSettings,

View file

@ -0,0 +1,38 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import uuid from 'uuid/v4';
export function doToast(params: ToastParams) {
if (!params) {
throw Error("'params' object is required to create a toast notification");
}
return {
type: ACTIONS.CREATE_TOAST,
data: {
id: uuid(),
params,
},
};
}
export function doDismissToast() {
return {
type: ACTIONS.DISMISS_TOAST,
};
}
export function doError(error: string | {}) {
return {
type: ACTIONS.CREATE_ERROR,
data: {
error,
},
};
}
export function doDismissError() {
return {
type: ACTIONS.DISMISS_ERROR,
};
}

View file

@ -4,13 +4,13 @@ import * as ACTIONS from 'constants/action_types';
import * as PAGES from 'constants/pages'; import * as PAGES from 'constants/pages';
import { import {
batchActions, batchActions,
doError,
selectMyClaims, selectMyClaims,
doPublish, doPublish,
doCheckPendingPublishes, doCheckPendingPublishes,
doCheckReflectingFiles, doCheckReflectingFiles,
ACTIONS as LBRY_REDUX_ACTIONS, ACTIONS as LBRY_REDUX_ACTIONS,
} from 'lbry-redux'; } from 'lbry-redux';
import { doError } from 'redux/actions/notifications';
import { selectosNotificationsEnabled } from 'redux/selectors/settings'; import { selectosNotificationsEnabled } from 'redux/selectors/settings';
import { push } from 'connected-react-router'; import { push } from 'connected-react-router';
import analytics from 'analytics'; import analytics from 'analytics';

View file

@ -1,4 +1,5 @@
import { Lbry, ACTIONS, doToast, SHARED_PREFERENCES, doWalletReconnect, SETTINGS } from 'lbry-redux'; import { Lbry, ACTIONS, SHARED_PREFERENCES, doWalletReconnect, SETTINGS } from 'lbry-redux';
import { doToast } from 'redux/actions/notifications';
import * as LOCAL_ACTIONS from 'constants/action_types'; import * as LOCAL_ACTIONS from 'constants/action_types';
import analytics from 'analytics'; import analytics from 'analytics';
import SUPPORTED_LANGUAGES from 'constants/supported_languages'; import SUPPORTED_LANGUAGES from 'constants/supported_languages';

View file

@ -0,0 +1,94 @@
// @flow
import * as ACTIONS from 'constants/action_types';
import { handleActions } from 'util/redux-utils';
const defaultState: NotificationState = {
notifications: [],
toasts: [],
errors: [],
};
const notificationsReducer = handleActions(
{
// Toasts
[ACTIONS.CREATE_TOAST]: (state: NotificationState, action: DoToast) => {
const toast: Toast = action.data;
const newToasts: Array<Toast> = state.toasts.slice();
newToasts.push(toast);
return {
...state,
toasts: newToasts,
};
},
[ACTIONS.DISMISS_TOAST]: (state: NotificationState) => {
const newToasts: Array<Toast> = state.toasts.slice();
newToasts.shift();
return {
...state,
toasts: newToasts,
};
},
// Notifications
[ACTIONS.CREATE_NOTIFICATION]: (state: NotificationState, action: DoNotification) => {
const notification: Notification = action.data;
const newNotifications: Array<Notification> = state.notifications.slice();
newNotifications.push(notification);
return {
...state,
notifications: newNotifications,
};
},
// Used to mark notifications as read/dismissed
[ACTIONS.EDIT_NOTIFICATION]: (state: NotificationState, action: DoEditNotification) => {
const { notification } = action.data;
let notifications: Array<Notification> = state.notifications.slice();
notifications = notifications.map(pastNotification =>
pastNotification.id === notification.id ? notification : pastNotification
);
return {
...state,
notifications,
};
},
[ACTIONS.DELETE_NOTIFICATION]: (state: NotificationState, action: DoDeleteNotification) => {
const { id } = action.data;
let newNotifications: Array<Notification> = state.notifications.slice();
newNotifications = newNotifications.filter(notification => notification.id !== id);
return {
...state,
notifications: newNotifications,
};
},
// Errors
[ACTIONS.CREATE_ERROR]: (state: NotificationState, action: DoError) => {
const error: ErrorNotification = action.data;
const newErrors: Array<ErrorNotification> = state.errors.slice();
newErrors.push(error);
return {
...state,
errors: newErrors,
};
},
[ACTIONS.DISMISS_ERROR]: (state: NotificationState) => {
const newErrors: Array<ErrorNotification> = state.errors.slice();
newErrors.shift();
return {
...state,
errors: newErrors,
};
},
},
defaultState
);
export { notificationsReducer };

View file

@ -0,0 +1,26 @@
import { createSelector } from 'reselect';
export const selectState = state => state.notifications || {};
export const selectToast = createSelector(selectState, state => {
if (state.toasts.length) {
const { id, params } = state.toasts[0];
return {
id,
...params,
};
}
return null;
});
export const selectError = createSelector(selectState, state => {
if (state.errors.length) {
const { error } = state.errors[0];
return {
error,
};
}
return null;
});