一些检查失败了
automerge / automerge (push) Has been cancelled
react-native-android-build-apk / AssembleRelease (push) Has been cancelled
Build macOS M1 / Main (push) Has been cancelled
Joplin Continuous Integration / Main (macos-15-intel) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / Main (ubuntu-22.04-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-11-vs2026-arm) (push) Has been cancelled
Joplin Continuous Integration / Main (windows-2025) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04) (push) Has been cancelled
Joplin Continuous Integration / ServerDockerImage (ubuntu-22.04-arm) (push) Has been cancelled
Joplin UI tests / Main (ubuntu-22.04) (push) Has been cancelled
Joplin UI tests / Main (windows-2025) (push) Has been cancelled
Joplin UI tests / Mobile (push) Has been cancelled
Close stale issues / ProcessStaleIssues (push) Has been cancelled
92 行
3.1 KiB
TypeScript
92 行
3.1 KiB
TypeScript
import * as React from 'react';
|
|
import { Dispatch } from 'redux';
|
|
import { useCallback, useState } from 'react';
|
|
import { _ } from '@joplin/lib/locale';
|
|
import DialogButtonRow, { ClickEvent } from '../DialogButtonRow';
|
|
import Dialog from '@joplin/lib/components/Dialog';
|
|
import DialogTitle from '../DialogTitle';
|
|
import LabelledPasswordInput from '../PasswordInput/LabelledPasswordInput';
|
|
import { confirmAndSkipNoteLockKeyMigration, startNoteLockKeyMigration } from '@joplin/lib/services/noteLock/NoteLockKeyMigration';
|
|
|
|
interface Props {
|
|
themeId: number;
|
|
dispatch: Dispatch;
|
|
}
|
|
|
|
export default function(props: Props) {
|
|
const [localPassword, setLocalPassword] = useState('');
|
|
const [targetPassword, setTargetPassword] = useState('');
|
|
const [migrating, setMigrating] = useState(false);
|
|
const [errorMessage, setErrorMessage] = useState('');
|
|
|
|
const onClose = useCallback(() => {
|
|
props.dispatch({
|
|
type: 'DIALOG_CLOSE',
|
|
name: 'noteLockMigration',
|
|
});
|
|
}, [props.dispatch]);
|
|
|
|
const onLocalPasswordChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
|
setLocalPassword(event.target.value);
|
|
}, []);
|
|
|
|
const onTargetPasswordChange = useCallback((event: React.ChangeEvent<HTMLInputElement>) => {
|
|
setTargetPassword(event.target.value);
|
|
}, []);
|
|
|
|
const onButtonRowClick = useCallback(async (event: ClickEvent) => {
|
|
if (event.buttonName === 'cancel') {
|
|
onClose();
|
|
return;
|
|
}
|
|
|
|
if (event.buttonName === 'skip') {
|
|
if (await confirmAndSkipNoteLockKeyMigration(props.dispatch)) onClose();
|
|
return;
|
|
}
|
|
|
|
if (event.buttonName === 'ok') {
|
|
setMigrating(true);
|
|
setErrorMessage('');
|
|
try {
|
|
await startNoteLockKeyMigration(localPassword, targetPassword, props.dispatch, onClose);
|
|
} catch (error) {
|
|
setErrorMessage(error.name === 'OperationError' ? _('Invalid password') : error.message);
|
|
setMigrating(false);
|
|
}
|
|
}
|
|
}, [localPassword, targetPassword, onClose, props.dispatch]);
|
|
|
|
return (
|
|
<Dialog onCancel={migrating ? undefined : onClose} className="note-lock-migration-dialog">
|
|
<div className="dialog-root">
|
|
<DialogTitle title={_('Migrate locked notes')}/>
|
|
<div className="dialog-content">
|
|
<p>{_('The sync target uses a different note lock key to the one on your device. Your locked notes must be re-encrypted with the synced key before synchronisation can continue. Locked notes cannot be read while they are being migrated.')}</p>
|
|
<div className="form">
|
|
<LabelledPasswordInput
|
|
labelText={_('Note lock password on this device')}
|
|
value={localPassword}
|
|
onChange={onLocalPasswordChange}
|
|
/>
|
|
<LabelledPasswordInput
|
|
labelText={_('Note lock password on the sync target')}
|
|
value={targetPassword}
|
|
onChange={onTargetPasswordChange}
|
|
/>
|
|
</div>
|
|
{!!errorMessage && <p className="error-message" role="alert">{errorMessage}</p>}
|
|
</div>
|
|
<DialogButtonRow
|
|
themeId={props.themeId}
|
|
onClick={onButtonRowClick}
|
|
okButtonLabel={_('Migrate')}
|
|
okButtonDisabled={!localPassword || !targetPassword || migrating}
|
|
cancelButtonDisabled={migrating}
|
|
customButtons={[{ name: 'skip', label: _('Skip'), disabled: migrating }]}
|
|
/>
|
|
</div>
|
|
</Dialog>
|
|
);
|
|
}
|