lbry-desktop/ui/store.js

201 lines
6.2 KiB
JavaScript
Raw Normal View History

2019-10-15 06:20:12 +02:00
import * as ACTIONS from 'constants/action_types';
2019-07-23 10:05:51 +02:00
import { persistStore, persistReducer } from 'redux-persist';
import autoMergeLevel2 from 'redux-persist/lib/stateReconciler/autoMergeLevel2';
import createCompressor from 'redux-persist-transform-compress';
2019-11-12 23:03:11 +01:00
import { createFilter, createBlacklistFilter } from 'redux-persist-transform-filter';
import localForage from 'localforage';
2019-04-04 23:05:23 +02:00
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import { createMemoryHistory, createBrowserHistory } from 'history';
2019-06-11 20:10:58 +02:00
import { routerMiddleware } from 'connected-react-router';
2019-04-04 23:05:23 +02:00
import createRootReducer from './reducers';
import { Lbry, buildSharedStateMiddleware, ACTIONS as LBRY_REDUX_ACTIONS, SETTINGS } from 'lbry-redux';
import { LBRYINC_ACTIONS, doGetSync, selectUserVerifiedEmail } from 'lbryinc';
import { getSavedPassword, getAuthToken } from 'util/saved-passwords';
2019-10-15 06:20:12 +02:00
import { makeSelectClientSetting } from 'redux/selectors/settings';
2020-02-12 05:59:30 +01:00
import { generateInitialUrl } from 'util/url';
import { X_LBRY_AUTH_TOKEN } from 'constants/token';
2017-04-07 07:15:22 +02:00
function isFunction(object) {
return typeof object === 'function';
2017-04-07 07:15:22 +02:00
}
function isNotFunction(object) {
return !isFunction(object);
2017-04-07 07:15:22 +02:00
}
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',
]);
2018-04-18 06:03:01 +02:00
// We only need to persist the receiveAddress for the wallet
const walletFilter = createFilter('wallet', ['receiveAddress']);
2019-02-18 18:24:56 +01:00
const searchFilter = createFilter('search', ['options']);
2019-07-02 23:00:05 +02:00
const tagsFilter = createFilter('tags', ['followedTags']);
2019-10-15 06:20:12 +02:00
const subscriptionsFilter = createFilter('subscriptions', ['subscriptions']);
2019-08-02 17:11:31 +02:00
const blockedFilter = createFilter('blocked', ['blockedChannels']);
2019-11-12 23:18:50 +01:00
const settingsFilter = createBlacklistFilter('settings', ['loadedLanguages', 'language']);
2019-07-01 06:35:36 +02:00
const whiteListedReducers = [
2019-10-24 20:07:48 +02:00
'fileInfo',
2019-07-01 06:35:36 +02:00
'publish',
'wallet',
2019-09-26 18:07:11 +02:00
'tags',
2019-07-01 06:35:36 +02:00
'content',
'app',
'search',
2019-08-02 17:11:31 +02:00
'blocked',
2019-09-17 20:49:03 +02:00
'settings',
2019-10-15 06:20:12 +02:00
'subscriptions',
2019-07-01 06:35:36 +02:00
];
2019-07-02 23:00:05 +02:00
2019-07-23 10:05:51 +02:00
const transforms = [
fileInfoFilter,
2019-10-24 20:07:48 +02:00
walletFilter,
blockedFilter,
2019-09-26 18:07:11 +02:00
tagsFilter,
2019-07-23 10:05:51 +02:00
appFilter,
searchFilter,
tagsFilter,
2019-09-17 20:57:22 +02:00
contentFilter,
2019-10-15 06:20:12 +02:00
subscriptionsFilter,
2019-11-12 23:03:11 +01:00
settingsFilter,
2019-07-23 10:05:51 +02:00
createCompressor(),
];
const persistOptions = {
2019-07-23 10:05:51 +02:00
key: 'v0',
storage: localForage,
stateReconciler: autoMergeLevel2,
2019-07-01 06:35:36 +02:00
whitelist: whiteListedReducers,
// Order is important. Needs to be compressed last or other transforms can't
// read the data
2019-07-23 10:05:51 +02:00
transforms,
};
2017-04-07 07:15:22 +02:00
2019-07-23 10:05:51 +02:00
let history;
// @if TARGET='app'
history = createMemoryHistory({
2020-02-12 05:59:30 +01:00
initialEntries: [generateInitialUrl(window.location.hash)],
initialIndex: 0,
});
2019-07-23 10:05:51 +02:00
// @endif
// @if TARGET='web'
history = createBrowserHistory();
// @endif
2019-10-15 17:47:43 +02:00
const triggerSharedStateActions = [
2019-10-15 06:20:12 +02:00
ACTIONS.CHANNEL_SUBSCRIBE,
ACTIONS.CHANNEL_UNSUBSCRIBE,
LBRY_REDUX_ACTIONS.TOGGLE_TAG_FOLLOW,
LBRY_REDUX_ACTIONS.TOGGLE_BLOCK_CHANNEL,
2019-10-15 17:47:43 +02:00
LBRY_REDUX_ACTIONS.CREATE_CHANNEL_COMPLETED,
2020-02-25 17:55:22 +01:00
// Disabled until we can overwrite preferences
// LBRY_REDUX_ACTIONS.SHARED_PREFERENCE_SET,
// ACTIONS.SET_WELCOME_VERSION,
// ACTIONS.SET_ALLOW_ANALYTICS,
2019-10-15 06:20:12 +02:00
];
/**
* source: the reducer name
* property: the property in the reducer-specific state
* transform: optional method to modify the value to be stored
2019-10-15 18:09:33 +02:00
*
* 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
2019-10-15 06:20:12 +02:00
*/
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' },
2019-12-13 20:47:50 +01:00
settings: { source: 'settings', property: 'sharedPreferences' },
app_welcome_version: { source: 'app', property: 'welcomeVersion' },
sharing_3P: { source: 'app', property: 'allowAnalytics' },
2019-10-15 06:20:12 +02:00
};
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 === LBRYINC_ACTIONS.USER_FETCH_SUCCESS || action.type === LBRYINC_ACTIONS.AUTHENTICATION_SUCCESS) &&
action.data.user.has_verified_email === true
) {
const authToken = getAuthToken();
Lbry.setApiHeader(X_LBRY_AUTH_TOKEN, authToken);
}
2020-06-08 20:22:03 +02:00
return next(action);
};
};
2019-10-15 17:47:43 +02:00
const sharedStateMiddleware = buildSharedStateMiddleware(triggerSharedStateActions, sharedStateFilters, sharedStateCb);
2019-07-23 10:05:51 +02:00
const rootReducer = createRootReducer(history);
const persistedReducer = persistReducer(persistOptions, rootReducer);
const bulkThunk = createBulkThunkMiddleware();
const middleware = [
sharedStateMiddleware,
// @if TARGET='web'
populateAuthTokenHeader,
// @endif
routerMiddleware(history),
thunk,
bulkThunk,
];
2019-07-23 10:05:51 +02:00
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;
2017-12-08 21:14:35 +01:00
2019-07-23 10:05:51 +02:00
export { store, persistor, history, whiteListedReducers };