lbry-desktop/ui/component/syncEnableFlow/view.jsx

245 lines
7.2 KiB
JavaScript

// @flow
import React from 'react';
import Button from 'component/button';
import { getSavedPassword } from 'util/saved-passwords';
import Card from 'component/common/card';
import { withRouter } from 'react-router';
import Spinner from 'component/spinner';
import Lbry from 'lbry';
import ErrorText from 'component/common/error-text';
import I18nMessage from 'component/i18nMessage';
type Props = {
setSyncEnabled: (boolean) => void,
syncEnabled: boolean,
getSyncError: ?string,
getSyncPending: boolean,
getSync: (pw: string, cb: () => void) => void,
checkSync: () => void,
closeModal: () => void,
updatePreferences: () => void,
mode: string,
};
const ENABLE_MODE = 'enable';
// steps
const FETCH_FOR_ENABLE = 'fetch-for-enable';
const FETCH_FOR_DISABLE = 'fetch-for-disable';
const CONFIRM = 'confirm';
const INITIAL = 'initial';
const ERROR = 'error';
const SHARED_KEY = 'shared';
const LOCAL_KEY = 'local';
function SyncEnableFlow(props: Props) {
const {
setSyncEnabled,
getSyncError,
getSyncPending,
getSync,
checkSync,
mode,
closeModal,
updatePreferences,
} = props;
const [step, setStep] = React.useState(INITIAL);
const [prefDict, setPrefDict]: [any, (any) => void] = React.useState();
const [error, setError] = React.useState();
const [password, setPassword] = React.useState('');
const handleSyncToggle = async () => {
const shared = prefDict.shared;
const local = prefDict.local;
let finalPrefs;
if (shared && local) {
if (mode === ENABLE_MODE) {
finalPrefs = makeMergedPrefs(local, shared);
} else {
finalPrefs = makeMergedPrefs(shared, local);
}
} else {
finalPrefs = local || shared || null;
}
// set busy (disable button)
if (finalPrefs) {
await Lbry.preference_set({ key: mode === ENABLE_MODE ? SHARED_KEY : LOCAL_KEY, value: finalPrefs });
}
await setSyncEnabled(mode === ENABLE_MODE);
await updatePreferences();
closeModal();
};
const makeMergedPrefs = (alt, base) => {
let finalPrefs = base;
let baseData = base.value;
let altData = alt.value;
if (!altData) {
return base;
}
let mergedBlockListSet = new Set(baseData.blocked || []);
let mergedSubscriptionsSet = new Set(baseData.subscriptions || []);
let mergedTagsSet = new Set(baseData.tags || []);
const altBlocklist = altData.blocked || [];
const altSubscriptions = altData.subscriptions || [];
const altTags = altData.tags || [];
if (altBlocklist.length) {
altBlocklist.forEach((el) => mergedBlockListSet.add(el));
}
if (altSubscriptions.length) {
altSubscriptions.forEach((el) => mergedSubscriptionsSet.add(el));
}
if (altTags.length) {
altTags.forEach((el) => mergedTagsSet.add(el));
}
baseData.blocked = Array.from(mergedBlockListSet);
baseData.subscriptions = Array.from(mergedSubscriptionsSet);
baseData.tags = Array.from(mergedTagsSet);
finalPrefs.value = baseData;
return finalPrefs;
};
React.useEffect(() => {
if (mode) {
checkSync();
if (mode === ENABLE_MODE) {
getSavedPassword().then((pw) => {
setPassword(pw);
setStep(FETCH_FOR_ENABLE);
});
} else {
setStep(FETCH_FOR_DISABLE);
}
}
}, [mode, setPassword]);
React.useEffect(() => {
if (step === FETCH_FOR_ENABLE) {
getSync(password, (e, hasChanged) => {
if (e) {
setStep(ERROR);
setError(e && e.message ? e.message : e);
} else {
Lbry.preference_get().then((result) => {
const prefs = {};
if (result[SHARED_KEY]) prefs[SHARED_KEY] = result[SHARED_KEY];
if (result[LOCAL_KEY]) prefs[LOCAL_KEY] = result[LOCAL_KEY];
setPrefDict(prefs);
setStep(CONFIRM);
});
}
});
}
if (step === FETCH_FOR_DISABLE) {
Lbry.preference_get().then((result) => {
const prefs = {};
if (result[SHARED_KEY]) prefs[SHARED_KEY] = result[SHARED_KEY];
if (result[LOCAL_KEY]) prefs[LOCAL_KEY] = result[LOCAL_KEY];
setPrefDict(prefs);
setStep(CONFIRM);
});
}
}, [step, setPrefDict, setStep, password]);
if (getSyncPending) {
return (
<div>
<Spinner />
</div>
);
}
return (
<Card
title={mode === ENABLE_MODE ? 'Enable Sync' : 'Disable Sync'}
subtitle={
<div>
{(error || getSyncError) && (
<I18nMessage
tokens={{
click_here: (
<Button
button="link"
href="https://lbry.com/faq/accounts-and-sync#limitations"
label={__('Click here')}
/>
),
}}
>
Something went wrong. Please %click_here% to learn about sync limitations.
</I18nMessage>
)}
{step === INITIAL && (
<>
<h1>{__(`Please wait...`)}</h1>
<Spinner />
</>
)}
{(step === FETCH_FOR_ENABLE || step === FETCH_FOR_DISABLE) && (
<>
<h1>{__(`Getting your profiles...`)}</h1>
<Spinner />
</>
)}
{step === CONFIRM && mode === ENABLE_MODE && (
<>
<h1>{__(`Enabling sync will switch to your cloud profile.`)}</h1>
</>
)}
{step === CONFIRM && mode !== ENABLE_MODE && (
<>
<h1>{__(`Disabling sync will switch to your local profile.`)}</h1>
</>
)}
{(error || getSyncError) && (
<>
<ErrorText>{error || (getSyncError && String(getSyncError)) || __('Unknown error')}</ErrorText>
</>
)}
</div>
}
actions={
<>
{step === CONFIRM && (
<div className={'card__actions'}>
<Button
button="primary"
name={'syncbutton'}
label={mode === ENABLE_MODE ? __('Enable Sync') : __('Disable Sync')}
onClick={() => handleSyncToggle()}
/>
<Button button="link" name={'cancel'} label={__('Cancel')} onClick={() => closeModal()} />
</div>
)}
{(step === FETCH_FOR_ENABLE || step === FETCH_FOR_DISABLE) && (
<div className={'card__actions'}>
<Button
button="primary"
name={'syncbutton'}
label={mode === ENABLE_MODE ? __('Enable Sync') : __('Disable Sync')}
onClick={() => handleSyncToggle()}
disabled
/>
<Button button="link" name={'cancel'} label={__('Cancel')} onClick={() => closeModal()} />
</div>
)}
{(error || getSyncError) && (
<div className={'card__actions'}>
<Button button="primary" name={'cancel'} label={__('Close')} onClick={() => closeModal()} />
<ErrorText>{error || (getSyncError && String(getSyncError)) || __('Unknown error')}</ErrorText>
</div>
)}
</>
}
/>
);
}
export default withRouter(SyncEnableFlow);