Skip to content
This repository has been archived by the owner on Jun 16, 2022. It is now read-only.

Commit

Permalink
Merge pull request #1585 from meriadec/fix-1554-reset
Browse files Browse the repository at this point in the history
Ensure sqlite folder is removed after clear cache / hard reset
  • Loading branch information
gre authored Oct 17, 2018
2 parents 4738392 + a9c7467 commit 8926b50
Show file tree
Hide file tree
Showing 6 changed files with 87 additions and 7 deletions.
14 changes: 11 additions & 3 deletions src/components/SettingsPage/CleanButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@
import React, { Fragment, PureComponent } from 'react'
import { connect } from 'react-redux'
import { translate } from 'react-i18next'
import logger from 'logger'
import type { T } from 'types/common'
import { cleanAccountsCache } from 'actions/accounts'
import Button from 'components/base/Button'
import { ConfirmModal } from 'components/base/Modal'
import { softReset } from 'helpers/reset'
import ResetFallbackModal from './ResetFallbackModal'

const mapDispatchToProps = {
cleanAccountsCache,
Expand All @@ -20,32 +22,36 @@ type Props = {

type State = {
opened: boolean,
fallbackOpened: boolean,
isLoading: boolean,
}

class CleanButton extends PureComponent<Props, State> {
state = {
opened: false,
fallbackOpened: false,
isLoading: false,
}

open = () => this.setState({ opened: true })

close = () => this.setState({ opened: false })
closeFallback = () => this.setState({ fallbackOpened: false })

action = async () => {
if (this.state.isLoading) return
try {
this.setState({ isLoading: true })
await softReset({ cleanAccountsCache: this.props.cleanAccountsCache })
} finally {
this.setState({ isLoading: false })
} catch (err) {
logger.error(err)
this.setState({ isLoading: false, fallbackOpened: true })
}
}

render() {
const { t } = this.props
const { opened, isLoading } = this.state
const { opened, isLoading, fallbackOpened } = this.state
return (
<Fragment>
<Button small primary onClick={this.open} event="ClearCacheIntent">
Expand All @@ -63,6 +69,8 @@ class CleanButton extends PureComponent<Props, State> {
subTitle={t('common.areYouSure')}
desc={t('settings.softResetModal.desc')}
/>

<ResetFallbackModal isOpened={fallbackOpened} onClose={this.closeFallback} />
</Fragment>
)
}
Expand Down
13 changes: 11 additions & 2 deletions src/components/SettingsPage/ResetButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import React, { Fragment, PureComponent } from 'react'
import styled from 'styled-components'
import { remote } from 'electron'
import { translate } from 'react-i18next'
import logger from 'logger'
import type { T } from 'types/common'
import { hardReset } from 'helpers/reset'
import Box from 'components/base/Box'
import Button from 'components/base/Button'
import { ConfirmModal } from 'components/base/Modal'
import IconTriangleWarning from 'icons/TriangleWarning'
import ResetFallbackModal from './ResetFallbackModal'

type Props = {
t: T,
Expand All @@ -18,30 +20,35 @@ type Props = {
type State = {
opened: boolean,
pending: boolean,
fallbackOpened: boolean,
}

class ResetButton extends PureComponent<Props, State> {
state = {
opened: false,
pending: false,
fallbackOpened: false,
}

open = () => this.setState({ opened: true })
close = () => this.setState({ opened: false })
closeFallback = () => this.setState({ fallbackOpened: false })

action = async () => {
this.setState({ pending: true })
try {
await hardReset()
remote.getCurrentWindow().webContents.reloadIgnoringCache()
} catch (err) {
this.setState({ pending: false })
logger.error(err)
this.setState({ pending: false, fallbackOpened: true })
}
}

render() {
const { t } = this.props
const { opened, pending } = this.state
const { opened, pending, fallbackOpened } = this.state

return (
<Fragment>
<Button small danger onClick={this.open} event="HardResetIntent">
Expand All @@ -66,6 +73,8 @@ class ResetButton extends PureComponent<Props, State> {
</IconWrapperCircle>
)}
/>

<ResetFallbackModal isOpened={fallbackOpened} onClose={this.closeFallback} />
</Fragment>
)
}
Expand Down
43 changes: 43 additions & 0 deletions src/components/SettingsPage/ResetFallbackModal.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
// @flow

import React, { PureComponent } from 'react'
import { translate } from 'react-i18next'

import { ConfirmModal } from 'components/base/Modal'
import { openUserDataFolderAndQuit } from 'helpers/reset'

type Props = {
t: *,
isOpened: boolean,
onClose: () => *,
}

class ResetFallbackModal extends PureComponent<Props> {
render() {
const { t, isOpened, onClose } = this.props
return (
<ConfirmModal
centered
isOpened={isOpened}
onConfirm={openUserDataFolderAndQuit}
onClose={onClose}
onReject={onClose}
confirmText={'Open folder'}
title={t('settings.resetFallbackModal.title')}
desc={
<div>
<p>{t('settings.resetFallbackModal.part1')}</p>
<p style={{ fontWeight: 'bold' }}>
{t('settings.resetFallbackModal.part2')}
{t('settings.resetFallbackModal.part3')}
{t('settings.resetFallbackModal.part4')}
</p>
<p style={{ marginTop: 20 }}>{t('settings.resetFallbackModal.part5')}</p>
</div>
}
/>
)
}
}

export default translate()(ResetFallbackModal)
1 change: 1 addition & 0 deletions src/config/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,4 @@ export const FeeNotLoaded = createCustomErrorClass('FeeNotLoaded')
// db stuff, no need to translate
export const NoDBPathGiven = createCustomErrorClass('NoDBPathGiven')
export const DBWrongPassword = createCustomErrorClass('DBWrongPassword')
export const DBNotReset = createCustomErrorClass('DBNotReset')
15 changes: 13 additions & 2 deletions src/helpers/reset.js
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
// @flow

import fs from 'fs'
import { shell, remote } from 'electron'
import path from 'path'
import rimraf from 'rimraf'
import resolveUserDataDirectory from 'helpers/resolveUserDataDirectory'
import { disable as disableDBMiddleware } from 'middlewares/db'
import db from 'helpers/db'
import { delay } from 'helpers/promise'
import killInternalProcess from 'commands/killInternalProcess'
import { DBNotReset } from 'config/errors'

async function resetLibcoreDatabase() {
await killInternalProcess.send().toPromise()
const dbpath = path.resolve(resolveUserDataDirectory(), 'sqlite/')
rimraf.sync(dbpath, { glob: false })
if (fs.existsSync(dbpath)) {
throw new DBNotReset()
}
}

function reload() {
Expand All @@ -24,14 +30,19 @@ export async function hardReset() {
disableDBMiddleware()
db.resetAll()
await delay(500)
resetLibcoreDatabase()
await resetLibcoreDatabase()
reload()
}

export async function softReset({ cleanAccountsCache }: *) {
cleanAccountsCache()
await delay(500)
await db.cleanCache()
resetLibcoreDatabase()
await resetLibcoreDatabase()
reload()
}

export async function openUserDataFolderAndQuit() {
shell.openItem(resolveUserDataDirectory())
remote.app.quit()
}
8 changes: 8 additions & 0 deletions static/i18n/en/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -406,6 +406,14 @@
"title": "Clear cache",
"desc": "Clearing the Ledger Live cache forces network resynchronization. Your settings and accounts are not affected. The private keys to access your crypto assets in the blockchain remain secure on your Ledger device and on your Recovery sheet."
},
"resetFallbackModal": {
"title": "User action required",
"part1": "Could not delete cache folder. Please delete the folder manually:",
"part2": "Click the Open folder button, the ",
"part3": "app will close",
"part4": ", and manually delete the \"sqlite\" folder.",
"part5": "Then you can restart the app normally."
},
"removeAccountModal": {
"title": "Remove account",
"desc": "The account will no longer be included in your portfolio. This operation does not affect your assets. Accounts can always be re-added."
Expand Down

0 comments on commit 8926b50

Please sign in to comment.