Files
standardnotes-app-web/app/assets/javascripts/preferences/panes/account/Sync.tsx
Vardan Hakobyan 8db549f6f6 feat: handle unprotected session expiration (#747)
* feat: hide note contents if the protection expires when the protected note is open and wasn't edited for a while

* feat: handle session expiration for opened protected note for both plain advanced editors

* fix: if after canceling  session expiry modal only one unprotected note stays selected, show its contents in the editor

* refactor: handle session expiration for opened protected note (move the logic to web client)

* feat: handle the case of selecting "Don't remember" option in session expiry dialog

* test (WIP): add unit tests for protecting opened note after the session has expired

* test: add remaining unit tests

* refactor: move the opened note protection logic to "editor_view"

* refactor: reviewer comments
- don't rely on user signed-in/out status to require authentication for protected note
- remove unnecessary async/awaits
- better wording on ui

* refactor: reviewer's comments:
 - use snjs method to check if "Don't remember" option is selected in authentication modal
 - move the constant to snjs
 - fix eslint error

* refactor: avoid `any` type for `appEvent` payload

* test: add unit tests

* chore: update function name

* refactor: use simpler protection session event types

* refactor: protected access terminology

* refactor: start counting idle timer after every edit (instead of counting by interval in spite of edits)

* test: unit tests

* style: don't give extra brightness to the "View Note"/"Authenticate" button on hover/focus

* chore: bump snjs version

Co-authored-by: Mo Bitar <me@bitar.io>
2021-12-14 19:14:01 +04:00

70 lines
2.1 KiB
TypeScript

import {
PreferencesGroup,
PreferencesSegment,
Text,
Title,
} from '@/preferences/components';
import { Button } from '@/components/Button';
import { SyncQueueStrategy, dateToLocalizedString } from '@standardnotes/snjs';
import { STRING_GENERIC_SYNC_ERROR } from '@/strings';
import { useState } from '@node_modules/preact/hooks';
import { observer } from 'mobx-react-lite';
import { WebApplication } from '@/ui_models/application';
import { FunctionComponent } from 'preact';
type Props = {
application: WebApplication;
};
export const formatLastSyncDate = (lastUpdatedDate: Date) => {
return dateToLocalizedString(lastUpdatedDate);
};
export const Sync: FunctionComponent<Props> = observer(
({ application }: Props) => {
const [isSyncingInProgress, setIsSyncingInProgress] = useState(false);
const [lastSyncDate, setLastSyncDate] = useState(
formatLastSyncDate(application.getLastSyncDate() as Date)
);
const doSynchronization = async () => {
setIsSyncingInProgress(true);
const response = await application.sync({
queueStrategy: SyncQueueStrategy.ForceSpawnNew,
checkIntegrity: true,
});
setIsSyncingInProgress(false);
if (response && response.error) {
application.alertService!.alert(STRING_GENERIC_SYNC_ERROR);
} else {
setLastSyncDate(
formatLastSyncDate(application.getLastSyncDate() as Date)
);
}
};
return (
<PreferencesGroup>
<PreferencesSegment>
<div className="flex flex-row items-center">
<div className="flex-grow flex flex-col">
<Title>Sync</Title>
<Text>
Last synced <span className="font-bold">on {lastSyncDate}</span>
</Text>
<Button
className="min-w-20 mt-3"
type="normal"
label="Sync now"
disabled={isSyncingInProgress}
onClick={doSynchronization}
/>
</div>
</div>
</PreferencesSegment>
</PreferencesGroup>
);
}
);