import { Button , FileInput , Intent } from '@blueprintjs/core' ; import FileSaver from 'file-saver' ; import _ from 'lodash' ; import * as React from 'react' ; import { connect } from 'react-redux' ; import SettingsView from 'components/SettingsView' ; import Toaster from 'libs/Toaster' ; import { restoreNotes } from 'store/ducks/notes' ; import { restoreSettings } from 'store/ducks/settings' ; import { ApplicationState } from 'store/reducers' ; import { getNotesBackup } from 'store/selectors/notes' ; import { getSettingsBackup } from 'store/selectors/settings' ; import styled from 'styled' ; import { readTextFile } from 'utils/html' ; /**
 * Section component.
 */ const Section = styled . h3 `
  margin: 20px 0;

  &:first-child {
    margin-top: 0;
  }
` ; /**
 * Notice component.
 */ const Notice = styled . div `
  font-style: italic;
  margin-bottom: 20px;
` ; /**
 * React State.
 */ const initialState = { importing : false } ; type State = Readonly < typeof initialState > ; /**
 * SettingsBackup Component.
 */ class SettingsBackup extends React . Component < Props , State > { public state : State = initialState ; return public render ( ) { const { importing } = this . state ; return ( < SettingsView > < Section > Backup < /Section> < div > < Notice > Credentials are not included . < /Notice> < Button disabled = { importing } icon = "download" intent = { Intent . SUCCESS } text = "Export settings & notes…" onClick = { this . onClickExport } / > < /div> < Section > Restore < /Section> < div > < FileInput disabled = { importing } text = "Choose file..." onInputChange = { this . onClickImport } inputProps = { { accept : '.bkp' , } } /> < /div> < /SettingsView>); } private onClickExport = ( ) => { const { notes , settings } = this . props ; const blob = new Blob ( [ JSON . stringify ( { notes , settings } ) ] , { type : 'text/plain;charset=utf-8;' , } ) ; FileSaver . saveAs ( blob , 'yata.bkp' ) ; } ; private onClickImport = async ( event ) => { if ( _ . isNil ( event . currentTarget . files ) ) { return ; } if ( event . currentTarget . files . length === 0 ) { return ; } this . setState ( ( ) => ( { importing : true } ) ) ; const file = _ . head ( event . currentTarget . files ) as File ; try { const content = await readTextFile ( file ) ; const { notes , settings } = JSON . parse ( content ) ; this . props . restoreSettings ( settings ) ; this . props . restoreNotes ( notes ) ; window . location . reload ( ) ; } catch { Toaster . show ( { icon : 'error' , intent : Intent . DANGER , message : 'Something went wrong! Please try again.' , } ) ; } finally { this . setState ( ( ) => ( { importing : false } ) ) ; } } ; } export default connect < StateProps , DispatchProps , { } , ApplicationState > ( ( state ) => ( { notes : getNotesBackup ( state ) , settings : getSettingsBackup ( state ) , } ) , { restoreNotes , restoreSettings } ) ( SettingsBackup ) ; /**
 * React Props.
 */ interface StateProps { notes : ReturnType < typeof getNotesBackup > ; settings : ReturnType < typeof getSettingsBackup > ; } /**
 * React Props.
 */ interface DispatchProps { restoreNotes : typeof restoreNotes ; restoreSettings : typeof restoreSettings ; } /**
 * React Props.
 */ type Props = StateProps & DispatchProps ;