Merge branch 'fe-config-cache' into 'develop'

Offline: persist Soapbox config (eg frontend_configurations or soapbox.json)

See merge request soapbox-pub/soapbox-fe!873
features-override
Alex Gleason 2021-11-15 22:59:58 +00:00
commit 3414363245
5 zmienionych plików z 67 dodań i 13 usunięć

Wyświetl plik

@ -22,7 +22,7 @@ const getMeUrl = state => {
}; };
// Figure out the appropriate instance to fetch depending on the state // Figure out the appropriate instance to fetch depending on the state
const getHost = state => { export const getHost = state => {
const accountUrl = getMeUrl(state) || getAuthUserUrl(state); const accountUrl = getMeUrl(state) || getAuthUserUrl(state);
try { try {

Wyświetl plik

@ -2,10 +2,16 @@ import api, { staticClient } from '../api';
import { Map as ImmutableMap, List as ImmutableList } from 'immutable'; import { Map as ImmutableMap, List as ImmutableList } from 'immutable';
import { getFeatures } from 'soapbox/utils/features'; import { getFeatures } from 'soapbox/utils/features';
import { createSelector } from 'reselect'; import { createSelector } from 'reselect';
import { getHost } from 'soapbox/actions/instance';
import KVStore from 'soapbox/storage/kv_store';
export const SOAPBOX_CONFIG_REQUEST_SUCCESS = 'SOAPBOX_CONFIG_REQUEST_SUCCESS'; export const SOAPBOX_CONFIG_REQUEST_SUCCESS = 'SOAPBOX_CONFIG_REQUEST_SUCCESS';
export const SOAPBOX_CONFIG_REQUEST_FAIL = 'SOAPBOX_CONFIG_REQUEST_FAIL'; export const SOAPBOX_CONFIG_REQUEST_FAIL = 'SOAPBOX_CONFIG_REQUEST_FAIL';
export const SOAPBOX_CONFIG_REMEMBER_REQUEST = 'SOAPBOX_CONFIG_REMEMBER_REQUEST';
export const SOAPBOX_CONFIG_REMEMBER_SUCCESS = 'SOAPBOX_CONFIG_REMEMBER_SUCCESS';
export const SOAPBOX_CONFIG_REMEMBER_FAIL = 'SOAPBOX_CONFIG_REMEMBER_FAIL';
const allowedEmoji = ImmutableList([ const allowedEmoji = ImmutableList([
'👍', '👍',
'❤', '❤',
@ -61,46 +67,71 @@ export const getSoapboxConfig = createSelector([
return makeDefaultConfig(features).merge(soapbox); return makeDefaultConfig(features).merge(soapbox);
}); });
export function fetchSoapboxConfig() { export function rememberSoapboxConfig(host) {
return (dispatch, getState) => {
dispatch({ type: SOAPBOX_CONFIG_REMEMBER_REQUEST, host });
return KVStore.getItemOrError(`soapbox_config:${host}`).then(soapboxConfig => {
dispatch({ type: SOAPBOX_CONFIG_REMEMBER_SUCCESS, host, soapboxConfig });
return soapboxConfig;
}).catch(error => {
dispatch({ type: SOAPBOX_CONFIG_REMEMBER_FAIL, host, error, skipAlert: true });
});
};
}
export function fetchSoapboxConfig(host) {
return (dispatch, getState) => { return (dispatch, getState) => {
api(getState).get('/api/pleroma/frontend_configurations').then(response => { api(getState).get('/api/pleroma/frontend_configurations').then(response => {
if (response.data.soapbox_fe) { if (response.data.soapbox_fe) {
dispatch(importSoapboxConfig(response.data.soapbox_fe)); dispatch(importSoapboxConfig(response.data.soapbox_fe, host));
} else { } else {
dispatch(fetchSoapboxJson()); dispatch(fetchSoapboxJson(host));
} }
}).catch(error => { }).catch(error => {
dispatch(fetchSoapboxJson()); dispatch(fetchSoapboxJson(host));
}); });
}; };
} }
export function fetchSoapboxJson() { // Tries to remember the config from browser storage before fetching it
export function loadSoapboxConfig() {
return (dispatch, getState) => {
const host = getHost(getState());
return dispatch(rememberSoapboxConfig(host)).finally(() => {
return dispatch(fetchSoapboxConfig(host));
});
};
}
export function fetchSoapboxJson(host) {
return (dispatch, getState) => { return (dispatch, getState) => {
staticClient.get('/instance/soapbox.json').then(({ data }) => { staticClient.get('/instance/soapbox.json').then(({ data }) => {
if (!isObject(data)) throw 'soapbox.json failed'; if (!isObject(data)) throw 'soapbox.json failed';
dispatch(importSoapboxConfig(data)); dispatch(importSoapboxConfig(data, host));
}).catch(error => { }).catch(error => {
dispatch(soapboxConfigFail(error)); dispatch(soapboxConfigFail(error, host));
}); });
}; };
} }
export function importSoapboxConfig(soapboxConfig) { export function importSoapboxConfig(soapboxConfig, host) {
if (!soapboxConfig.brandColor) { if (!soapboxConfig.brandColor) {
soapboxConfig.brandColor = '#0482d8'; soapboxConfig.brandColor = '#0482d8';
} }
return { return {
type: SOAPBOX_CONFIG_REQUEST_SUCCESS, type: SOAPBOX_CONFIG_REQUEST_SUCCESS,
soapboxConfig, soapboxConfig,
host,
}; };
} }
export function soapboxConfigFail(error) { export function soapboxConfigFail(error, host) {
return { return {
type: SOAPBOX_CONFIG_REQUEST_FAIL, type: SOAPBOX_CONFIG_REQUEST_FAIL,
error, error,
skipAlert: true, skipAlert: true,
host,
}; };
} }

Wyświetl plik

@ -17,7 +17,7 @@ import { preload } from '../actions/preload';
import { IntlProvider } from 'react-intl'; import { IntlProvider } from 'react-intl';
import ErrorBoundary from '../components/error_boundary'; import ErrorBoundary from '../components/error_boundary';
import { loadInstance } from 'soapbox/actions/instance'; import { loadInstance } from 'soapbox/actions/instance';
import { fetchSoapboxConfig } from 'soapbox/actions/soapbox'; import { loadSoapboxConfig } from 'soapbox/actions/soapbox';
import { fetchMe } from 'soapbox/actions/me'; import { fetchMe } from 'soapbox/actions/me';
import PublicLayout from 'soapbox/features/public_layout'; import PublicLayout from 'soapbox/features/public_layout';
import { getSettings } from 'soapbox/actions/settings'; import { getSettings } from 'soapbox/actions/settings';
@ -43,7 +43,7 @@ store.dispatch(fetchMe())
.then(() => { .then(() => {
// Postpone for authenticated fetch // Postpone for authenticated fetch
store.dispatch(loadInstance()); store.dispatch(loadInstance());
store.dispatch(fetchSoapboxConfig()); store.dispatch(loadSoapboxConfig());
}) })
.catch(() => {}); .catch(() => {});

Wyświetl plik

@ -6,6 +6,7 @@ import {
import { PLEROMA_PRELOAD_IMPORT } from 'soapbox/actions/preload'; import { PLEROMA_PRELOAD_IMPORT } from 'soapbox/actions/preload';
import { Map as ImmutableMap, fromJS } from 'immutable'; import { Map as ImmutableMap, fromJS } from 'immutable';
import { ConfigDB } from 'soapbox/utils/config_db'; import { ConfigDB } from 'soapbox/utils/config_db';
import KVStore from 'soapbox/storage/kv_store';
const initialState = ImmutableMap(); const initialState = ImmutableMap();
@ -36,12 +37,23 @@ const preloadImport = (state, action) => {
} }
}; };
const persistSoapboxConfig = (soapboxConfig, host) => {
if (host) {
KVStore.setItem(`soapbox_config:${host}`, soapboxConfig.toJS()).catch(console.error);
}
};
const importSoapboxConfig = (state, soapboxConfig, host) => {
persistSoapboxConfig(soapboxConfig, host);
return soapboxConfig;
};
export default function soapbox(state = initialState, action) { export default function soapbox(state = initialState, action) {
switch(action.type) { switch(action.type) {
case PLEROMA_PRELOAD_IMPORT: case PLEROMA_PRELOAD_IMPORT:
return preloadImport(state, action); return preloadImport(state, action);
case SOAPBOX_CONFIG_REQUEST_SUCCESS: case SOAPBOX_CONFIG_REQUEST_SUCCESS:
return fromJS(action.soapboxConfig); return importSoapboxConfig(state, fromJS(action.soapboxConfig), action.host);
case SOAPBOX_CONFIG_REQUEST_FAIL: case SOAPBOX_CONFIG_REQUEST_FAIL:
return fallbackState.mergeDeep(state); return fallbackState.mergeDeep(state);
case ADMIN_CONFIG_UPDATE_SUCCESS: case ADMIN_CONFIG_UPDATE_SUCCESS:

Wyświetl plik

@ -0,0 +1,11 @@
export const getHost = instance => {
try {
return new URL(instance.get('uri')).host;
} catch {
try {
return new URL(`https://${instance.get('uri')}`).host;
} catch {
return null;
}
}
};