Skip to content

Commit

Permalink
Auto Backups
Browse files Browse the repository at this point in the history
- Adds the feature to enable auto backup creation
- Lets user change how many days of backups to keep
- Disables number input for how many backups on disabling feature
  • Loading branch information
merlinmarijn authored and xgi committed Jan 11, 2024
1 parent af0505d commit 8f4d828
Show file tree
Hide file tree
Showing 5 changed files with 58 additions and 5 deletions.
8 changes: 7 additions & 1 deletion src/components/general/DashboardPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,10 @@ import {
seriesListState,
} from '../../state/libraryStates';
import library from '../../services/library';
import { chapterLanguagesState, refreshOnStartState } from '../../state/settingStates';
import { autoBackupCountState, autoBackupState, chapterLanguagesState, refreshOnStartState } from '../../state/settingStates';
import DashboardSidebarLink from './DashboardSidebarLink';
import { downloadCover } from '../../util/download';
import { createAutoBackup } from '../../util/backup';

import ToggleThemeSwitch from './ToggleThemeSwitch';

Expand All @@ -50,12 +51,17 @@ const DashboardPage: React.FC<Props> = (props: Props) => {
const [, setReloadingSeriesList] = useRecoilState(reloadingSeriesListState);
const [completedStartReload, setCompletedStartReload] = useRecoilState(completedStartReloadState);
const refreshOnStart = useRecoilValue(refreshOnStartState);
const autoBackup = useRecoilValue(autoBackupState);
const autoBackupCount = useRecoilValue(autoBackupCountState);
const chapterLanguages = useRecoilValue(chapterLanguagesState);
const [importQueue, setImportQueue] = useRecoilState(importQueueState);
const [importing, setImporting] = useRecoilState(importingState);
const categoryList = useRecoilValue(categoryListState);

useEffect(() => {
if(autoBackup){
createAutoBackup(autoBackupCount);
}
if (refreshOnStart && !completedStartReload && activeSeriesList.length > 0) {
setCompletedStartReload(true);
reloadSeriesList(
Expand Down
27 changes: 23 additions & 4 deletions src/components/settings/GeneralSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,15 @@ import React from 'react';
import { Language, LanguageKey, Languages } from 'houdoku-extension-lib';
import { ipcRenderer } from 'electron';
import { useRecoilState } from 'recoil';
import { Button, Checkbox, Flex, Group, Input, MultiSelect, Stack, Text } from '@mantine/core';
import { Button, Checkbox, Flex, Group, Input, MultiSelect, NumberInput, Stack, Text, Tooltip } from '@mantine/core';
import { IconArrowBack } from '@tabler/icons';
import { GeneralSetting } from '../../models/types';
import ipcChannels from '../../constants/ipcChannels.json';
import { createBackup, restoreBackup } from '../../util/backup';
import {
autoCheckForExtensionUpdatesState,
autoBackupState,
autoBackupCountState,
autoCheckForUpdatesState,
chapterLanguagesState,
confirmRemoveSeriesState,
Expand All @@ -30,9 +32,9 @@ const GeneralSettings: React.FC<Props> = () => {
const [chapterLanguages, setChapterLanguages] = useRecoilState(chapterLanguagesState);
const [refreshOnStart, setRefreshOnStart] = useRecoilState(refreshOnStartState);
const [autoCheckForUpdates, setAutoCheckForUpdates] = useRecoilState(autoCheckForUpdatesState);
const [autoCheckForExtensionUpdates, setAutoCheckForExtensionUpdates] = useRecoilState(
autoCheckForExtensionUpdatesState
);
const [autoCheckForExtensionUpdates, setAutoCheckForExtensionUpdates] = useRecoilState(autoCheckForExtensionUpdatesState);
const [autoBackup, setAutoBackup] = useRecoilState(autoBackupState);
const [autoBackupCount, setAutoBackupCount] = useRecoilState(autoBackupCountState);
const [confirmRemoveSeries, setConfirmRemoveSeries] = useRecoilState(confirmRemoveSeriesState);
const [libraryCropCovers, setLibraryCropCovers] = useRecoilState(libraryCropCoversState);
const [customDownloadsDir, setCustomDownloadsDir] = useRecoilState(customDownloadsDirState);
Expand Down Expand Up @@ -61,6 +63,12 @@ const GeneralSettings: React.FC<Props> = () => {
case GeneralSetting.CustomDownloadsDir:
setCustomDownloadsDir(value);
break;
case GeneralSetting.autoBackup:
setAutoBackup(value);
break;
case GeneralSetting.autoBackupCount:
setAutoBackupCount(value);
break;
default:
break;
}
Expand Down Expand Up @@ -185,6 +193,17 @@ const GeneralSettings: React.FC<Props> = () => {
>
Restore Backup
</Button>
<Tooltip label={`Makes backup every day (stores ${autoBackupCount} backups)`}>
<Checkbox
label="Auto backup"
size="md"
checked={autoBackup}
onChange={(e) => updateGeneralSetting(GeneralSetting.autoBackup, e.target.checked)}
></Checkbox>
</Tooltip>
<NumberInput disabled={!autoBackup} min={1} value={autoBackupCount} onChange={(value) =>
updateGeneralSetting(GeneralSetting.autoBackupCount, value)
}></NumberInput>
</Group>
</Flex>
</Stack>
Expand Down
6 changes: 6 additions & 0 deletions src/models/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ export enum GeneralSetting {
RefreshOnStart = 'RefreshOnStart',
AutoCheckForUpdates = 'AutoCheckForUpdates',
AutoCheckForExtensionUpdates = 'AutoCheckForExtensionUpdates',
autoBackup = "autoBackup",
autoBackupCount = "autoBackupCount",
ConfirmRemoveSeries = 'ConfirmRemoveSeries',
CustomDownloadsDir = 'CustomDownloadsDir',
LibraryColumns = 'LibraryColumns',
Expand Down Expand Up @@ -190,6 +192,8 @@ export const SettingTypes = {
[GeneralSetting.RefreshOnStart]: SettingType.BOOLEAN,
[GeneralSetting.AutoCheckForUpdates]: SettingType.BOOLEAN,
[GeneralSetting.AutoCheckForExtensionUpdates]: SettingType.BOOLEAN,
[GeneralSetting.autoBackup]: SettingType.BOOLEAN,
[GeneralSetting.autoBackupCount]: SettingType.NUMBER,
[GeneralSetting.ConfirmRemoveSeries]: SettingType.BOOLEAN,
[GeneralSetting.CustomDownloadsDir]: SettingType.STRING,
[GeneralSetting.LibraryColumns]: SettingType.NUMBER,
Expand Down Expand Up @@ -242,6 +246,8 @@ export const DefaultSettings = {
[GeneralSetting.RefreshOnStart]: true,
[GeneralSetting.AutoCheckForUpdates]: true,
[GeneralSetting.AutoCheckForExtensionUpdates]: true,
[GeneralSetting.autoBackup]: false,
[GeneralSetting.autoBackupCount]: 10,
[GeneralSetting.ConfirmRemoveSeries]: true,
[GeneralSetting.CustomDownloadsDir]: '',
[GeneralSetting.LibraryColumns]: 4,
Expand Down
2 changes: 2 additions & 0 deletions src/state/settingStates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,8 @@ export const chapterLanguagesState = atomFromSetting<LanguageKey[]>(GeneralSetti
export const autoCheckForUpdatesState = atomFromSetting<boolean>(GeneralSetting.AutoCheckForUpdates);
export const refreshOnStartState = atomFromSetting<boolean>(GeneralSetting.RefreshOnStart);
export const autoCheckForExtensionUpdatesState = atomFromSetting<boolean>(GeneralSetting.AutoCheckForExtensionUpdates);
export const autoBackupState = atomFromSetting<boolean>(GeneralSetting.autoBackup);
export const autoBackupCountState = atomFromSetting<number>(GeneralSetting.autoBackupCount);
export const confirmRemoveSeriesState = atomFromSetting<boolean>(GeneralSetting.ConfirmRemoveSeries);
export const customDownloadsDirState = atomFromSetting<string>(GeneralSetting.CustomDownloadsDir);
export const libraryColumnsState = atomFromSetting<number>(GeneralSetting.LibraryColumns);
Expand Down
20 changes: 20 additions & 0 deletions src/util/backup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@ import { Chapter, Series } from 'houdoku-extension-lib';
import storeKeys from '../constants/storeKeys.json';
import { updateSeries } from '../features/library/utils';
import library from '../services/library';
import fs from 'fs-extra';
import path from 'path';

export const createBackup = async () => {
const blob = new Blob([JSON.stringify(localStorage)], {
Expand All @@ -17,6 +19,24 @@ export const createBackup = async () => {
document.body.removeChild(link);
};

export const createAutoBackup = async (Count = 1) => {
if (!fs.existsSync("backups")) {
fs.mkdir("backups");
}
var fileName = `houdoku_backup_${new Date().toJSON().slice(0, 10)}.json`
if (!fs.existsSync(`backups/${fileName}`)) {
var jsondata = JSON.stringify(localStorage);
jsondata = JSON.parse(jsondata);
await fs.writeJson(`backups/${fileName}`, jsondata);
}
fs.readdir("backups", function (err, files) {
if (err) { return console.log('Unable to scan directory: ' + err); }
if (files.length > Count) {
fs.unlinkSync(path.join('backups', files[0]))
}
})
}

export const restoreBackup = (backupFileContent: string) => {
const data: { [key: string]: string } = JSON.parse(backupFileContent);

Expand Down

0 comments on commit 8f4d828

Please sign in to comment.