Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(desktop): add database reset page to fix blank screen from corrupted file #1627

Merged
merged 1 commit into from
Apr 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 51 additions & 23 deletions src/background.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import { app, protocol, BrowserWindow, ipcMain, shell, Menu } from 'electron'
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib'
import installExtension, { VUEJS_DEVTOOLS } from 'electron-devtools-installer'
import { quitAndRenameLogger } from './utils/logger'
import rebuildDatabase from './utils/rebuildDatabase'
import { createUpdateWindow, autoDownload } from './main/updateDownloader'
import { getCurrentLang } from './main/updateChecker'
import getMenuTemplate from './main/getMenuTemplate'
Expand All @@ -14,6 +15,7 @@ import { onSystemThemeChanged } from './main/systemTheme'
import useConnection, { initOptionModel } from '@/database/useConnection'
import useServices from '@/database/useServices'
import { dialog } from 'electron'
import ORMConfig from './database/database.config'
import version from '@/version'

declare const __static: string
Expand Down Expand Up @@ -92,6 +94,20 @@ function handleIpcMessages() {
ipcMain.on('insertCodeToEditor', (event, ...args) => {
event.sender.send('insertCodeToEditor', ...args)
})
ipcMain.on('rebuildDatabase', (event) => {
try {
rebuildDatabase(ORMConfig.database as string)
DM1-1 marked this conversation as resolved.
Show resolved Hide resolved
app.relaunch()
app.exit()
} catch (error) {
dialog.showMessageBox({
type: 'error',
title: 'Rebuild Database Error',
message: 'An error occurred while rebuilding the database.',
detail: error.message
})
}
})
}

// handle event when APP quit
Expand All @@ -106,30 +122,41 @@ function beforeAppQuit() {

async function createWindow() {
// Init tables and connect to local database.
await ConnectionInit({ doMigrations: true } as initOptionModel)
const { settingService } = useServices()
await settingService.set()
const setting = await settingService.get()
if (setting) {
theme = setting.currentTheme
autoCheckUpdate = setting.autoCheck
syncOsTheme = setting.syncOsTheme
windowSize.height = setting.height
windowSize.width = setting.width
try {
await ConnectionInit({ doMigrations: true } as initOptionModel)
const { settingService } = useServices()
await settingService.set()
const setting = await settingService.get()
if (setting) {
theme = setting.currentTheme
autoCheckUpdate = setting.autoCheck
syncOsTheme = setting.syncOsTheme
windowSize.height = setting.height
windowSize.width = setting.width
//@ts-ignore
global.sharedData = {
currentTheme: setting.currentTheme,
currentLang: setting.currentLang,
autoCheck: setting.autoCheck,
autoResub: setting.autoResub,
maxReconnectTimes: setting.maxReconnectTimes,
syncOsTheme: setting.syncOsTheme,
multiTopics: setting.multiTopics,
jsonHighlight: setting.jsonHighlight,
enableCopilot: setting.enableCopilot,
openAIAPIKey: setting.openAIAPIKey,
model: setting.model,
logLevel: setting.logLevel,
}
}
} catch (error) {
console.error('ConnectionInit error:', error)
//@ts-ignore
global.sharedData = {
currentTheme: setting.currentTheme,
currentLang: setting.currentLang,
autoCheck: setting.autoCheck,
autoResub: setting.autoResub,
maxReconnectTimes: setting.maxReconnectTimes,
syncOsTheme: setting.syncOsTheme,
multiTopics: setting.multiTopics,
jsonHighlight: setting.jsonHighlight,
enableCopilot: setting.enableCopilot,
openAIAPIKey: setting.openAIAPIKey,
model: setting.model,
logLevel: setting.logLevel,
connectDatabaseFailMessage: error.message,
currentTheme: 'light',
currentLang: 'en',
syncOsTheme: false,
}
}
// Create the browser window.
Expand All @@ -156,7 +183,8 @@ async function createWindow() {
}
})
// Menu Manger
const templateMenu = getMenuTemplate(win, setting?.currentLang)
// @ts-ignore
const templateMenu = getMenuTemplate(win, global.sharedData.currentLang)
menu = Menu.buildFromTemplate(templateMenu)
Menu.setApplicationMenu(menu)

Expand Down
87 changes: 87 additions & 0 deletions src/components/DatabaseError.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
<template>
<div class="connect-database-error-page">
<div class="page-content">
<p class="info">A corruption has been detected in the database file, preventing the software from launching properly. To fix this, please click 'Rebuild Database'.</p>
<p class="error">Error - {{ connectDatabaseFailMessage }}</p>
</div>
<el-button class="rebuild-database-btn" type="primary" @click="confirmRebuild">
Rebuild Database
</el-button>
</div>
</template>


<script lang="ts">
import { Component, Vue } from 'vue-property-decorator'
import { Getter } from 'vuex-class'
import { ipcRenderer } from 'electron'

@Component
export default class DatabaseError extends Vue {
@Getter('connectDatabaseFailMessage') private connectDatabaseFailMessage!: string

private rebuildDatabase() {
ipcRenderer.send('rebuildDatabase')
}

private confirmRebuild() {
this.$confirm(
'Proceed with database rebuild now? All data will be lost and cannot be undone',
{
title:'Database Rebuild Confirmation',
showClose: false,
closeOnClickModal:false,
confirmButtonText: 'Confirm',
cancelButtonText: 'Cancel',
type: 'warning',
beforeClose: (action, instance, done) => {
if (action === 'confirm') {
instance.confirmButtonLoading = true
instance.confirmButtonText = 'Loading...'
}
done()
}
}
)
.then(() => {
try {
this.rebuildDatabase()
this.$log.info('Database rebuild completed. The application will restart')
} catch (error) {
this.$log.error(`Failed to rebuilding database: ${error}`)
}
})
}

private mounted() {
this.$log.error(`Database connect error - ${this.connectDatabaseFailMessage}`)
}
}
</script>

<style lang="scss">
.connect-database-error-page {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
height: 100vh;
.page-content {
text-align: center;
width: 60%;
font-size: 20px;
margin-bottom: 24px;
.info {
margin-bottom: 14px;
}
.error {
color: var(--color-minor-red);
}
}
.rebuild-database-btn {
padding: 10px 16px;
border: none;
border-radius: 8px;
}
}
</style>
1 change: 1 addition & 0 deletions src/store/getter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ const getters = {
isPrismButtonAdded: (state: State) => state.app.isPrismButtonAdded,
logLevel: (state: State) => state.app.logLevel,
showConnectionList: (state: State) => state.app.showConnectionList,
connectDatabaseFailMessage: (state: State) => state.app.connectDatabaseFailMessage,
}

export default getters
1 change: 1 addition & 0 deletions src/store/modules/app.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ const app = {
isPrismButtonAdded: false,
logLevel: settingData.logLevel || 'info',
showConnectionList: getShowConnectionList(),
connectDatabaseFailMessage: settingData.connectDatabaseFailMessage || '',
},
mutations: {
[TOGGLE_THEME](state: App, currentTheme: Theme) {
Expand Down
1 change: 1 addition & 0 deletions src/types/global.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ declare global {
isPrismButtonAdded: boolean
logLevel: LogLevel
showConnectionList: boolean
connectDatabaseFailMessage: string
}

interface State {
Expand Down
13 changes: 13 additions & 0 deletions src/utils/rebuildDatabase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import fs from 'fs'

const rebuildDatabase = (filePath: string) => {
fs.writeFile(filePath, '', (error) => {
if (error) {
console.error('Error rebuilding database:', error)
} else {
console.log('Database rebuilt successfully.')
}
})
}

export default rebuildDatabase
6 changes: 5 additions & 1 deletion src/views/Home.vue
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<template>
<div class="home-view">
<DatabaseError v-if="connectDatabaseFailMessage" />
<div class="home-view" v-else>
<Leftbar />
<RouterView />
<Ipc @setTheme="setTheme" @setLang="setLang" />
Expand All @@ -13,18 +14,21 @@ import { Getter, Action } from 'vuex-class'
import { remote } from 'electron'
import Ipc from '@/components/Ipc.vue'
import Leftbar from '@/components/Leftbar.vue'
import DatabaseError from '@/components/DatabaseError.vue'

@Component({
components: {
Ipc,
Leftbar,
Update: () => import('@/views/update/index.vue'),
DatabaseError,
},
})
export default class Home extends Vue {
@Getter('currentTheme') private getterTheme!: Theme
@Getter('currentLang') private getterLang!: Language
@Getter('syncOsTheme') private syncOsTheme!: boolean
@Getter('connectDatabaseFailMessage') private connectDatabaseFailMessage!: string
@Action('TOGGLE_THEME') private actionTheme!: (payload: { currentTheme: string }) => void
@Action('TOGGLE_LANG') private actionLang!: (payload: { currentLang: string }) => void
private updateActive: boolean = false
Expand Down
Loading