mirror of
https://github.com/koodo-reader/koodo-reader.git
synced 2026-06-17 04:11:40 -04:00
fix bug
Former-commit-id: ffb6df3902b5f945c4572f11c5dce04a3b9bc4b1
This commit is contained in:
@@ -218,7 +218,7 @@
|
||||
"Line Height": "行间距",
|
||||
"Tips": "提示",
|
||||
"How sync works": "同步是如何实现的?",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "同步功能需要配合第三方同步盘实现,在不同电脑上把数据存储位置修改为同一个同步文件夹,手动点击同步按钮后,Koodo会把同步文件夹中的数据更新到软件中,从而实现同步。",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "同步功能需要配合第三方同步盘实现,在不同电脑上把数据存储位置修改为同一个网盘文件夹,点击同步按钮后,Koodo会自动进行数据的双向同步。目前该功能还处在测试阶段,请谨慎使用。",
|
||||
"Please choose an empty folder": "请选择空文件夹",
|
||||
"Data change detected, whether to update?": "检测到数据变化,是否更新",
|
||||
"Empty Library": "图书库为空",
|
||||
|
||||
@@ -231,7 +231,7 @@
|
||||
"Tips": "Tips",
|
||||
"Brightness": "Brightness",
|
||||
"How sync works": "How sync works",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp. This function is still in beta, use with caution.",
|
||||
"Line Height": "Line Height",
|
||||
"Please choose an empty folder": "Please choose an empty folder",
|
||||
"Data change detected, whether to update?": "Data change detected, whether to update?",
|
||||
@@ -294,4 +294,4 @@
|
||||
"Our Website": "Our Website",
|
||||
"What's New": "What's New",
|
||||
"What's been fixed": "What's been fixed"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@
|
||||
"Invert color": "Invert color",
|
||||
"Auto Update relys on Github Release for package hosting, if your internet doesn't have stable connection to Github, we highly recommand you to turn off this option": "Auto Update relys on Github Release for package hosting, if your internet doesn't have stable connection to Github, we highly recommand you to turn off this option",
|
||||
"How sync works": "How sync works",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp. This function is still in beta, use with caution.",
|
||||
"Purple": "Purple",
|
||||
"Please choose an empty folder": "Please choose an empty folder",
|
||||
"Data change detected, whether to update?": "Data change detected, whether to update?",
|
||||
@@ -294,4 +294,4 @@
|
||||
"What's been fixed": "What's been fixed",
|
||||
"Voice": "Voice",
|
||||
"Speed": "Speed"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -281,7 +281,7 @@
|
||||
"System Font": "系統字體",
|
||||
"Tips": "提示",
|
||||
"How sync works": "同步是如何實現的?",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "同步功能需要配合第三方同步盤實現,在不同電腦上把數據存儲位置修改為同一個同步文件夾,手動點擊同步按鈕後,Koodo會把同步文件夾中的數據更新到軟件中,從而實現同步。",
|
||||
"You need to manually change the storage location to the same sync folder on different computers. When you click the sync button, Koodo Reader will automatically upload or download the data from this folder according the timestamp.": "同步功能需要配合第三方同步盤實現,在不同電腦上把數據存儲位置修改為同一個網盤文件夾,點擊同步按鈕後,Koodo會自動進行數據的雙向同步。目前該功能還處在測試階段,請謹慎使用。",
|
||||
"Please choose an empty folder": "請選擇空文件夾",
|
||||
"Data change detected, whether to update?": "檢測到數據變化,是否更新",
|
||||
"File size": "文件大小",
|
||||
@@ -292,4 +292,4 @@
|
||||
"Hide navigation button": "不显示翻页按钮",
|
||||
"More": "显示笔记出处",
|
||||
"Sync data from storage": "从存储位置同步数据"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
import React from "react";
|
||||
import "./backupDialog.css";
|
||||
import { driveList } from "../../../constants/driveList";
|
||||
import BackupUtil from "../../../utils/syncUtils/backupUtil";
|
||||
import RestoreUtil from "../../../utils/syncUtils/restoreUtil";
|
||||
import { backup } from "../../../utils/syncUtils/backupUtil";
|
||||
import { restore } from "../../../utils/syncUtils/restoreUtil";
|
||||
import { Trans } from "react-i18next";
|
||||
import DropboxUtil from "../../../utils/syncUtils/dropbox";
|
||||
import WebdavUtil from "../../../utils/syncUtils/webdav";
|
||||
@@ -12,7 +12,7 @@ import TokenDialog from "../tokenDialog";
|
||||
import OtherUtil from "../../../utils/otherUtil";
|
||||
import Lottie from "react-lottie";
|
||||
import animationSuccess from "../../../assets/lotties/success.json";
|
||||
|
||||
import FileSaver from "file-saver";
|
||||
const successOptions = {
|
||||
loop: false,
|
||||
autoplay: true,
|
||||
@@ -42,26 +42,40 @@ class BackupDialog extends React.Component<
|
||||
this.props.handleLoadingDialog(false);
|
||||
this.showMessage("Sync Successfully");
|
||||
};
|
||||
handleRestoreToLocal = (event: any) => {
|
||||
handleRestoreToLocal = async (event: any) => {
|
||||
event.preventDefault();
|
||||
RestoreUtil.restore(event.target.files[0], this.handleFinish);
|
||||
let result = await restore(event.target.files[0]);
|
||||
if (result) {
|
||||
this.handleFinish();
|
||||
}
|
||||
};
|
||||
showMessage = (message: string) => {
|
||||
this.props.handleMessage(message);
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
handleDrive = (index: number) => {
|
||||
this.setState({ currentDrive: index }, () => {
|
||||
let year = new Date().getFullYear(),
|
||||
month = new Date().getMonth() + 1,
|
||||
day = new Date().getDate();
|
||||
this.setState({ currentDrive: index }, async () => {
|
||||
switch (index) {
|
||||
case 0:
|
||||
BackupUtil.backup(
|
||||
let blob: Blob | boolean = await backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
this.handleFinish,
|
||||
0,
|
||||
this.showMessage
|
||||
false
|
||||
);
|
||||
if (!blob) {
|
||||
this.showMessage("Backup Failed");
|
||||
}
|
||||
FileSaver.saveAs(
|
||||
blob as Blob,
|
||||
`${year}-${month <= 9 ? "0" + month : month}-${
|
||||
day <= 9 ? "0" + day : day
|
||||
}.zip`
|
||||
);
|
||||
this.handleFinish();
|
||||
break;
|
||||
case 1:
|
||||
if (!OtherUtil.getReaderConfig("dropbox_token")) {
|
||||
@@ -73,18 +87,32 @@ class BackupDialog extends React.Component<
|
||||
this.showMessage("Uploading");
|
||||
this.props.handleLoadingDialog(true);
|
||||
|
||||
BackupUtil.backup(
|
||||
let blob: Blob | boolean = await backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
this.handleFinish,
|
||||
1,
|
||||
this.showMessage
|
||||
false
|
||||
);
|
||||
if (!blob) {
|
||||
this.showMessage("Backup Failed");
|
||||
this.props.handleLoadingDialog(false);
|
||||
}
|
||||
let result = await DropboxUtil.UploadFile(blob);
|
||||
if (result) {
|
||||
this.handleFinish();
|
||||
} else {
|
||||
this.showMessage("Upload failed, check your connection");
|
||||
}
|
||||
} else {
|
||||
this.props.handleLoadingDialog(true);
|
||||
this.showMessage("Downloading");
|
||||
DropboxUtil.DownloadFile(this.handleFinish, this.showMessage);
|
||||
let result = await DropboxUtil.DownloadFile();
|
||||
if (result) {
|
||||
this.handleFinish();
|
||||
} else {
|
||||
this.showMessage("Download failed,network problem or no backup");
|
||||
this.props.handleLoadingDialog(false);
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -101,19 +129,39 @@ class BackupDialog extends React.Component<
|
||||
this.showMessage("Uploading");
|
||||
this.props.handleLoadingDialog(true);
|
||||
|
||||
BackupUtil.backup(
|
||||
let blob: any = await backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
this.handleFinish,
|
||||
3,
|
||||
this.showMessage
|
||||
false
|
||||
);
|
||||
if (!blob) {
|
||||
this.showMessage("Backup Failed");
|
||||
this.props.handleLoadingDialog(false);
|
||||
}
|
||||
|
||||
let result = await WebdavUtil.UploadFile(
|
||||
new File([blob], "data.zip", {
|
||||
lastModified: new Date().getTime(),
|
||||
type: blob.type,
|
||||
})
|
||||
);
|
||||
if (result) {
|
||||
this.handleFinish();
|
||||
} else {
|
||||
this.showMessage("Upload failed, check your connection");
|
||||
this.props.handleLoadingDialog(false);
|
||||
}
|
||||
} else {
|
||||
this.showMessage("Downloading");
|
||||
this.props.handleLoadingDialog(true);
|
||||
|
||||
WebdavUtil.DownloadFile(this.handleFinish, this.showMessage);
|
||||
let result = await WebdavUtil.DownloadFile();
|
||||
if (!result) {
|
||||
this.showMessage("Download failed,network problem or no backup");
|
||||
} else {
|
||||
this.handleFinish();
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -6,12 +6,11 @@ import { Trans } from "react-i18next";
|
||||
import i18n from "../../../i18n";
|
||||
import { version } from "../../../../package.json";
|
||||
import OtherUtil from "../../../utils/otherUtil";
|
||||
import SyncUtil from "../../../utils/syncUtils/common";
|
||||
import { changePath } from "../../../utils/syncUtils/common";
|
||||
import { isElectron } from "react-device-detect";
|
||||
import { dropdownList } from "../../../constants/dropdownList";
|
||||
import { Tooltip } from "react-tippy";
|
||||
import RestoreUtil from "../../../utils/syncUtils/restoreUtil";
|
||||
import BackupUtil from "../../../utils/syncUtils/backupUtil";
|
||||
import { restore } from "../../../utils/syncUtils/restoreUtil";
|
||||
import {
|
||||
settingList,
|
||||
langList,
|
||||
@@ -111,23 +110,14 @@ class SettingDialog extends React.Component<
|
||||
type: blobTemp.type,
|
||||
});
|
||||
|
||||
RestoreUtil.restore(
|
||||
fileTemp,
|
||||
() => {
|
||||
BackupUtil.backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
() => {
|
||||
this.props.handleMessage("Change Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
},
|
||||
5,
|
||||
() => {}
|
||||
);
|
||||
},
|
||||
true
|
||||
);
|
||||
let result = await restore(fileTemp, true);
|
||||
if (result) {
|
||||
this.props.handleMessage("Change Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
} else {
|
||||
this.props.handleMessage("Change Failed");
|
||||
this.props.handleMessageBox(true);
|
||||
}
|
||||
};
|
||||
handleChangeLocation = async () => {
|
||||
const { dialog } = window.require("electron").remote;
|
||||
@@ -138,15 +128,21 @@ class SettingDialog extends React.Component<
|
||||
if (!path.filePaths[0]) {
|
||||
return;
|
||||
}
|
||||
SyncUtil.changeLocation(
|
||||
let result = await changePath(
|
||||
localStorage.getItem("storageLocation")
|
||||
? localStorage.getItem("storageLocation")
|
||||
: ipcRenderer.sendSync("storage-location", "ping"),
|
||||
path.filePaths[0],
|
||||
this.props.handleMessage,
|
||||
this.props.handleMessageBox,
|
||||
this.syncFromLocation
|
||||
path.filePaths[0]
|
||||
);
|
||||
if (result === 1) {
|
||||
this.syncFromLocation();
|
||||
} else if (result === 2) {
|
||||
this.props.handleMessage("Change Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
} else {
|
||||
this.props.handleMessage("Change Failed");
|
||||
this.props.handleMessageBox(true);
|
||||
}
|
||||
localStorage.setItem("storageLocation", path.filePaths[0]);
|
||||
document.getElementsByClassName(
|
||||
"setting-dialog-location-title"
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
position: relative;
|
||||
top: 10px;
|
||||
margin-left: 5px;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
.cover-footer {
|
||||
width: 100%;
|
||||
|
||||
@@ -174,7 +174,8 @@ class ImportLocal extends React.Component<ImportLocalProps, ImportLocalState> {
|
||||
const file_content = (event.target as any).result;
|
||||
let mobiFile = new MobiParser(file_content);
|
||||
let content: any = await mobiFile.render(isElectron);
|
||||
if (typeof content === "object") {
|
||||
//包含太多图片或者文件大于5m就不转换
|
||||
if (typeof content === "object" || file.size / 1024 / 1024 > 10) {
|
||||
result = BookUtil.generateBook(
|
||||
bookName,
|
||||
extension,
|
||||
|
||||
@@ -110,11 +110,9 @@ class TextToSpeech extends React.Component<
|
||||
};
|
||||
|
||||
msg.onend = (event) => {
|
||||
console.log(event, "event", new Date().getTime());
|
||||
if (!(this.state.isAudioOn && this.props.isReading)) {
|
||||
return;
|
||||
}
|
||||
console.log(event, "event1", new Date().getTime());
|
||||
this.props.currentEpub.rendition.next().then(() => {
|
||||
this.handleAudio();
|
||||
});
|
||||
|
||||
@@ -7,10 +7,12 @@ import { Trans } from "react-i18next";
|
||||
import { HeaderProps, HeaderState } from "./interface";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
import UpdateInfo from "../../components/dialogs/updateInfo";
|
||||
import RestoreUtil from "../../utils/syncUtils/restoreUtil";
|
||||
import BackupUtil from "../../utils/syncUtils/backupUtil";
|
||||
import { restore } from "../../utils/syncUtils/restoreUtil";
|
||||
import { backup } from "../../utils/syncUtils/backupUtil";
|
||||
import { Tooltip } from "react-tippy";
|
||||
import { isElectron } from "react-device-detect";
|
||||
import { syncData } from "../../utils/syncUtils/common";
|
||||
|
||||
class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
constructor(props: HeaderProps) {
|
||||
super(props);
|
||||
@@ -114,40 +116,40 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
lastModified: new Date().getTime(),
|
||||
type: blobTemp.type,
|
||||
});
|
||||
RestoreUtil.restore(
|
||||
fileTemp,
|
||||
() => {
|
||||
this.setState({ isdataChange: false });
|
||||
//Check for data update
|
||||
let storageLocation = localStorage.getItem("storageLocation")
|
||||
? localStorage.getItem("storageLocation")
|
||||
: window
|
||||
.require("electron")
|
||||
.ipcRenderer.sendSync("storage-location", "ping");
|
||||
let sourcePath = path.join(
|
||||
storageLocation,
|
||||
"config",
|
||||
"readerConfig.json"
|
||||
);
|
||||
let result = await restore(fileTemp, true);
|
||||
if (result) {
|
||||
this.setState({ isdataChange: false });
|
||||
//Check for data update
|
||||
let storageLocation = localStorage.getItem("storageLocation")
|
||||
? localStorage.getItem("storageLocation")
|
||||
: window
|
||||
.require("electron")
|
||||
.ipcRenderer.sendSync("storage-location", "ping");
|
||||
let sourcePath = path.join(
|
||||
storageLocation,
|
||||
"config",
|
||||
"readerConfig.json"
|
||||
);
|
||||
|
||||
fs.readFile(sourcePath, "utf8", (err, data) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
const readerConfig = JSON.parse(data);
|
||||
if (
|
||||
localStorage.getItem("lastSyncTime") &&
|
||||
readerConfig.lastSyncTime
|
||||
) {
|
||||
localStorage.setItem("lastSyncTime", readerConfig.lastSyncTime);
|
||||
}
|
||||
});
|
||||
},
|
||||
true
|
||||
);
|
||||
fs.readFile(sourcePath, "utf8", (err, data) => {
|
||||
if (err) {
|
||||
console.error(err);
|
||||
return;
|
||||
}
|
||||
const readerConfig = JSON.parse(data);
|
||||
if (localStorage.getItem("lastSyncTime") && readerConfig.lastSyncTime) {
|
||||
localStorage.setItem("lastSyncTime", readerConfig.lastSyncTime);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!result) {
|
||||
this.props.handleMessage("Sync Failed");
|
||||
} else {
|
||||
this.props.handleMessage("Sync Successfully");
|
||||
}
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
syncToLocation = () => {
|
||||
handleSync = () => {
|
||||
if (OtherUtil.getReaderConfig("isFirst") !== "no") {
|
||||
this.props.handleTipDialog(true);
|
||||
this.props.handleTip(
|
||||
@@ -164,21 +166,9 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
.require("electron")
|
||||
.ipcRenderer.sendSync("storage-location", "ping");
|
||||
let sourcePath = path.join(storageLocation, "config", "readerConfig.json");
|
||||
fs.readFile(sourcePath, "utf8", (err, data) => {
|
||||
if (err) {
|
||||
BackupUtil.backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
() => {
|
||||
this.props.handleMessage("Sync Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
},
|
||||
5,
|
||||
() => {}
|
||||
);
|
||||
console.log(err);
|
||||
return;
|
||||
fs.readFile(sourcePath, "utf8", async (err, data) => {
|
||||
if (err || !data) {
|
||||
this.syncToLocation();
|
||||
}
|
||||
const readerConfig = JSON.parse(data);
|
||||
|
||||
@@ -191,20 +181,28 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
this.syncFromLocation();
|
||||
} else {
|
||||
//否则就把Koodo中数据同步到同步文件夹
|
||||
BackupUtil.backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
() => {
|
||||
this.props.handleMessage("Sync Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
},
|
||||
5,
|
||||
() => {}
|
||||
);
|
||||
this.syncToLocation();
|
||||
}
|
||||
});
|
||||
};
|
||||
syncToLocation = async () => {
|
||||
let timestamp = new Date().getTime().toString();
|
||||
OtherUtil.setReaderConfig("lastSyncTime", timestamp);
|
||||
localStorage.setItem("lastSyncTime", timestamp);
|
||||
let result = await backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
true
|
||||
);
|
||||
if (!result) {
|
||||
this.props.handleMessage("Sync Failed");
|
||||
} else {
|
||||
syncData(result as Blob, this.props.books, true);
|
||||
this.props.handleMessage("Sync Successfully");
|
||||
}
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
@@ -260,7 +258,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
className="setting-icon-container"
|
||||
onClick={() => {
|
||||
// this.syncFromLocation();
|
||||
this.syncToLocation();
|
||||
this.handleSync();
|
||||
}}
|
||||
style={{ left: "635px" }}
|
||||
>
|
||||
|
||||
@@ -17,7 +17,7 @@ import DeletePopup from "../../../components/dialogs/deletePopup";
|
||||
import Empty from "../../emptyPage";
|
||||
import { Redirect, withRouter } from "react-router-dom";
|
||||
import ViewMode from "../../../components/viewMode";
|
||||
import BackUtil from "../../../utils/syncUtils/backupUtil";
|
||||
import { backup } from "../../../utils/syncUtils/backupUtil";
|
||||
import { isElectron } from "react-device-detect";
|
||||
|
||||
class BookList extends React.Component<BookListProps, BookListState> {
|
||||
@@ -126,7 +126,6 @@ class BookList extends React.Component<BookListProps, BookListState> {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return books.map((item: BookModel, index: number) => {
|
||||
return this.props.viewMode === "list" ? (
|
||||
<BookListItem
|
||||
@@ -200,13 +199,11 @@ class BookList extends React.Component<BookListProps, BookListState> {
|
||||
//兼容之前的版本
|
||||
localforage.getItem(this.props.books[0].key).then((result) => {
|
||||
if (result) {
|
||||
BackUtil.backup(
|
||||
backup(
|
||||
this.props.books,
|
||||
this.props.notes,
|
||||
this.props.bookmarks,
|
||||
() => {},
|
||||
4,
|
||||
() => {}
|
||||
false
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -126,6 +126,7 @@ class Sidebar extends React.Component<SidebarProps, SidebarState> {
|
||||
)}
|
||||
position="top"
|
||||
trigger="mouseenter"
|
||||
distance={25}
|
||||
>
|
||||
<span className="icon-menu sidebar-list"></span>
|
||||
</Tooltip>
|
||||
|
||||
@@ -1,125 +1,33 @@
|
||||
import FileSaver from "file-saver";
|
||||
import BookModel from "../../model/Book";
|
||||
import NoteModel from "../../model/Note";
|
||||
import BookmarkModel from "../../model/Bookmark";
|
||||
import DropboxUtil from "./dropbox";
|
||||
import WebdavUtil from "./webdav";
|
||||
import localforage from "localforage";
|
||||
import SyncUtil, { moveData } from "./common";
|
||||
import BookUtil from "../fileUtils/bookUtil";
|
||||
import OtherUtil from "../otherUtil";
|
||||
import { zipBook, zipConfig } from "./common";
|
||||
|
||||
let JSZip = (window as any).JSZip;
|
||||
|
||||
class BackupUtil {
|
||||
static backup = async (
|
||||
bookArr: BookModel[],
|
||||
notes: NoteModel[],
|
||||
bookmarks: BookmarkModel[],
|
||||
handleFinish: () => void,
|
||||
driveIndex: number,
|
||||
showMessage: (message: string) => void
|
||||
) => {
|
||||
export const backup = (
|
||||
bookArr: BookModel[],
|
||||
notes: NoteModel[],
|
||||
bookmarks: BookmarkModel[],
|
||||
isSync: boolean
|
||||
) => {
|
||||
return new Promise<Blob | boolean>(async (resolve, reject) => {
|
||||
let zip = new JSZip();
|
||||
let books = bookArr;
|
||||
//0表示备份到本地,1表示备份到dropbox,2表示备份到onedrive,3表示备份到webdav,4表示把indexeddb中的数据转移到uploads文件夹中,5表示同步数据到本地
|
||||
if (driveIndex !== 5) {
|
||||
let bookZip = zip.folder("book");
|
||||
let data: any = [];
|
||||
books &&
|
||||
books.forEach((item) => {
|
||||
data.push(
|
||||
driveIndex === 4
|
||||
? localforage.getItem(item.key)
|
||||
: BookUtil.fetchBook(item.key)
|
||||
);
|
||||
});
|
||||
let results = await Promise.all(data);
|
||||
for (let i = 0; i < books.length; i++) {
|
||||
bookZip.file(`${books[i].key}`, results[i]);
|
||||
}
|
||||
} else {
|
||||
let timestamp = new Date().getTime().toString();
|
||||
OtherUtil.setReaderConfig("lastSyncTime", timestamp);
|
||||
|
||||
localStorage.setItem("lastSyncTime", timestamp);
|
||||
let result = await zipConfig(zip, books, notes, bookmarks);
|
||||
if (!result) resolve(false);
|
||||
if (!isSync) {
|
||||
await zipBook(zip, books);
|
||||
}
|
||||
let configZip = zip.folder("config");
|
||||
configZip
|
||||
.file("notes.json", JSON.stringify(notes))
|
||||
.file("books.json", JSON.stringify(books))
|
||||
.file("bookmarks.json", JSON.stringify(bookmarks))
|
||||
.file("readerConfig.json", localStorage.getItem("readerConfig") || "")
|
||||
.file("themeColors.json", localStorage.getItem("themeColors") || "")
|
||||
.file(
|
||||
"bookSortCode.json",
|
||||
localStorage.getItem("bookSortCode") ||
|
||||
JSON.stringify({ sort: 0, order: 2 })
|
||||
)
|
||||
.file(
|
||||
"noteSortCode.json",
|
||||
localStorage.getItem("noteSortCode") ||
|
||||
JSON.stringify({ sort: 2, order: 2 })
|
||||
)
|
||||
.file("readingTime.json", localStorage.getItem("readingTime") || "")
|
||||
.file("recentBooks.json", localStorage.getItem("recentBooks") || [])
|
||||
.file("favoriteBooks.json", localStorage.getItem("favoriteBooks") || [])
|
||||
.file("shelfList.json", localStorage.getItem("shelfList") || [])
|
||||
.file("noteTags.json", localStorage.getItem("noteTags") || [])
|
||||
.file("pdfjs.history.json", localStorage.getItem("pdfjs.history") || [])
|
||||
.file(
|
||||
"recordLocation.json",
|
||||
localStorage.getItem("recordLocation") || ""
|
||||
);
|
||||
let year = new Date().getFullYear(),
|
||||
month = new Date().getMonth() + 1,
|
||||
day = new Date().getDate();
|
||||
|
||||
zip
|
||||
.generateAsync({ type: "blob" })
|
||||
.then((blob: any) => {
|
||||
switch (driveIndex) {
|
||||
case 0:
|
||||
handleFinish();
|
||||
FileSaver.saveAs(
|
||||
blob,
|
||||
`${year}-${month <= 9 ? "0" + month : month}-${
|
||||
day <= 9 ? "0" + day : day
|
||||
}.zip`
|
||||
);
|
||||
break;
|
||||
case 1:
|
||||
DropboxUtil.UploadFile(blob, handleFinish, showMessage);
|
||||
break;
|
||||
case 2:
|
||||
break;
|
||||
case 3:
|
||||
WebdavUtil.UploadFile(
|
||||
new File([blob], "data.zip", {
|
||||
lastModified: new Date().getTime(),
|
||||
type: blob.type,
|
||||
}),
|
||||
handleFinish,
|
||||
showMessage
|
||||
);
|
||||
break;
|
||||
case 4:
|
||||
moveData(blob, 4, books);
|
||||
|
||||
break;
|
||||
case 5:
|
||||
handleFinish();
|
||||
SyncUtil.syncData(blob, 5, [], handleFinish);
|
||||
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
resolve(blob);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.log(err);
|
||||
resolve(false);
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
export default BackupUtil;
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,6 +1,28 @@
|
||||
import BookModel from "../../model/Book";
|
||||
import localforage from "localforage";
|
||||
import BookUtil from "../fileUtils/bookUtil";
|
||||
import NoteModel from "../../model/Note";
|
||||
import BookmarkModel from "../../model/Bookmark";
|
||||
import { isElectron } from "react-device-detect";
|
||||
|
||||
let JSZip = (window as any).JSZip;
|
||||
let configArr = [
|
||||
"notes",
|
||||
"books",
|
||||
"bookmarks",
|
||||
"readerConfig",
|
||||
"noteTags",
|
||||
"themeColors",
|
||||
"bookSortCode",
|
||||
"noteSortCode",
|
||||
"readingTime",
|
||||
"recentBooks",
|
||||
"favoriteBooks",
|
||||
"favoriteBooks",
|
||||
"shelfList",
|
||||
"pdfjs.history",
|
||||
"recordLocation",
|
||||
];
|
||||
export function getParamsFromUrl() {
|
||||
var hashParams: any = {};
|
||||
var e,
|
||||
@@ -14,6 +36,7 @@ export function getParamsFromUrl() {
|
||||
}
|
||||
return hashParams;
|
||||
}
|
||||
//移动文件到指定路径
|
||||
export const moveData = (
|
||||
blob,
|
||||
driveIndex,
|
||||
@@ -64,15 +87,9 @@ export const moveData = (
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
class SyncUtil {
|
||||
static changeLocation(
|
||||
oldPath: string,
|
||||
newPath: string,
|
||||
handleMessage: (message: string) => void,
|
||||
handleMessageBox: (isShow: boolean) => void,
|
||||
syncFromLocation: () => void = () => {}
|
||||
) {
|
||||
//改变数据存储路径
|
||||
export const changePath = (oldPath: string, newPath: string) => {
|
||||
return new Promise<number>((resolve, reject) => {
|
||||
const fs = window.require("fs-extra");
|
||||
try {
|
||||
fs.readdir(newPath, (err, files: string[]) => {
|
||||
@@ -84,27 +101,23 @@ class SyncUtil {
|
||||
});
|
||||
if (isConfiged) {
|
||||
localStorage.setItem("storageLocation", newPath);
|
||||
syncFromLocation();
|
||||
resolve(1);
|
||||
} else {
|
||||
fs.copy(oldPath, newPath, function (err) {
|
||||
if (err) return;
|
||||
fs.emptyDirSync(oldPath);
|
||||
handleMessage("Change Successfully");
|
||||
handleMessageBox(true);
|
||||
resolve(2);
|
||||
});
|
||||
}
|
||||
});
|
||||
} catch (error) {
|
||||
handleMessage("Change Failed");
|
||||
handleMessageBox(true);
|
||||
console.log(error);
|
||||
resolve(0);
|
||||
}
|
||||
}
|
||||
static syncData(
|
||||
blob,
|
||||
driveIndex,
|
||||
books: BookModel[] = [],
|
||||
handleFinish: () => void = () => {}
|
||||
) {
|
||||
});
|
||||
};
|
||||
export const syncData = (blob: Blob, books: BookModel[] = [], isSync: true) => {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
let file = new File([blob], "config.zip", {
|
||||
lastModified: new Date().getTime(),
|
||||
type: blob.type,
|
||||
@@ -127,17 +140,161 @@ class SyncUtil {
|
||||
var zip = new AdmZip(path.join(dataPath, file.name));
|
||||
zip.extractAllTo(/*target path*/ dataPath, /*overwrite*/ true);
|
||||
|
||||
if (driveIndex === 4) {
|
||||
if (!isSync) {
|
||||
let deleteBooks = books.map((item) => {
|
||||
return localforage.removeItem(item.key);
|
||||
});
|
||||
await Promise.all(deleteBooks);
|
||||
}
|
||||
if (driveIndex === 5) {
|
||||
handleFinish();
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export default SyncUtil;
|
||||
export const zipBook = (zip: any, books: BookModel[]) => {
|
||||
return new Promise<boolean>(async (resolve, reject) => {
|
||||
let bookZip = zip.folder("book");
|
||||
let data: any = [];
|
||||
books &&
|
||||
books.forEach((item) => {
|
||||
data.push(
|
||||
!isElectron
|
||||
? localforage.getItem(item.key)
|
||||
: BookUtil.fetchBook(item.key)
|
||||
);
|
||||
});
|
||||
try {
|
||||
let results = await Promise.all(data);
|
||||
for (let i = 0; i < books.length; i++) {
|
||||
bookZip.file(`${books[i].key}`, results[i]);
|
||||
}
|
||||
resolve(true);
|
||||
} catch (error) {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const unzipConfig = (file: File) => {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
let zip = new JSZip();
|
||||
let count = 0;
|
||||
configArr.forEach((item) => {
|
||||
zip
|
||||
.loadAsync(file)
|
||||
.then((content: any) => {
|
||||
return content.files[
|
||||
content.files[`${item}.json`]
|
||||
? `${item}.json`
|
||||
: `config/${item}.json`
|
||||
].async("text");
|
||||
})
|
||||
.then(async (text: any) => {
|
||||
if (text) {
|
||||
if (item === "notes" || item === "books" || item === "bookmarks") {
|
||||
localforage.setItem(item, JSON.parse(text));
|
||||
} else {
|
||||
localStorage.setItem(item, text);
|
||||
}
|
||||
}
|
||||
count++;
|
||||
if (count === configArr.length) {
|
||||
resolve(true);
|
||||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
reject(false);
|
||||
console.log(err, "Error happen");
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const unzipBook = (file: File) => {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
localforage.getItem("books").then((value: any) => {
|
||||
let zip = new JSZip();
|
||||
let count = 0;
|
||||
value &&
|
||||
value.length > 0 &&
|
||||
value.forEach((item: any) => {
|
||||
zip
|
||||
.loadAsync(file)
|
||||
.then((content: any) => {
|
||||
if (content.files[`book/${item.key}`]) {
|
||||
return content.files[`book/${item.key}`].async("arraybuffer");
|
||||
} else if (content.files[`${item.key}`]) {
|
||||
return content.files[`${item.key}`].async("arraybuffer");
|
||||
}
|
||||
if (
|
||||
content.files[`book/${item.name}.pdf`] &&
|
||||
item.description === "pdf"
|
||||
) {
|
||||
//兼容之前的版本
|
||||
return content.files[`book/${item.name}.pdf`].async(
|
||||
"arraybuffer"
|
||||
); // a promise of "Hello World\n"
|
||||
} else if (content.files[`book/${item.name}.epub`]) {
|
||||
return content.files[`book/${item.name}.epub`].async(
|
||||
"arraybuffer"
|
||||
); // a promise of "Hello World\n"
|
||||
}
|
||||
})
|
||||
.then(async (book: any) => {
|
||||
await BookUtil.addBook(item.key, book);
|
||||
count++;
|
||||
if (count === value.length) {
|
||||
resolve(true);
|
||||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const zipConfig = (
|
||||
zip: any,
|
||||
books: BookModel[],
|
||||
notes: NoteModel[],
|
||||
bookmarks: BookmarkModel[]
|
||||
) => {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
try {
|
||||
let configZip = zip.folder("config");
|
||||
configZip
|
||||
.file("notes.json", JSON.stringify(notes))
|
||||
.file("books.json", JSON.stringify(books))
|
||||
.file("bookmarks.json", JSON.stringify(bookmarks))
|
||||
.file("readerConfig.json", localStorage.getItem("readerConfig") || "")
|
||||
.file("themeColors.json", localStorage.getItem("themeColors") || "")
|
||||
.file(
|
||||
"bookSortCode.json",
|
||||
localStorage.getItem("bookSortCode") ||
|
||||
JSON.stringify({ sort: 0, order: 2 })
|
||||
)
|
||||
.file(
|
||||
"noteSortCode.json",
|
||||
localStorage.getItem("noteSortCode") ||
|
||||
JSON.stringify({ sort: 2, order: 2 })
|
||||
)
|
||||
.file("readingTime.json", localStorage.getItem("readingTime") || "")
|
||||
.file("recentBooks.json", localStorage.getItem("recentBooks") || [])
|
||||
.file("favoriteBooks.json", localStorage.getItem("favoriteBooks") || [])
|
||||
.file("shelfList.json", localStorage.getItem("shelfList") || [])
|
||||
.file("noteTags.json", localStorage.getItem("noteTags") || [])
|
||||
.file("pdfjs.history.json", localStorage.getItem("pdfjs.history") || [])
|
||||
.file(
|
||||
"recordLocation.json",
|
||||
localStorage.getItem("recordLocation") || ""
|
||||
);
|
||||
resolve(true);
|
||||
} catch (error) {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,76 +1,66 @@
|
||||
import RestoreUtil from "./restoreUtil";
|
||||
import { restore } from "./restoreUtil";
|
||||
import OtherUtil from "../otherUtil";
|
||||
|
||||
var Dropbox = (window as any).Dropbox;
|
||||
|
||||
class DropboxUtil {
|
||||
static UploadFile(
|
||||
blob: any,
|
||||
handleFinish: () => void,
|
||||
showMessage: (message: string) => void
|
||||
) {
|
||||
var ACCESS_TOKEN = OtherUtil.getReaderConfig("dropbox_token") || "";
|
||||
let year = new Date().getFullYear(),
|
||||
month = new Date().getMonth() + 1,
|
||||
day = new Date().getDate();
|
||||
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
|
||||
const file = new File([blob], "data.zip");
|
||||
|
||||
dbx
|
||||
.filesUpload({
|
||||
path: "/data.zip",
|
||||
contents: file,
|
||||
})
|
||||
.then(function (response: any) {
|
||||
console.log(response, "上传成功");
|
||||
dbx
|
||||
.filesCopyV2({
|
||||
from_path: "/data.zip",
|
||||
to_path:
|
||||
"/" +
|
||||
`${year}-${month <= 9 ? "0" + month : month}-${
|
||||
day <= 9 ? "0" + day : day
|
||||
}.zip`,
|
||||
})
|
||||
.then(function (response: any) {
|
||||
console.log(response, "上传成功");
|
||||
handleFinish();
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.error(error, "上传失败");
|
||||
showMessage("Upload failed, check your connection");
|
||||
});
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.error(error, "上传失败");
|
||||
showMessage("Upload failed, check your connection");
|
||||
});
|
||||
return false;
|
||||
static UploadFile(blob: any) {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
var ACCESS_TOKEN = OtherUtil.getReaderConfig("dropbox_token") || "";
|
||||
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
|
||||
const file = new File([blob], "data.zip");
|
||||
let date = new Date().getTime();
|
||||
dbx
|
||||
.filesUpload({
|
||||
path: `/${date}/data.zip`,
|
||||
contents: file,
|
||||
})
|
||||
.then(function (response: any) {
|
||||
console.log(response, "上传成功");
|
||||
resolve(true);
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.error(error, "上传失败");
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
}
|
||||
static DownloadFile(
|
||||
handleFinish: () => void,
|
||||
showMessage: (message: string) => void,
|
||||
isSync: boolean = false
|
||||
) {
|
||||
var ACCESS_TOKEN = OtherUtil.getReaderConfig("dropbox_token") || "";
|
||||
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
|
||||
dbx
|
||||
.filesDownload({
|
||||
path: isSync ? "/config.zip" : "/data.zip",
|
||||
})
|
||||
.then(function (data: any) {
|
||||
let file = data.result.fileBlob;
|
||||
file.lastModifiedDate = new Date();
|
||||
file.name = "data.zip";
|
||||
RestoreUtil.restore(file, handleFinish, isSync);
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
showMessage("Download failed,network problem or no backup");
|
||||
|
||||
console.error(error);
|
||||
});
|
||||
|
||||
return false;
|
||||
static DownloadFile() {
|
||||
return new Promise<boolean>((resolve, reject) => {
|
||||
var ACCESS_TOKEN = OtherUtil.getReaderConfig("dropbox_token") || "";
|
||||
var dbx = new Dropbox.Dropbox({ accessToken: ACCESS_TOKEN });
|
||||
dbx
|
||||
.filesListFolder({ path: "" })
|
||||
.then(function (response) {
|
||||
let folderArr: string[] = [];
|
||||
response.result.entries.forEach((item) => {
|
||||
if (!isNaN(parseInt(item.name))) folderArr.push(item.name);
|
||||
});
|
||||
let folder = folderArr.sort().reverse()[0];
|
||||
dbx
|
||||
.filesDownload({
|
||||
path: `/${folder}/data.zip`,
|
||||
})
|
||||
.then(async (data: any) => {
|
||||
let file = data.result.fileBlob;
|
||||
file.lastModifiedDate = new Date();
|
||||
file.name = "data.zip";
|
||||
let result = await restore(file);
|
||||
if (result) {
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
})
|
||||
.catch(function (error: any) {
|
||||
console.error(error);
|
||||
resolve(false);
|
||||
});
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error(error);
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,97 +1,21 @@
|
||||
import localforage from "localforage";
|
||||
import BookUtil from "../fileUtils/bookUtil";
|
||||
import { unzipBook, unzipConfig } from "./common";
|
||||
|
||||
let JSZip = (window as any).JSZip;
|
||||
|
||||
class RestoreUtil {
|
||||
static restore = (file: any, handleFinish: () => void, isSync = false) => {
|
||||
let configArr = [
|
||||
"notes",
|
||||
"books",
|
||||
"bookmarks",
|
||||
"readerConfig",
|
||||
"noteTags",
|
||||
"themeColors",
|
||||
"bookSortCode",
|
||||
"noteSortCode",
|
||||
"readingTime",
|
||||
"recentBooks",
|
||||
"favoriteBooks",
|
||||
"favoriteBooks",
|
||||
"shelfList",
|
||||
"pdfjs.history",
|
||||
"recordLocation",
|
||||
];
|
||||
let zip = new JSZip();
|
||||
|
||||
// more files !
|
||||
configArr.forEach((item) => {
|
||||
zip
|
||||
.loadAsync(file)
|
||||
.then((content: any) => {
|
||||
// you now have every files contained in the loaded zip
|
||||
return content.files[
|
||||
content.files[`${item}.json`]
|
||||
? `${item}.json`
|
||||
: `config/${item}.json`
|
||||
].async("text"); // a promise of "Hello World\n"
|
||||
})
|
||||
.then((text: any) => {
|
||||
if (text) {
|
||||
if (item === "notes" || item === "books" || item === "bookmarks") {
|
||||
localforage.setItem(item, JSON.parse(text));
|
||||
} else {
|
||||
localStorage.setItem(item, text);
|
||||
}
|
||||
}
|
||||
})
|
||||
.then(() => {
|
||||
if (item === "books" && !isSync) {
|
||||
localforage.getItem("books").then((value: any) => {
|
||||
let zip = new JSZip();
|
||||
value &&
|
||||
value.length > 0 &&
|
||||
value.forEach((item: any) => {
|
||||
zip
|
||||
.loadAsync(file)
|
||||
.then((content: any) => {
|
||||
if (content.files[`book/${item.key}`]) {
|
||||
return content.files[`book/${item.key}`].async(
|
||||
"arraybuffer"
|
||||
);
|
||||
}
|
||||
//兼容之前的版本
|
||||
if (
|
||||
content.files[`book/${item.name}.pdf`] &&
|
||||
item.description === "pdf"
|
||||
) {
|
||||
return content.files[`book/${item.name}.pdf`].async(
|
||||
"arraybuffer"
|
||||
); // a promise of "Hello World\n"
|
||||
} else if (content.files[`book/${item.name}.epub`]) {
|
||||
return content.files[`book/${item.name}.epub`].async(
|
||||
"arraybuffer"
|
||||
); // a promise of "Hello World\n"
|
||||
}
|
||||
})
|
||||
.then(async (book: any) => {
|
||||
await BookUtil.addBook(item.key, book);
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.log(err, "Error occurs");
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
})
|
||||
.catch((err: any) => {
|
||||
console.log(err, "Error happen");
|
||||
});
|
||||
});
|
||||
setTimeout(() => {
|
||||
handleFinish();
|
||||
}, 1000);
|
||||
};
|
||||
}
|
||||
|
||||
export default RestoreUtil;
|
||||
export const restore = (file: any, isSync = false) => {
|
||||
return new Promise<boolean>(async (resolve, reject) => {
|
||||
let result = await unzipConfig(file);
|
||||
if (result) {
|
||||
if (isSync) {
|
||||
resolve(true);
|
||||
} else {
|
||||
let res = await unzipBook(file);
|
||||
if (res) {
|
||||
resolve(true);
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,101 +1,98 @@
|
||||
import RestoreUtil from "./restoreUtil";
|
||||
import { restore } from "./restoreUtil";
|
||||
import OtherUtil from "../otherUtil";
|
||||
|
||||
class WebdavUtil {
|
||||
static UploadFile = async (
|
||||
file: any,
|
||||
handleFinish: () => void,
|
||||
showMessage: (message: string) => void
|
||||
) => {
|
||||
const { createClient } = window.require("webdav");
|
||||
let { url, username, password } = JSON.parse(
|
||||
OtherUtil.getReaderConfig("webdav_token") || ""
|
||||
);
|
||||
const client = createClient(url, {
|
||||
username,
|
||||
password,
|
||||
static UploadFile = async (file: any) => {
|
||||
return new Promise<boolean>(async (resolve, reject) => {
|
||||
const { createClient } = window.require("webdav");
|
||||
let { url, username, password } = JSON.parse(
|
||||
OtherUtil.getReaderConfig("webdav_token") || ""
|
||||
);
|
||||
const client = createClient(url, {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
var wfs = window.require("webdav-fs")(url, {
|
||||
username: username,
|
||||
password: password,
|
||||
});
|
||||
if ((await client.exists("/KoodoReader")) === false) {
|
||||
await client.createDirectory("/KoodoReader");
|
||||
}
|
||||
wfs.writeFile("/KoodoReader/data.zip", file, "binary", function (err) {
|
||||
console.log(err);
|
||||
if (err) resolve(false);
|
||||
let year = new Date().getFullYear(),
|
||||
month = new Date().getMonth() + 1,
|
||||
day = new Date().getDate();
|
||||
client
|
||||
.copyFile(
|
||||
"/KoodoReader/data.zip",
|
||||
"/KoodoReader/" +
|
||||
`${year}-${month <= 9 ? "0" + month : month}-${
|
||||
day <= 9 ? "0" + day : day
|
||||
}.zip`
|
||||
)
|
||||
.then(() => {
|
||||
resolve(true);
|
||||
})
|
||||
.catch(() => {
|
||||
resolve(false);
|
||||
});
|
||||
});
|
||||
});
|
||||
var wfs = window.require("webdav-fs")(url, {
|
||||
username: username,
|
||||
password: password,
|
||||
});
|
||||
if ((await client.exists("/KoodoReader")) === false) {
|
||||
await client.createDirectory("/KoodoReader");
|
||||
}
|
||||
wfs.writeFile("/KoodoReader/data.zip", file, "binary", function (err) {
|
||||
console.log(err);
|
||||
if (err) showMessage("Upload failed, check your connection");
|
||||
let year = new Date().getFullYear(),
|
||||
month = new Date().getMonth() + 1,
|
||||
day = new Date().getDate();
|
||||
client
|
||||
.copyFile(
|
||||
"/KoodoReader/data.zip",
|
||||
"/KoodoReader/" +
|
||||
`${year}-${month <= 9 ? "0" + month : month}-${
|
||||
day <= 9 ? "0" + day : day
|
||||
}.zip`
|
||||
)
|
||||
.then(() => {
|
||||
handleFinish();
|
||||
})
|
||||
.catch(() => {
|
||||
showMessage("Upload failed, check your connection");
|
||||
};
|
||||
static DownloadFile = async () => {
|
||||
return new Promise<boolean>(async (resolve, reject) => {
|
||||
const fs = window.require("fs");
|
||||
const path = window.require("path");
|
||||
const { createClient } = window.require("webdav");
|
||||
const { remote, app } = window.require("electron");
|
||||
const configDir = (app || remote.app).getPath("userData");
|
||||
const dirPath = path.join(configDir, "uploads");
|
||||
const request = window.require("request");
|
||||
let { url, username, password } = JSON.parse(
|
||||
OtherUtil.getReaderConfig("webdav_token") || ""
|
||||
);
|
||||
const client = createClient(url, {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
if ((await client.exists("/KoodoReader/data.zip")) === false) {
|
||||
resolve(false);
|
||||
}
|
||||
const downloadLink: string = client.getFileDownloadLink(
|
||||
"/KoodoReader/data.zip"
|
||||
);
|
||||
let stream = fs.createWriteStream(path.join(dirPath, `data.zip`));
|
||||
request(downloadLink)
|
||||
.pipe(stream)
|
||||
.on("close", async (err) => {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
resolve(false);
|
||||
} else {
|
||||
var data = fs.readFileSync(path.join(dirPath, `data.zip`));
|
||||
let blobTemp: any = new Blob([data], { type: "application/zip" });
|
||||
let fileTemp = new File([blobTemp], "data.zip", {
|
||||
lastModified: new Date().getTime(),
|
||||
type: blobTemp.type,
|
||||
});
|
||||
let result = await restore(fileTemp);
|
||||
if (!result) resolve(false);
|
||||
try {
|
||||
const fs_extra = window.require("fs-extra");
|
||||
fs_extra.remove(path.join(dirPath, `data.zip`), (error: any) => {
|
||||
if (error) resolve(false);
|
||||
resolve(true);
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("error removing ", path.join(dirPath, `data.zip`));
|
||||
resolve(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
static DownloadFile = async (
|
||||
handleFinish: () => void,
|
||||
showMessage: (message: string) => void
|
||||
) => {
|
||||
const fs = window.require("fs");
|
||||
const path = window.require("path");
|
||||
const { createClient } = window.require("webdav");
|
||||
const { remote, app } = window.require("electron");
|
||||
const configDir = (app || remote.app).getPath("userData");
|
||||
const dirPath = path.join(configDir, "uploads");
|
||||
const request = window.require("request");
|
||||
let { url, username, password } = JSON.parse(
|
||||
OtherUtil.getReaderConfig("webdav_token") || ""
|
||||
);
|
||||
const client = createClient(url, {
|
||||
username,
|
||||
password,
|
||||
});
|
||||
if ((await client.exists("/KoodoReader/data.zip")) === false) {
|
||||
showMessage("Download failed,network problem or no backup");
|
||||
}
|
||||
const downloadLink: string = client.getFileDownloadLink(
|
||||
"/KoodoReader/data.zip"
|
||||
);
|
||||
let stream = fs.createWriteStream(path.join(dirPath, `data.zip`));
|
||||
request(downloadLink)
|
||||
.pipe(stream)
|
||||
.on("close", function (err) {
|
||||
if (err) {
|
||||
console.log(err);
|
||||
} else {
|
||||
var data = fs.readFileSync(path.join(dirPath, `data.zip`));
|
||||
let blobTemp: any = new Blob([data], { type: "application/zip" });
|
||||
let fileTemp = new File([blobTemp], "data.zip", {
|
||||
lastModified: new Date().getTime(),
|
||||
type: blobTemp.type,
|
||||
});
|
||||
RestoreUtil.restore(fileTemp, handleFinish);
|
||||
try {
|
||||
const fs_extra = window.require("fs-extra");
|
||||
fs_extra.remove(path.join(dirPath, `data.zip`), (error: any) => {
|
||||
if (error) throw error;
|
||||
});
|
||||
} catch (e) {
|
||||
console.log("error removing ", path.join(dirPath, `data.zip`));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
return false;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user