d9bf72a351
sync settings backout nav cases and anon preference key more robust backout header put notificationSettings under backout bar review changes
202 lines
6.2 KiB
JavaScript
202 lines
6.2 KiB
JavaScript
import * as ACTIONS from 'constants/action_types';
|
|
import { persistStore, persistReducer } from 'redux-persist';
|
|
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
|
|
import createCompressor from 'redux-persist-transform-compress';
|
|
import { createFilter, createBlacklistFilter } from 'redux-persist-transform-filter';
|
|
import localForage from 'localforage';
|
|
import { createStore, applyMiddleware, compose } from 'redux';
|
|
import thunk from 'redux-thunk';
|
|
import { createMemoryHistory, createBrowserHistory } from 'history';
|
|
import { routerMiddleware } from 'connected-react-router';
|
|
import createRootReducer from './reducers';
|
|
import { Lbry, buildSharedStateMiddleware, ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS } from 'lbry-redux';
|
|
import { doGetSync } from 'lbryinc';
|
|
import { selectUserVerifiedEmail } from 'redux/selectors/user';
|
|
import { getSavedPassword, getAuthToken } from 'util/saved-passwords';
|
|
import { makeSelectClientSetting } from 'redux/selectors/settings';
|
|
import { generateInitialUrl } from 'util/url';
|
|
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
|
|
|
|
function isFunction(object) {
|
|
return typeof object === 'function';
|
|
}
|
|
|
|
function isNotFunction(object) {
|
|
return !isFunction(object);
|
|
}
|
|
|
|
function createBulkThunkMiddleware() {
|
|
return ({ dispatch, getState }) => next => action => {
|
|
if (action.type === 'BATCH_ACTIONS') {
|
|
action.actions.filter(isFunction).map(actionFn => actionFn(dispatch, getState));
|
|
}
|
|
return next(action);
|
|
};
|
|
}
|
|
|
|
function enableBatching(reducer) {
|
|
return function batchingReducer(state, action) {
|
|
switch (action.type) {
|
|
case 'BATCH_ACTIONS':
|
|
return action.actions.filter(isNotFunction).reduce(batchingReducer, state);
|
|
default:
|
|
return reducer(state, action);
|
|
}
|
|
};
|
|
}
|
|
|
|
const contentFilter = createFilter('content', ['positions', 'history']);
|
|
const fileInfoFilter = createFilter('fileInfo', [
|
|
'fileListPublishedSort',
|
|
'fileListDownloadedSort',
|
|
'fileListSubscriptionSort',
|
|
]);
|
|
const appFilter = createFilter('app', [
|
|
'hasClickedComment',
|
|
'searchOptionsExpanded',
|
|
'volume',
|
|
'muted',
|
|
'allowAnalytics',
|
|
'welcomeVersion',
|
|
]);
|
|
// We only need to persist the receiveAddress for the wallet
|
|
const walletFilter = createFilter('wallet', ['receiveAddress']);
|
|
const searchFilter = createFilter('search', ['options']);
|
|
const tagsFilter = createFilter('tags', ['followedTags']);
|
|
const subscriptionsFilter = createFilter('subscriptions', ['subscriptions']);
|
|
const blockedFilter = createFilter('blocked', ['blockedChannels']);
|
|
const settingsFilter = createBlacklistFilter('settings', ['loadedLanguages', 'language']);
|
|
const whiteListedReducers = [
|
|
'fileInfo',
|
|
'publish',
|
|
'wallet',
|
|
'tags',
|
|
'content',
|
|
'app',
|
|
'search',
|
|
'blocked',
|
|
'settings',
|
|
'subscriptions',
|
|
];
|
|
|
|
const transforms = [
|
|
fileInfoFilter,
|
|
walletFilter,
|
|
blockedFilter,
|
|
tagsFilter,
|
|
appFilter,
|
|
searchFilter,
|
|
tagsFilter,
|
|
contentFilter,
|
|
subscriptionsFilter,
|
|
settingsFilter,
|
|
createCompressor(),
|
|
];
|
|
|
|
const persistOptions = {
|
|
key: 'v0',
|
|
storage: localForage,
|
|
stateReconciler: autoMergeLevel2,
|
|
whitelist: whiteListedReducers,
|
|
// Order is important. Needs to be compressed last or other transforms can't
|
|
// read the data
|
|
transforms,
|
|
};
|
|
|
|
let history;
|
|
// @if TARGET='app'
|
|
history = createMemoryHistory({
|
|
initialEntries: [generateInitialUrl(window.location.hash)],
|
|
initialIndex: 0,
|
|
});
|
|
// @endif
|
|
// @if TARGET='web'
|
|
history = createBrowserHistory();
|
|
// @endif
|
|
|
|
const triggerSharedStateActions = [
|
|
ACTIONS.CHANNEL_SUBSCRIBE,
|
|
ACTIONS.CHANNEL_UNSUBSCRIBE,
|
|
ACTIONS.TOGGLE_BLOCK_CHANNEL,
|
|
LBRY_REDUX_ACTIONS.TOGGLE_TAG_FOLLOW,
|
|
LBRY_REDUX_ACTIONS.CREATE_CHANNEL_COMPLETED,
|
|
ACTIONS.SYNC_CLIENT_SETTINGS,
|
|
// Disabled until we can overwrite preferences
|
|
LBRY_REDUX_ACTIONS.SHARED_PREFERENCE_SET,
|
|
// ACTIONS.SET_WELCOME_VERSION,
|
|
// ACTIONS.SET_ALLOW_ANALYTICS,
|
|
];
|
|
|
|
/**
|
|
* source: the reducer name
|
|
* property: the property in the reducer-specific state
|
|
* transform: optional method to modify the value to be stored
|
|
*
|
|
* See https://github.com/lbryio/lbry-redux/blob/master/src/redux/middleware/shared-state.js for the source
|
|
* This is based off v0.1
|
|
* If lbry-redux changes to another version, this code will need to be changed when upgrading
|
|
*/
|
|
const sharedStateFilters = {
|
|
tags: { source: 'tags', property: 'followedTags' },
|
|
subscriptions: {
|
|
source: 'subscriptions',
|
|
property: 'subscriptions',
|
|
transform: function(value) {
|
|
return value.map(({ uri }) => uri);
|
|
},
|
|
},
|
|
blocked: { source: 'blocked', property: 'blockedChannels' },
|
|
settings: { source: 'settings', property: 'sharedPreferences' },
|
|
app_welcome_version: { source: 'app', property: 'welcomeVersion' },
|
|
sharing_3P: { source: 'app', property: 'allowAnalytics' },
|
|
};
|
|
|
|
const sharedStateCb = ({ dispatch, getState }) => {
|
|
const state = getState();
|
|
const syncEnabled = makeSelectClientSetting(SETTINGS.ENABLE_SYNC)(state);
|
|
const emailVerified = selectUserVerifiedEmail(state);
|
|
if (syncEnabled && emailVerified) {
|
|
getSavedPassword().then(savedPassword => {
|
|
dispatch(doGetSync(savedPassword));
|
|
});
|
|
}
|
|
};
|
|
|
|
const populateAuthTokenHeader = () => {
|
|
return next => action => {
|
|
if (
|
|
(action.type === ACTIONS.USER_FETCH_SUCCESS || action.type === ACTIONS.AUTHENTICATION_SUCCESS) &&
|
|
action.data.user.has_verified_email === true
|
|
) {
|
|
const authToken = getAuthToken();
|
|
Lbry.setApiHeader(X_LBRY_AUTH_TOKEN, authToken);
|
|
}
|
|
|
|
return next(action);
|
|
};
|
|
};
|
|
|
|
const sharedStateMiddleware = buildSharedStateMiddleware(triggerSharedStateActions, sharedStateFilters, sharedStateCb);
|
|
const rootReducer = createRootReducer(history);
|
|
const persistedReducer = persistReducer(persistOptions, rootReducer);
|
|
const bulkThunk = createBulkThunkMiddleware();
|
|
const middleware = [
|
|
sharedStateMiddleware,
|
|
// @if TARGET='web'
|
|
populateAuthTokenHeader,
|
|
// @endif
|
|
routerMiddleware(history),
|
|
thunk,
|
|
bulkThunk,
|
|
];
|
|
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
|
|
const store = createStore(
|
|
enableBatching(persistedReducer),
|
|
{}, // initial state
|
|
composeEnhancers(applyMiddleware(...middleware))
|
|
);
|
|
|
|
const persistor = persistStore(store);
|
|
window.persistor = persistor;
|
|
|
|
export { store, persistor, history, whiteListedReducers };
|