mirror of
https://github.com/koodo-reader/koodo-reader.git
synced 2025-12-23 23:17:55 -05:00
9
.github/workflows/release.yml
vendored
9
.github/workflows/release.yml
vendored
@@ -51,6 +51,15 @@ jobs:
|
||||
run: echo "USE_SYSTEM_FPM=true" >> $GITHUB_ENV
|
||||
- name: Set environment variable USE_HARD_LINKS
|
||||
run: echo "USE_HARD_LINKS=false" >> $GITHUB_ENV
|
||||
- name: Modify package.json for dev branch
|
||||
if: github.ref == 'refs/heads/dev'
|
||||
shell: bash
|
||||
run: |
|
||||
if [[ "${{ matrix.os }}" == "windows-latest" ]]; then
|
||||
powershell -Command "(Get-Content package.json) -replace '\"productName\": \"Koodo Reader\"', '\"productName\": \"Koodo Reader DEV\"' | Set-Content package.json"
|
||||
else
|
||||
sed -i.bak 's/"productName": "Koodo Reader"/"productName": "Koodo Reader DEV"/' package.json
|
||||
fi
|
||||
- name: Modify package.json for Linux arm64 build
|
||||
if: startsWith(matrix.os, 'ubuntu-24.04-arm')
|
||||
run: |
|
||||
|
||||
6
main.js
6
main.js
@@ -669,12 +669,12 @@ const createMainWin = () => {
|
||||
ipcMain.handle("reload-reader", (event, arg) => {
|
||||
if (readerWindowList.length > 0) {
|
||||
readerWindowList.forEach(win => {
|
||||
if (win && !win.isDestroyed()) {
|
||||
if (win && !win.isDestroyed() && win.webContents.getURL().indexOf(arg.bookKey) > -1) {
|
||||
win.reload();
|
||||
}
|
||||
})
|
||||
}
|
||||
if (readerWindow && !readerWindow.isDestroyed()) {
|
||||
if (readerWindow && !readerWindow.isDestroyed() && readerWindow.webContents.getURL().indexOf(arg.bookKey) > -1) {
|
||||
readerWindow.reload();
|
||||
}
|
||||
});
|
||||
@@ -697,7 +697,6 @@ const createMainWin = () => {
|
||||
hasShadow: true,
|
||||
transparent: false,
|
||||
});
|
||||
console.log(config.url)
|
||||
chatWindow.loadURL(config.url);
|
||||
chatWindow.on("close", (event) => {
|
||||
chatWindow && chatWindow.destroy();
|
||||
@@ -720,7 +719,6 @@ const createMainWin = () => {
|
||||
}
|
||||
});
|
||||
ipcMain.on('picker-action', (event, config) => {
|
||||
console.log("Picker finished with data:", config);
|
||||
//将数据传递给主窗口
|
||||
|
||||
if (mainWin && !mainWin.isDestroyed() && config.action === 'picked') {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "koodo-reader",
|
||||
"main": "main.js",
|
||||
"version": "2.2.2",
|
||||
"version": "2.2.3",
|
||||
"description": "Koodo Reader is a cross-platform ebook reader",
|
||||
"author": {
|
||||
"name": "App by Troye",
|
||||
|
||||
2
src/assets/lib/kookit-extra-browser.min.js
vendored
2
src/assets/lib/kookit-extra-browser.min.js
vendored
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
2
src/assets/lib/kookit.min.js
vendored
2
src/assets/lib/kookit.min.js
vendored
File diff suppressed because one or more lines are too long
@@ -208,6 +208,8 @@
|
||||
"Note": "笔记",
|
||||
"Page width": "页面宽度",
|
||||
"Tasks failed after multiple retries, please check the network connection": "多次重试后任务失败,请检查网络连接",
|
||||
"Tasks failed after multiple retries, please check the network connection or reauthorize the data source in the settings": "多次重试后任务失败,请检查网络连接或在设置中重新授权数据源",
|
||||
"This data source already contains a library. If you need to merge local and cloud data, please turn off Koodo Sync and resync.": "此数据源已经存在了一个图书库,如果需要将本地和云端的数据合并。请关闭 Koodo Sync 后重新同步。",
|
||||
"Render PDF from even page": "从偶数页开始渲染 PDF",
|
||||
"Filter by book": "按图书筛选",
|
||||
"Server path (Please first create this folder manually)": "服务器路径(请先手动创建此文件夹)",
|
||||
@@ -337,7 +339,11 @@
|
||||
"Start Transferring Data": "开始传输数据",
|
||||
"Download successful": "下载成功",
|
||||
"Download failed": "下载失败",
|
||||
"If you have purchased the code directly from our website, please redeem with an account registered in global server region": "如果您是直接从我们的网站购买的兑换码,请使用在全球服务器地区注册的账户进行兑换",
|
||||
"If you have purchased the code from Tabao store, please redeem with an account registered in Chinese server region": "如果您是从淘宝店铺购买的兑换码,请使用在中国服务器地区注册的账户进行兑换",
|
||||
"Downloading": "下载中",
|
||||
"Send email": "发送邮件",
|
||||
"Email copied to clipboard": "邮箱已复制到剪贴板",
|
||||
"Back": "返回",
|
||||
"Almost finished": "即将完成",
|
||||
"Please select an empty folder": "请选择一个空文件夹",
|
||||
|
||||
@@ -2,7 +2,7 @@ import React from "react";
|
||||
import { Trans } from "react-i18next";
|
||||
import { AboutDialogProps, AboutDialogState } from "./interface";
|
||||
import { isElectron } from "react-device-detect";
|
||||
import { openExternalUrl, WEBSITE_URL } from "../../../utils/common";
|
||||
import { getWebsiteUrl, openExternalUrl } from "../../../utils/common";
|
||||
import toast from "react-hot-toast";
|
||||
import {
|
||||
exportBooks,
|
||||
@@ -13,8 +13,7 @@ import {
|
||||
import "./aboutDialog.css";
|
||||
import DatabaseService from "../../../utils/storage/databaseService";
|
||||
import { ConfigService } from "../../../assets/lib/kookit-extra-browser.min";
|
||||
import ConfigUtil from "../../../utils/file/configUtil";
|
||||
|
||||
import copyTextToClipboard from "copy-text-to-clipboard";
|
||||
declare var window: any;
|
||||
class AboutDialog extends React.Component<AboutDialogProps, AboutDialogState> {
|
||||
constructor(props: AboutDialogProps) {
|
||||
@@ -59,9 +58,9 @@ class AboutDialog extends React.Component<AboutDialogProps, AboutDialogState> {
|
||||
ConfigService.getReaderConfig("lang") &&
|
||||
ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
) {
|
||||
this.handleJump(WEBSITE_URL + "/zh/document");
|
||||
this.handleJump(getWebsiteUrl() + "/zh/document");
|
||||
} else {
|
||||
this.handleJump(WEBSITE_URL + "/en/document");
|
||||
this.handleJump(getWebsiteUrl() + "/en/document");
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -74,9 +73,9 @@ class AboutDialog extends React.Component<AboutDialogProps, AboutDialogState> {
|
||||
ConfigService.getReaderConfig("lang") &&
|
||||
ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
) {
|
||||
openExternalUrl(WEBSITE_URL + "/zh/support");
|
||||
openExternalUrl(getWebsiteUrl() + "/zh/support");
|
||||
} else {
|
||||
openExternalUrl(WEBSITE_URL + "/en/support");
|
||||
openExternalUrl(getWebsiteUrl() + "/en/support");
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -85,11 +84,20 @@ class AboutDialog extends React.Component<AboutDialogProps, AboutDialogState> {
|
||||
<li
|
||||
className="sort-by-category-list"
|
||||
onClick={() => {
|
||||
this.handleJump(WEBSITE_URL);
|
||||
this.handleJump(getWebsiteUrl());
|
||||
}}
|
||||
>
|
||||
<Trans>Our website</Trans>
|
||||
</li>
|
||||
<li
|
||||
className="sort-by-category-list"
|
||||
onClick={() => {
|
||||
copyTextToClipboard("feedback@koodoreader.com");
|
||||
toast.success(this.props.t("Email copied to clipboard"));
|
||||
}}
|
||||
>
|
||||
<Trans>Send email</Trans>
|
||||
</li>
|
||||
<li
|
||||
className="sort-by-category-list"
|
||||
onClick={() => {
|
||||
@@ -125,7 +133,7 @@ class AboutDialog extends React.Component<AboutDialogProps, AboutDialogState> {
|
||||
<li
|
||||
className="sort-by-category-list"
|
||||
onClick={() => {
|
||||
this.handleJump(WEBSITE_URL);
|
||||
this.handleJump(getWebsiteUrl());
|
||||
}}
|
||||
style={{ color: "rgb(35, 170, 242)" }}
|
||||
>
|
||||
|
||||
@@ -14,7 +14,7 @@ import {
|
||||
ConfigService,
|
||||
TokenService,
|
||||
} from "../../../assets/lib/kookit-extra-browser.min";
|
||||
import { generateSyncRecord } from "../../../utils/common";
|
||||
import { generateSyncRecord, getServerRegion } from "../../../utils/common";
|
||||
const successOptions = {
|
||||
loop: false,
|
||||
autoplay: true,
|
||||
@@ -157,7 +157,7 @@ class BackupDialog extends React.Component<
|
||||
{[
|
||||
{ label: "Local", value: "local", isPro: false },
|
||||
...driveList.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
@@ -211,7 +211,7 @@ class BackupDialog extends React.Component<
|
||||
{[
|
||||
{ label: "Local", value: "local", isPro: false },
|
||||
...driveList.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -48,7 +48,7 @@ class ConvertDialog extends React.Component<
|
||||
item.propName,
|
||||
this.state[item.propName] ? "no" : "yes"
|
||||
);
|
||||
BookUtil.reloadBooks();
|
||||
BookUtil.reloadBooks(this.props.currentBook);
|
||||
}}
|
||||
style={this.state[item.propName] ? {} : { opacity: 0.6 }}
|
||||
>
|
||||
@@ -123,7 +123,7 @@ class ConvertDialog extends React.Component<
|
||||
if (
|
||||
ConfigService.getReaderConfig("isConvertPDF") === "yes"
|
||||
) {
|
||||
BookUtil.reloadBooks();
|
||||
BookUtil.reloadBooks(this.props.currentBook);
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -182,7 +182,7 @@ class ConvertDialog extends React.Component<
|
||||
if (
|
||||
ConfigService.getReaderConfig("isConvertPDF") === "yes"
|
||||
) {
|
||||
BookUtil.reloadBooks();
|
||||
BookUtil.reloadBooks(this.props.currentBook);
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -237,7 +237,7 @@ class ConvertDialog extends React.Component<
|
||||
ConfigService.getReaderConfig("isConvertPDF") ===
|
||||
"yes"
|
||||
) {
|
||||
BookUtil.reloadBooks();
|
||||
BookUtil.reloadBooks(this.props.currentBook);
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -298,7 +298,7 @@ class ConvertDialog extends React.Component<
|
||||
ConfigService.getReaderConfig("isConvertPDF") ===
|
||||
"yes"
|
||||
) {
|
||||
BookUtil.reloadBooks();
|
||||
BookUtil.reloadBooks(this.props.currentBook);
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -9,6 +9,7 @@ import { isElectron } from "react-device-detect";
|
||||
import { getCloudConfig } from "../../../utils/file/common";
|
||||
import SyncService from "../../../utils/storage/syncService";
|
||||
import {
|
||||
getServerRegion,
|
||||
getStorageLocation,
|
||||
openInBrowser,
|
||||
showDownloadProgress,
|
||||
@@ -368,7 +369,7 @@ class ImportDialog extends React.Component<
|
||||
<>
|
||||
{driveList
|
||||
.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
@@ -411,8 +412,7 @@ class ImportDialog extends React.Component<
|
||||
) {
|
||||
openInBrowser(
|
||||
new SyncUtil(settingDrive, {}).getAuthUrl(
|
||||
ConfigService.getItem("serverRegion") ===
|
||||
"china" &&
|
||||
getServerRegion() === "china" &&
|
||||
(settingDrive === "microsoft" ||
|
||||
settingDrive === "microsoft_exp" ||
|
||||
settingDrive === "adrive")
|
||||
|
||||
@@ -68,29 +68,17 @@ class SortDialog extends React.Component<SortDialogProps, SortDialogState> {
|
||||
onMouseEnter={() => {
|
||||
this.props.handleSortDisplay(true);
|
||||
}}
|
||||
style={this.state.isNote ? { height: "132px" } : {}}
|
||||
style={this.state.isNote ? { height: "102px" } : {}}
|
||||
>
|
||||
{this.state.isNote ? (
|
||||
<ul className="sort-by-category">
|
||||
{["Book name", "Sort by Date"].map((item, index) => {
|
||||
return (
|
||||
<li
|
||||
className="sort-by-category-list"
|
||||
onClick={() => {
|
||||
this.handleSort(index + 1);
|
||||
}}
|
||||
style={sortCode.sort === index + 1 ? {} : { opacity: 0.34 }}
|
||||
>
|
||||
<Trans>{item}</Trans>
|
||||
{sortCode.sort === index + 1 && (
|
||||
<span
|
||||
className="icon-check"
|
||||
style={{ fontWeight: "bold" }}
|
||||
></span>
|
||||
)}
|
||||
</li>
|
||||
);
|
||||
})}
|
||||
<li className="sort-by-category-list">
|
||||
<Trans>{"Sort by Date"}</Trans>
|
||||
<span
|
||||
className="icon-check"
|
||||
style={{ fontWeight: "bold" }}
|
||||
></span>
|
||||
</li>
|
||||
</ul>
|
||||
) : (
|
||||
<ul className="sort-by-category">
|
||||
|
||||
@@ -6,9 +6,10 @@ import Lottie from "react-lottie";
|
||||
import supportAnimation from "../../../assets/lotties/support.json";
|
||||
import exitAnimation from "../../../assets/lotties/exit.json";
|
||||
import {
|
||||
getServerRegion,
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
openInBrowser,
|
||||
WEBSITE_URL,
|
||||
} from "../../../utils/common";
|
||||
import {
|
||||
ConfigService,
|
||||
@@ -237,6 +238,27 @@ class SupporDialog extends React.Component<
|
||||
id: "redeem-code",
|
||||
}
|
||||
);
|
||||
if (response.code === 10009) {
|
||||
if (getServerRegion() === "china") {
|
||||
toast(
|
||||
this.props.t(
|
||||
"If you have purchased the code directly from our website, please redeem with an account registered in global server region"
|
||||
),
|
||||
{
|
||||
duration: 8000,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
toast(
|
||||
this.props.t(
|
||||
"If you have purchased the code from Tabao store, please redeem with an account registered in Chinese server region"
|
||||
),
|
||||
{
|
||||
duration: 8000,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -338,7 +360,7 @@ class SupporDialog extends React.Component<
|
||||
let deviceUuid =
|
||||
await TokenService.getFingerprint();
|
||||
openInBrowser(
|
||||
WEBSITE_URL +
|
||||
getWebsiteUrl() +
|
||||
(ConfigService.getReaderConfig(
|
||||
"lang"
|
||||
).startsWith("zh")
|
||||
|
||||
@@ -5,7 +5,7 @@ import packageInfo from "../../../../package.json";
|
||||
import { Trans } from "react-i18next";
|
||||
import Lottie from "react-lottie";
|
||||
import animationNew from "../../../assets/lotties/new.json";
|
||||
import { openExternalUrl, WEBSITE_URL } from "../../../utils/common";
|
||||
import { getWebsiteUrl, openExternalUrl } from "../../../utils/common";
|
||||
import { isElectron } from "react-device-detect";
|
||||
import { sleep } from "../../../utils/common";
|
||||
import {
|
||||
@@ -207,7 +207,7 @@ class UpdateInfo extends React.Component<UpdateInfoProps, UpdateInfoState> {
|
||||
lang = "zh";
|
||||
}
|
||||
openExternalUrl(
|
||||
WEBSITE_URL +
|
||||
getWebsiteUrl() +
|
||||
"/" +
|
||||
lang +
|
||||
"/download" +
|
||||
@@ -238,7 +238,7 @@ class UpdateInfo extends React.Component<UpdateInfoProps, UpdateInfoState> {
|
||||
lang = "zh";
|
||||
}
|
||||
openExternalUrl(
|
||||
WEBSITE_URL +
|
||||
getWebsiteUrl() +
|
||||
"/" +
|
||||
lang +
|
||||
"/download" +
|
||||
|
||||
@@ -6,9 +6,9 @@ import Parser from "html-react-parser";
|
||||
import DOMPurify from "dompurify";
|
||||
import { Trans } from "react-i18next";
|
||||
import {
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
openExternalUrl,
|
||||
WEBSITE_URL,
|
||||
} from "../../../utils/common";
|
||||
import toast from "react-hot-toast";
|
||||
import DatabaseService from "../../../utils/storage/databaseService";
|
||||
@@ -348,9 +348,9 @@ class PopupAssist extends React.Component<PopupAssistProps, PopupAssistState> {
|
||||
ConfigService.getReaderConfig("lang") &&
|
||||
ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
) {
|
||||
openExternalUrl(WEBSITE_URL + "/zh/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/zh/plugin");
|
||||
} else {
|
||||
openExternalUrl(WEBSITE_URL + "/en/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/en/plugin");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -8,9 +8,9 @@ import axios from "axios";
|
||||
import DictHistory from "../../../models/DictHistory";
|
||||
import { Trans } from "react-i18next";
|
||||
import {
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
openExternalUrl,
|
||||
WEBSITE_URL,
|
||||
} from "../../../utils/common";
|
||||
import toast from "react-hot-toast";
|
||||
import DatabaseService from "../../../utils/storage/databaseService";
|
||||
@@ -114,7 +114,7 @@ class PopupDict extends React.Component<PopupDictProps, PopupDictState> {
|
||||
let moreElement = document.querySelector(".dict-learn-more");
|
||||
if (moreElement) {
|
||||
moreElement.addEventListener("click", () => {
|
||||
openExternalUrl(window.learnMoreUrl || WEBSITE_URL);
|
||||
openExternalUrl(window.learnMoreUrl || getWebsiteUrl());
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -273,9 +273,9 @@ class PopupDict extends React.Component<PopupDictProps, PopupDictState> {
|
||||
ConfigService.getReaderConfig("lang") &&
|
||||
ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
) {
|
||||
openExternalUrl(WEBSITE_URL + "/zh/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/zh/plugin");
|
||||
} else {
|
||||
openExternalUrl(WEBSITE_URL + "/en/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/en/plugin");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -7,9 +7,9 @@ import { Trans } from "react-i18next";
|
||||
import toast from "react-hot-toast";
|
||||
import {
|
||||
getDefaultTransTarget,
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
openExternalUrl,
|
||||
WEBSITE_URL,
|
||||
} from "../../../utils/common";
|
||||
import DatabaseService from "../../../utils/storage/databaseService";
|
||||
import { checkPlugin } from "../../../utils/common";
|
||||
@@ -214,9 +214,9 @@ class PopupTrans extends React.Component<PopupTransProps, PopupTransState> {
|
||||
ConfigService.getReaderConfig("lang") &&
|
||||
ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
) {
|
||||
openExternalUrl(WEBSITE_URL + "/zh/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/zh/plugin");
|
||||
} else {
|
||||
openExternalUrl(WEBSITE_URL + "/en/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/en/plugin");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -6,10 +6,10 @@ import { ConfigService } from "../../assets/lib/kookit-extra-browser.min";
|
||||
import {
|
||||
checkPlugin,
|
||||
getAllVoices,
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
sleep,
|
||||
splitSentences,
|
||||
WEBSITE_URL,
|
||||
} from "../../utils/common";
|
||||
import { isElectron } from "react-device-detect";
|
||||
import toast from "react-hot-toast";
|
||||
@@ -536,9 +536,9 @@ class TextToSpeech extends React.Component<
|
||||
ConfigService.getReaderConfig("lang") &&
|
||||
ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
) {
|
||||
openExternalUrl(WEBSITE_URL + "/zh/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/zh/plugin");
|
||||
} else {
|
||||
openExternalUrl(WEBSITE_URL + "/en/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/en/plugin");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -31,21 +31,21 @@ import {
|
||||
checkMissingBook,
|
||||
generateSyncRecord,
|
||||
getChatLocale,
|
||||
getStorageLocation,
|
||||
getWebsiteUrl,
|
||||
removeChatBox,
|
||||
resetKoodoSync,
|
||||
showTaskProgress,
|
||||
WEBSITE_URL,
|
||||
} from "../../utils/common";
|
||||
import { driveList } from "../../constants/driveList";
|
||||
import SupportDialog from "../../components/dialogs/supportDialog";
|
||||
import SyncService from "../../utils/storage/syncService";
|
||||
import { LocalFileManager } from "../../utils/file/localFile";
|
||||
import { updateUserConfig } from "../../utils/request/user";
|
||||
import packageJson from "../../../package.json";
|
||||
declare var window: any;
|
||||
|
||||
class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
timer: any;
|
||||
private isSyncing: boolean = false;
|
||||
constructor(props: HeaderProps) {
|
||||
super(props);
|
||||
|
||||
@@ -132,8 +132,13 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
});
|
||||
this.props.handleCloudSyncFunc(this.handleCloudSync);
|
||||
document.addEventListener("visibilitychange", async (event) => {
|
||||
if (document.visibilityState === "visible") {
|
||||
if (
|
||||
document.visibilityState === "visible" &&
|
||||
!isElectron &&
|
||||
ConfigService.getReaderConfig("isFinishWebReading") === "yes"
|
||||
) {
|
||||
this.handleFinishReading();
|
||||
ConfigService.setReaderConfig("isFinishWebReading", "no");
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -171,27 +176,24 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
}
|
||||
}
|
||||
handleFinishReading = async () => {
|
||||
if (!this.props.isLoadMore) {
|
||||
this.props.handleFetchBooks();
|
||||
}
|
||||
this.props.handleFetchBookmarks();
|
||||
this.props.handleFetchNotes();
|
||||
|
||||
if (ConfigService.getItem("isFinshReading") === "yes") {
|
||||
ConfigService.setItem("isFinshReading", "no");
|
||||
if (
|
||||
ConfigService.getReaderConfig("isDisableAutoSync") !== "yes" &&
|
||||
ConfigService.getItem("defaultSyncOption")
|
||||
) {
|
||||
await this.props.handleFetchUserInfo();
|
||||
this.setState({ isSync: true });
|
||||
this.handleCloudSync();
|
||||
}
|
||||
ConfigService.setItem("isFinshReading", "yes");
|
||||
if (
|
||||
ConfigService.getReaderConfig("isDisableAutoSync") !== "yes" &&
|
||||
ConfigService.getItem("defaultSyncOption") &&
|
||||
!this.state.isSync
|
||||
) {
|
||||
await this.props.handleFetchUserInfo();
|
||||
this.setState({ isSync: true }, async () => {
|
||||
await this.handleCloudSync();
|
||||
ConfigService.setItem("isFinshReading", "no");
|
||||
});
|
||||
}
|
||||
};
|
||||
handleFinishUpgrade = () => {
|
||||
setTimeout(() => {
|
||||
this.props.history.push("/manager/home");
|
||||
if (this.props.mode === "home") {
|
||||
this.props.history.push("/manager/home");
|
||||
}
|
||||
}, 2000);
|
||||
};
|
||||
|
||||
@@ -247,7 +249,6 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
beforeSync = async () => {
|
||||
if (!ConfigService.getItem("defaultSyncOption")) {
|
||||
toast.error(this.props.t("Please add data source in the setting"));
|
||||
this.setState({ isSync: false });
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
@@ -269,7 +270,6 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
duration: 4000,
|
||||
}
|
||||
);
|
||||
this.setState({ isSync: false });
|
||||
return false;
|
||||
}
|
||||
let config = await getCloudConfig(
|
||||
@@ -277,7 +277,6 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
);
|
||||
if (Object.keys(config).length === 0) {
|
||||
toast.error(this.props.t("Cannot get sync config"));
|
||||
this.setState({ isSync: false });
|
||||
return false;
|
||||
}
|
||||
if (
|
||||
@@ -301,16 +300,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
this.props.handleFetchDefaultSyncOption();
|
||||
}
|
||||
if (ConfigService.getReaderConfig("isEnableKoodoSync") === "yes") {
|
||||
await updateUserConfig({
|
||||
is_enable_koodo_sync: "no",
|
||||
default_sync_option:
|
||||
ConfigService.getItem("defaultSyncOption") === "google",
|
||||
});
|
||||
setTimeout(() => {
|
||||
updateUserConfig({
|
||||
is_enable_koodo_sync: "yes",
|
||||
});
|
||||
}, 1000);
|
||||
resetKoodoSync();
|
||||
}
|
||||
toast(
|
||||
this.props.t(
|
||||
@@ -318,7 +308,6 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
),
|
||||
{ duration: 4000 }
|
||||
);
|
||||
this.setState({ isSync: false });
|
||||
return false;
|
||||
}
|
||||
checkMissingBook(this.props.books);
|
||||
@@ -329,7 +318,6 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
"Broken data detected, please click the setting button to reset the sync records"
|
||||
)
|
||||
);
|
||||
this.setState({ isSync: false });
|
||||
return false;
|
||||
}
|
||||
if (ConfigService.getReaderConfig("isEnableKoodoSync") !== "yes") {
|
||||
@@ -360,12 +348,23 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
ConfigUtil
|
||||
);
|
||||
};
|
||||
handleSyncStateChange = (isSyncing: boolean) => {
|
||||
this.setState({ isSync: isSyncing });
|
||||
};
|
||||
handleCloudSync = async (): Promise<false | undefined> => {
|
||||
this.timer = await showTaskProgress();
|
||||
if (!this.timer) {
|
||||
if (this.isSyncing) {
|
||||
console.info("Sync already in progress, skipping...");
|
||||
return false;
|
||||
}
|
||||
this.isSyncing = true;
|
||||
|
||||
try {
|
||||
this.timer = await showTaskProgress(this.handleSyncStateChange);
|
||||
if (!this.timer) {
|
||||
this.setState({ isSync: false });
|
||||
return false;
|
||||
}
|
||||
|
||||
let res = await this.beforeSync();
|
||||
if (!res) {
|
||||
clearInterval(this.timer);
|
||||
@@ -389,6 +388,8 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
clearInterval(this.timer);
|
||||
this.setState({ isSync: false });
|
||||
return false;
|
||||
} finally {
|
||||
this.isSyncing = false;
|
||||
}
|
||||
setTimeout(() => {
|
||||
toast.dismiss("syncing");
|
||||
@@ -396,9 +397,10 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
return;
|
||||
};
|
||||
handleSuccess = async () => {
|
||||
if (!this.props.isLoadMore) {
|
||||
if (ConfigService.getItem("isFinshReading") !== "yes" || !isElectron) {
|
||||
this.props.handleFetchBooks();
|
||||
}
|
||||
|
||||
this.props.handleFetchBookmarks();
|
||||
this.props.handleFetchNotes();
|
||||
toast.success(this.props.t("Synchronisation successful"), {
|
||||
@@ -424,7 +426,9 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
}
|
||||
//when book is empty, need to refresh the book list
|
||||
setTimeout(() => {
|
||||
this.props.history.push("/manager/home");
|
||||
if (this.props.mode === "home") {
|
||||
this.props.history.push("/manager/home");
|
||||
}
|
||||
}, 1000);
|
||||
};
|
||||
handleSync = async (compareResult) => {
|
||||
@@ -498,7 +502,7 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
onClick={() => {
|
||||
window.require("electron").ipcRenderer.invoke("new-chat", {
|
||||
url:
|
||||
WEBSITE_URL +
|
||||
getWebsiteUrl() +
|
||||
(ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
? "/zh/faq"
|
||||
: "/en/faq") +
|
||||
|
||||
@@ -30,6 +30,7 @@ const mapStateToProps = (state: stateType) => {
|
||||
isCollapsed: state.sidebar.isCollapsed,
|
||||
isNewWarning: state.manager.isNewWarning,
|
||||
notes: state.reader.notes,
|
||||
mode: state.sidebar.mode,
|
||||
isAuthed: state.manager.isAuthed,
|
||||
defaultSyncOption: state.backupPage.defaultSyncOption,
|
||||
userInfo: state.manager.userInfo,
|
||||
|
||||
@@ -14,6 +14,7 @@ export interface HeaderProps extends RouteComponentProps<any> {
|
||||
notes: NoteModel[];
|
||||
books: BookModel[];
|
||||
defaultSyncOption: string;
|
||||
mode: string;
|
||||
userInfo: any;
|
||||
bookSortCode: { sort: number; order: number };
|
||||
handleSortDisplay: (isSortDisplay: boolean) => void;
|
||||
|
||||
@@ -3,10 +3,8 @@ import "./cardList.css";
|
||||
import NoteModel from "../../../models/Note";
|
||||
import { Trans } from "react-i18next";
|
||||
import { CardListProps, CardListStates } from "./interface";
|
||||
import DeleteIcon from "../../../components/deleteIcon";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { Redirect } from "react-router-dom";
|
||||
import NoteTag from "../../../components/noteTag";
|
||||
import BookUtil from "../../../utils/file/bookUtil";
|
||||
import toast from "react-hot-toast";
|
||||
import BookModel from "../../../models/Book";
|
||||
@@ -52,13 +50,13 @@ class CardList extends React.Component<CardListProps, CardListStates> {
|
||||
}
|
||||
|
||||
loadInitialCards = () => {
|
||||
let sortedCards = Object.values(
|
||||
SortUtil.sortNotes(
|
||||
this.props.cards,
|
||||
this.props.noteSortCode,
|
||||
this.props.books
|
||||
)
|
||||
).flat() as NoteModel[];
|
||||
let sortedCards = [...this.props.cards];
|
||||
// 按照key排序
|
||||
sortedCards.sort((a, b) => {
|
||||
return this.props.noteSortCode.order === 2
|
||||
? b.key.localeCompare(a.key)
|
||||
: a.key.localeCompare(b.key);
|
||||
});
|
||||
const { itemsPerPage } = this.state;
|
||||
|
||||
// 根据屏幕大小动态调整每页显示的卡片数量
|
||||
@@ -75,13 +73,12 @@ class CardList extends React.Component<CardListProps, CardListStates> {
|
||||
};
|
||||
|
||||
loadMoreCards = () => {
|
||||
let sortedCards = Object.values(
|
||||
SortUtil.sortNotes(
|
||||
this.props.cards,
|
||||
this.props.noteSortCode,
|
||||
this.props.books
|
||||
)
|
||||
).flat() as NoteModel[];
|
||||
let sortedCards = [...this.props.cards];
|
||||
sortedCards.sort((a, b) => {
|
||||
return this.props.noteSortCode.order === 2
|
||||
? b.key.localeCompare(a.key)
|
||||
: a.key.localeCompare(b.key);
|
||||
});
|
||||
const { displayedCards, currentPage, itemsPerPage, isLoading } = this.state;
|
||||
|
||||
if (isLoading || displayedCards.length >= sortedCards.length) {
|
||||
|
||||
@@ -70,7 +70,6 @@ class OperationPanel extends React.Component<
|
||||
}
|
||||
async handleExit() {
|
||||
ConfigService.setReaderConfig("isFullscreen", "no");
|
||||
ConfigService.setItem("isFinshReading", "yes");
|
||||
this.props.handleReadingState(false);
|
||||
this.props.handleSearch(false);
|
||||
window.speechSynthesis && window.speechSynthesis.cancel();
|
||||
@@ -86,6 +85,7 @@ class OperationPanel extends React.Component<
|
||||
window.close();
|
||||
}
|
||||
} else {
|
||||
ConfigService.setReaderConfig("isFinishWebReading", "yes");
|
||||
window.close();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,16 +3,15 @@ import { SettingInfoProps, SettingInfoState } from "./interface";
|
||||
import { Trans } from "react-i18next";
|
||||
import { isElectron } from "react-device-detect";
|
||||
import _ from "underscore";
|
||||
import { themeList } from "../../../constants/themeList";
|
||||
import toast from "react-hot-toast";
|
||||
import {
|
||||
formatTimestamp,
|
||||
getServerRegion,
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
openInBrowser,
|
||||
reloadManager,
|
||||
WEBSITE_URL,
|
||||
} from "../../../utils/common";
|
||||
import { getStorageLocation } from "../../../utils/common";
|
||||
import {
|
||||
CommonTool,
|
||||
ConfigService,
|
||||
@@ -46,7 +45,7 @@ class AccountSetting extends React.Component<
|
||||
redeemCode: "",
|
||||
isSendingCode: false,
|
||||
countdown: 0,
|
||||
serverRegion: ConfigService.getItem("serverRegion") || "global",
|
||||
serverRegion: getServerRegion(),
|
||||
};
|
||||
}
|
||||
componentDidMount(): void {
|
||||
@@ -93,8 +92,7 @@ class AccountSetting extends React.Component<
|
||||
let url = LoginHelper.getAuthUrl(
|
||||
event.target.value,
|
||||
"manual",
|
||||
ConfigService.getItem("serverRegion") === "china" &&
|
||||
event.target.value === "microsoft"
|
||||
getServerRegion() === "china" && event.target.value === "microsoft"
|
||||
? KookitConfig.ThirdpartyConfig.cnCallbackUrl
|
||||
: KookitConfig.ThirdpartyConfig.callbackUrl
|
||||
);
|
||||
@@ -160,7 +158,7 @@ class AccountSetting extends React.Component<
|
||||
KookitConfig.LoginAuthRequest[this.state.settingLogin].extraParams
|
||||
.scope,
|
||||
redirect_uri:
|
||||
ConfigService.getItem("serverRegion") === "china" &&
|
||||
getServerRegion() === "china" &&
|
||||
this.state.settingLogin === "microsoft"
|
||||
? KookitConfig.ThirdpartyConfig.cnCallbackUrl
|
||||
: KookitConfig.ThirdpartyConfig.callbackUrl,
|
||||
@@ -252,7 +250,7 @@ class AccountSetting extends React.Component<
|
||||
let url = LoginHelper.getAuthUrl(
|
||||
this.state.settingLogin,
|
||||
"manual",
|
||||
ConfigService.getItem("serverRegion") === "china" &&
|
||||
getServerRegion() === "china" &&
|
||||
this.state.settingLogin === "microsoft"
|
||||
? KookitConfig.ThirdpartyConfig.cnCallbackUrl
|
||||
: KookitConfig.ThirdpartyConfig.callbackUrl
|
||||
@@ -525,6 +523,27 @@ class AccountSetting extends React.Component<
|
||||
id: "redeem-code",
|
||||
}
|
||||
);
|
||||
if (response.code === 10009) {
|
||||
if (getServerRegion() === "china") {
|
||||
toast(
|
||||
this.props.t(
|
||||
"If you have purchased the code directly from our website, please redeem with an account registered in global server region"
|
||||
),
|
||||
{
|
||||
duration: 8000,
|
||||
}
|
||||
);
|
||||
} else {
|
||||
toast(
|
||||
this.props.t(
|
||||
"If you have purchased the code from Tabao store, please redeem with an account registered in Chinese server region"
|
||||
),
|
||||
{
|
||||
duration: 8000,
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
@@ -544,49 +563,56 @@ class AccountSetting extends React.Component<
|
||||
</div>
|
||||
)}
|
||||
<div className="setting-dialog-new-title">
|
||||
<Trans>Select server region</Trans>
|
||||
<select
|
||||
name=""
|
||||
className="lang-setting-dropdown"
|
||||
onChange={(event) => {
|
||||
if (!event.target.value) {
|
||||
return;
|
||||
}
|
||||
if (event.target.value === "china") {
|
||||
toast(
|
||||
this.props.t(
|
||||
"Some login options and data sources are not available in your selected server region"
|
||||
)
|
||||
);
|
||||
}
|
||||
ConfigService.setItem("serverRegion", event.target.value);
|
||||
this.setState({
|
||||
serverRegion: event.target.value,
|
||||
});
|
||||
resetReaderRequest();
|
||||
resetUserRequest();
|
||||
resetThirdpartyRequest();
|
||||
toast.success(this.props.t("Setup successful"));
|
||||
}}
|
||||
>
|
||||
{[
|
||||
{ value: "", label: "Please select" },
|
||||
{ value: "global", label: "Global" },
|
||||
{ value: "china", label: "China" },
|
||||
].map((item) => (
|
||||
<option
|
||||
value={item.value}
|
||||
key={item.value}
|
||||
className="lang-setting-option"
|
||||
selected={
|
||||
item.value ===
|
||||
(ConfigService.getItem("serverRegion") || "global")
|
||||
<Trans>
|
||||
{this.props.isAuthed ? "Server region" : "Select server region"}
|
||||
</Trans>
|
||||
{this.props.isAuthed ? (
|
||||
<div className="lang-setting-option">
|
||||
<Trans>
|
||||
{getServerRegion() === "china" ? "China" : "Global"}
|
||||
</Trans>
|
||||
</div>
|
||||
) : (
|
||||
<select
|
||||
name=""
|
||||
className="lang-setting-dropdown"
|
||||
onChange={(event) => {
|
||||
if (!event.target.value) {
|
||||
return;
|
||||
}
|
||||
>
|
||||
{this.props.t(item.label)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
if (event.target.value === "china") {
|
||||
toast(
|
||||
this.props.t(
|
||||
"Some login options and data sources are not available in your selected server region"
|
||||
)
|
||||
);
|
||||
}
|
||||
ConfigService.setItem("serverRegion", event.target.value);
|
||||
this.setState({
|
||||
serverRegion: event.target.value,
|
||||
});
|
||||
resetReaderRequest();
|
||||
resetUserRequest();
|
||||
resetThirdpartyRequest();
|
||||
toast.success(this.props.t("Setup successful"));
|
||||
}}
|
||||
>
|
||||
{[
|
||||
{ value: "", label: "Please select" },
|
||||
{ value: "global", label: "Global" },
|
||||
{ value: "china", label: "China" },
|
||||
].map((item) => (
|
||||
<option
|
||||
value={item.value}
|
||||
key={item.value}
|
||||
className="lang-setting-option"
|
||||
selected={item.value === getServerRegion()}
|
||||
>
|
||||
{this.props.t(item.label)}
|
||||
</option>
|
||||
))}
|
||||
</select>
|
||||
)}
|
||||
</div>
|
||||
{!this.props.isAuthed && (
|
||||
<div className="setting-dialog-new-title">
|
||||
@@ -599,7 +625,7 @@ class AccountSetting extends React.Component<
|
||||
{[
|
||||
{ label: "Please select", value: "" },
|
||||
...loginList.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
@@ -827,7 +853,7 @@ class AccountSetting extends React.Component<
|
||||
onClick={async () => {
|
||||
if (!this.props.isAuthed) {
|
||||
openInBrowser(
|
||||
WEBSITE_URL +
|
||||
getWebsiteUrl() +
|
||||
(ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
? "/zh"
|
||||
: "/en") +
|
||||
@@ -840,7 +866,7 @@ class AccountSetting extends React.Component<
|
||||
let tempToken = response.data.access_token;
|
||||
let deviceUuid = await TokenService.getFingerprint();
|
||||
openInBrowser(
|
||||
WEBSITE_URL +
|
||||
getWebsiteUrl() +
|
||||
(ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
? "/zh"
|
||||
: "/en") +
|
||||
|
||||
@@ -6,9 +6,9 @@ import { themeList } from "../../../constants/themeList";
|
||||
import toast from "react-hot-toast";
|
||||
import {
|
||||
checkPlugin,
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
openExternalUrl,
|
||||
WEBSITE_URL,
|
||||
} from "../../../utils/common";
|
||||
import { getStorageLocation } from "../../../utils/common";
|
||||
import DatabaseService from "../../../utils/storage/databaseService";
|
||||
@@ -152,9 +152,9 @@ class SettingDialog extends React.Component<
|
||||
ConfigService.getReaderConfig("lang") &&
|
||||
ConfigService.getReaderConfig("lang").startsWith("zh")
|
||||
) {
|
||||
openExternalUrl(WEBSITE_URL + "/zh/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/zh/plugin");
|
||||
} else {
|
||||
openExternalUrl(WEBSITE_URL + "/en/plugin");
|
||||
openExternalUrl(getWebsiteUrl() + "/en/plugin");
|
||||
}
|
||||
}}
|
||||
>
|
||||
|
||||
@@ -10,13 +10,15 @@ import { themeList } from "../../../constants/themeList";
|
||||
import toast from "react-hot-toast";
|
||||
import {
|
||||
generateSyncRecord,
|
||||
getServerRegion,
|
||||
getWebsiteUrl,
|
||||
handleContextMenu,
|
||||
openExternalUrl,
|
||||
openInBrowser,
|
||||
resetKoodoSync,
|
||||
showTaskProgress,
|
||||
testConnection,
|
||||
testCORS,
|
||||
WEBSITE_URL,
|
||||
} from "../../../utils/common";
|
||||
import { getStorageLocation } from "../../../utils/common";
|
||||
import { driveInputConfig, driveList } from "../../../constants/driveList";
|
||||
@@ -35,6 +37,7 @@ import SyncService from "../../../utils/storage/syncService";
|
||||
import { updateUserConfig } from "../../../utils/request/user";
|
||||
import BookUtil from "../../../utils/file/bookUtil";
|
||||
import Book from "../../../models/Book";
|
||||
import ConfigUtil from "../../../utils/file/configUtil";
|
||||
declare var window: any;
|
||||
class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
constructor(props: SettingInfoProps) {
|
||||
@@ -112,7 +115,7 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
) {
|
||||
this.handleJump(
|
||||
new SyncUtil(settingDrive, {}).getAuthUrl(
|
||||
ConfigService.getItem("serverRegion") === "china" &&
|
||||
getServerRegion() === "china" &&
|
||||
(settingDrive === "microsoft" ||
|
||||
settingDrive === "microsoft_exp" ||
|
||||
settingDrive === "adrive")
|
||||
@@ -149,13 +152,24 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
return;
|
||||
}
|
||||
ConfigService.setItem("defaultSyncOption", event.target.value);
|
||||
if (ConfigService.getItem("isEnableKoodoSync") === "yes") {
|
||||
updateUserConfig({
|
||||
default_sync_option: event.target.value,
|
||||
});
|
||||
if (ConfigService.getReaderConfig("isEnableKoodoSync") === "yes") {
|
||||
resetKoodoSync();
|
||||
}
|
||||
this.props.handleFetchDefaultSyncOption();
|
||||
toast.success(this.props.t("Change successful"));
|
||||
if (
|
||||
!(await ConfigUtil.isCloudEmpty()) &&
|
||||
ConfigService.getReaderConfig("isEnableKoodoSync") === "yes"
|
||||
) {
|
||||
toast(
|
||||
this.props.t(
|
||||
"This data source already contains a library. If you need to merge local and cloud data, please turn off Koodo Sync and resync."
|
||||
),
|
||||
{
|
||||
duration: 10000,
|
||||
}
|
||||
);
|
||||
}
|
||||
};
|
||||
handleCancelDrive = () => {
|
||||
this.props.handleSettingDrive("");
|
||||
@@ -238,7 +252,7 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
ConfigService,
|
||||
BookUtil
|
||||
);
|
||||
let timer = await showTaskProgress();
|
||||
let timer = await showTaskProgress((_: boolean) => {});
|
||||
if (!timer) {
|
||||
return;
|
||||
}
|
||||
@@ -452,8 +466,11 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
}
|
||||
}
|
||||
if (
|
||||
this.props.settingDrive === "docker" ||
|
||||
this.props.settingDrive === "webdav" ||
|
||||
this.props.settingDrive === "docker" ||
|
||||
this.props.settingDrive === "ftp" ||
|
||||
this.props.settingDrive === "sftp" ||
|
||||
this.props.settingDrive === "mega" ||
|
||||
this.props.settingDrive === "s3compatible"
|
||||
) {
|
||||
let connectionResult = await testConnection(
|
||||
@@ -495,7 +512,7 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
onClick={async () => {
|
||||
this.handleJump(
|
||||
new SyncUtil(this.props.settingDrive, {}).getAuthUrl(
|
||||
ConfigService.getItem("serverRegion") === "china" &&
|
||||
getServerRegion() === "china" &&
|
||||
(this.props.settingDrive === "microsoft" ||
|
||||
this.props.settingDrive === "microsoft_exp" ||
|
||||
this.props.settingDrive === "adrive")
|
||||
@@ -545,7 +562,7 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
className="voice-add-cancel"
|
||||
style={{ borderWidth: 0, lineHeight: "30px" }}
|
||||
onClick={() => {
|
||||
openExternalUrl(WEBSITE_URL + "/zh/add-source");
|
||||
openExternalUrl(getWebsiteUrl() + "/zh/add-source");
|
||||
}}
|
||||
>
|
||||
{this.props.t("How to fill out")}
|
||||
@@ -570,7 +587,7 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
support: ["desktop", "browser", "phone"],
|
||||
},
|
||||
...driveList.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
@@ -608,7 +625,7 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
{[
|
||||
{ label: "Please select", value: "", isPro: false },
|
||||
...driveList.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
@@ -672,7 +689,7 @@ class SyncSetting extends React.Component<SettingInfoProps, SettingInfoState> {
|
||||
{[
|
||||
{ label: "Please select", value: "", isPro: false },
|
||||
...driveList.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -4,7 +4,7 @@ import { sideMenu } from "../../constants/sideMenu";
|
||||
import { SidebarProps, SidebarState } from "./interface";
|
||||
import { withRouter } from "react-router-dom";
|
||||
import { ConfigService } from "../../assets/lib/kookit-extra-browser.min";
|
||||
import { openInBrowser, WEBSITE_URL } from "../../utils/common";
|
||||
import { getWebsiteUrl, openInBrowser } from "../../utils/common";
|
||||
import { Trans } from "react-i18next";
|
||||
import toast from "react-hot-toast";
|
||||
class Sidebar extends React.Component<SidebarProps, SidebarState> {
|
||||
@@ -263,7 +263,7 @@ class Sidebar extends React.Component<SidebarProps, SidebarState> {
|
||||
}
|
||||
alt=""
|
||||
onClick={() => {
|
||||
this.handleJump(WEBSITE_URL);
|
||||
this.handleJump(getWebsiteUrl());
|
||||
}}
|
||||
style={this.state.isCollapsed ? { display: "none" } : {}}
|
||||
className="logo"
|
||||
|
||||
@@ -16,6 +16,7 @@ import PageWidget from "../pageWidget";
|
||||
import {
|
||||
getPageWidth,
|
||||
getPdfPassword,
|
||||
getServerRegion,
|
||||
scrollContents,
|
||||
showDownloadProgress,
|
||||
} from "../../utils/common";
|
||||
@@ -82,9 +83,12 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
|
||||
)
|
||||
);
|
||||
this.props.handleRenderBookFunc(this.handleRenderBook);
|
||||
|
||||
window.addEventListener("resize", () => {
|
||||
BookUtil.reloadBooks();
|
||||
let resizeTimer: NodeJS.Timeout;
|
||||
window.addEventListener("resize", (event) => {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(() => {
|
||||
BookUtil.reloadBooks(this.props.currentBook);
|
||||
}, 300); // 300ms 防抖
|
||||
});
|
||||
}
|
||||
async UNSAFE_componentWillReceiveProps(nextProps: ViewerProps) {
|
||||
@@ -214,20 +218,13 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
|
||||
if (result) {
|
||||
toast.success(this.props.t("Download successful"));
|
||||
} else {
|
||||
result = await BookUtil.downloadCacheBook(key);
|
||||
if (result) {
|
||||
toast.success(this.props.t("Download successful"));
|
||||
} else {
|
||||
toast.error(this.props.t("Download failed"));
|
||||
return;
|
||||
}
|
||||
toast.error(this.props.t("Book not exists"));
|
||||
}
|
||||
} else {
|
||||
toast.error(this.props.t("Book not exists"));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
let rendition = BookHelper.getRendition(
|
||||
result,
|
||||
{
|
||||
@@ -258,7 +255,10 @@ class Viewer extends React.Component<ViewerProps, ViewerState> {
|
||||
(item) => item.lang === ConfigService.getReaderConfig("lang")
|
||||
)?.value || "chi_sim",
|
||||
ocrEngine: ConfigService.getReaderConfig("ocrEngine") || "tesseract",
|
||||
serverRegion: ConfigService.getItem("serverRegion") || "global",
|
||||
serverRegion:
|
||||
ConfigService.getItem("serverRegion") === "china"
|
||||
? "china"
|
||||
: "global",
|
||||
paraSpacingValue:
|
||||
ConfigService.getReaderConfig("paraSpacingValue") || "1.5",
|
||||
titleSizeValue:
|
||||
|
||||
@@ -7,6 +7,7 @@ import toast, { Toaster } from "react-hot-toast";
|
||||
import { loginList } from "../../constants/loginList";
|
||||
import {
|
||||
generateSyncRecord,
|
||||
getServerRegion,
|
||||
handleContextMenu,
|
||||
openInBrowser,
|
||||
removeSearchParams,
|
||||
@@ -37,7 +38,7 @@ class Login extends React.Component<LoginProps, LoginState> {
|
||||
loginConfig: {},
|
||||
countdown: 0,
|
||||
isSendingCode: false,
|
||||
serverRegion: ConfigService.getItem("serverRegion") || "global",
|
||||
serverRegion: getServerRegion(),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -366,8 +367,8 @@ class Login extends React.Component<LoginProps, LoginState> {
|
||||
let url = LoginHelper.getAuthUrl(
|
||||
item.value,
|
||||
isElectron ? "desktop" : "browser",
|
||||
ConfigService.getItem("serverRegion") ===
|
||||
"china" && item.value === "microsoft"
|
||||
getServerRegion() === "china" &&
|
||||
item.value === "microsoft"
|
||||
? KookitConfig.ThirdpartyConfig.cnCallbackUrl
|
||||
: KookitConfig.ThirdpartyConfig.callbackUrl
|
||||
);
|
||||
@@ -453,7 +454,7 @@ class Login extends React.Component<LoginProps, LoginState> {
|
||||
<div className="login-sync-container">
|
||||
{driveList
|
||||
.filter((item) => {
|
||||
if (ConfigService.getItem("serverRegion") === "china") {
|
||||
if (getServerRegion() === "china") {
|
||||
return item.isCNAvailable;
|
||||
}
|
||||
return true;
|
||||
|
||||
@@ -11,8 +11,8 @@ import { Tooltip } from "react-tooltip";
|
||||
import "./index.css";
|
||||
import Book from "../../models/Book";
|
||||
import DatabaseService from "../../utils/storage/databaseService";
|
||||
import BookUtil from "../../utils/file/bookUtil";
|
||||
import ConvertDialog from "../../components/dialogs/convertDialog";
|
||||
import { isElectron } from "react-device-detect";
|
||||
|
||||
let lock = false; //prevent from clicking too fasts
|
||||
let throttleTime =
|
||||
@@ -67,8 +67,11 @@ class Reader extends React.Component<ReaderProps, ReaderState> {
|
||||
);
|
||||
}
|
||||
}, 5000);
|
||||
|
||||
window.addEventListener("beforeunload", function (event) {
|
||||
ConfigService.setItem("isFinshReading", "yes");
|
||||
if (!isElectron) {
|
||||
ConfigService.setReaderConfig("isFinishWebReading", "yes");
|
||||
}
|
||||
});
|
||||
window.addEventListener("mousemove", () => {
|
||||
isMouseMoving = true;
|
||||
|
||||
@@ -195,6 +195,9 @@ export function handleFetchAuthed() {
|
||||
try {
|
||||
TokenService.getToken("is_authed").then((value) => {
|
||||
let isAuthed = value === "yes";
|
||||
if (isAuthed && !ConfigService.getItem("serverRegion")) {
|
||||
ConfigService.setItem("serverRegion", "global");
|
||||
}
|
||||
dispatch(handleAuthed(isAuthed));
|
||||
});
|
||||
} catch (error) {
|
||||
|
||||
@@ -19,6 +19,7 @@ import { getCloudConfig } from "./file/common";
|
||||
import SyncService from "./storage/syncService";
|
||||
import localforage from "localforage";
|
||||
import { driveList } from "../constants/driveList";
|
||||
import { updateUserConfig } from "./request/user";
|
||||
declare var window: any;
|
||||
export const supportedFormats = [
|
||||
".epub",
|
||||
@@ -580,6 +581,21 @@ export const getDefaultTransTarget = (langList) => {
|
||||
return langMap[langTarget || "English"];
|
||||
};
|
||||
export const WEBSITE_URL = "https://koodoreader.com";
|
||||
export const CN_WEBSITE_URL = "https://koodoreader.cn";
|
||||
export const getServerRegion = () => {
|
||||
let isUseCN = false;
|
||||
if (ConfigService.getItem("serverRegion")) {
|
||||
isUseCN = ConfigService.getItem("serverRegion") === "china";
|
||||
} else {
|
||||
if (navigator.language && navigator.language === "zh-CN") {
|
||||
isUseCN = true;
|
||||
}
|
||||
}
|
||||
return isUseCN ? "china" : "global";
|
||||
};
|
||||
export const getWebsiteUrl = () => {
|
||||
return getServerRegion() === "china" ? CN_WEBSITE_URL : WEBSITE_URL;
|
||||
};
|
||||
export const formatTimestamp = (timestamp) => {
|
||||
if (!timestamp) return "";
|
||||
|
||||
@@ -800,7 +816,9 @@ export const showDownloadProgress = (
|
||||
}, 500);
|
||||
return timer;
|
||||
};
|
||||
export const showTaskProgress = async () => {
|
||||
export const showTaskProgress = async (
|
||||
handleSyncStateChange: (isSync: boolean) => void
|
||||
) => {
|
||||
let config = {};
|
||||
let timer: any;
|
||||
let service = ConfigService.getItem("defaultSyncOption");
|
||||
@@ -829,13 +847,14 @@ export const showTaskProgress = async () => {
|
||||
if (stats.hasFailedTasks) {
|
||||
toast.error(
|
||||
i18n.t(
|
||||
"Tasks failed after multiple retries, please check the network connection"
|
||||
"Tasks failed after multiple retries, please check the network connection or reauthorize the data source in the settings"
|
||||
),
|
||||
{
|
||||
id: "syncing",
|
||||
}
|
||||
);
|
||||
clearInterval(timer);
|
||||
handleSyncStateChange(false);
|
||||
return;
|
||||
} else {
|
||||
toast.loading(
|
||||
@@ -867,13 +886,14 @@ export const showTaskProgress = async () => {
|
||||
if (stats.hasFailedTasks) {
|
||||
toast.error(
|
||||
i18n.t(
|
||||
"Tasks failed after multiple retries, please check the network connection"
|
||||
"Tasks failed after multiple retries, please check the network connection or reauthorize the data source in the settings"
|
||||
),
|
||||
{
|
||||
id: "syncing",
|
||||
}
|
||||
);
|
||||
clearInterval(timer);
|
||||
handleSyncStateChange(false);
|
||||
return;
|
||||
} else {
|
||||
toast.loading(
|
||||
@@ -925,3 +945,15 @@ export const clearAllData = async () => {
|
||||
}
|
||||
await localforage.clear();
|
||||
};
|
||||
export const resetKoodoSync = async () => {
|
||||
await updateUserConfig({
|
||||
is_enable_koodo_sync: "no",
|
||||
default_sync_option: ConfigService.getItem("defaultSyncOption"),
|
||||
});
|
||||
setTimeout(() => {
|
||||
updateUserConfig({
|
||||
is_enable_koodo_sync: "yes",
|
||||
default_sync_option: ConfigService.getItem("defaultSyncOption"),
|
||||
});
|
||||
}, 1000);
|
||||
};
|
||||
|
||||
@@ -200,15 +200,14 @@ class BookUtil {
|
||||
let result = await this.downloadBook(book.key, book.format);
|
||||
clearInterval(timer);
|
||||
toast.dismiss("offline-book");
|
||||
if (ConfigService.getItem("defaultSyncOption") === "adrive") {
|
||||
let syncUtil = await SyncService.getSyncUtil();
|
||||
let covers = await syncUtil.listFiles("cover");
|
||||
for (let cover of covers) {
|
||||
if (cover.startsWith(book.key)) {
|
||||
await CoverUtil.downloadCover(cover);
|
||||
}
|
||||
|
||||
let covers = await CoverUtil.getCloudCoverList();
|
||||
for (let cover of covers) {
|
||||
if (cover.startsWith(book.key)) {
|
||||
await CoverUtil.downloadCover(cover);
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
toast.success(i18n.t("Download successful"), {
|
||||
id: "offline-book",
|
||||
@@ -276,12 +275,16 @@ class BookUtil {
|
||||
let ref = book.format.toLowerCase();
|
||||
return `/${ref}/${book.key}`;
|
||||
}
|
||||
static reloadBooks() {
|
||||
static reloadBooks(currentBook: BookModel) {
|
||||
if (isElectron) {
|
||||
if (ConfigService.getReaderConfig("isOpenInMain") === "yes") {
|
||||
window.require("electron").ipcRenderer.invoke("reload-tab", "ping");
|
||||
window
|
||||
.require("electron")
|
||||
.ipcRenderer.invoke("reload-tab", { bookKey: currentBook.key });
|
||||
} else {
|
||||
window.require("electron").ipcRenderer.invoke("reload-reader", "ping");
|
||||
window.require("electron").ipcRenderer.invoke("reload-reader", {
|
||||
bookKey: currentBook.key,
|
||||
});
|
||||
}
|
||||
} else {
|
||||
window.location.reload();
|
||||
|
||||
@@ -113,10 +113,9 @@ class ConfigUtil {
|
||||
}
|
||||
let thirdpartyRequest = await getThirdpartyRequest();
|
||||
|
||||
let response = await thirdpartyRequest.getSyncData();
|
||||
let response = await thirdpartyRequest.getSyncDataByType({ type });
|
||||
if (response.code === 200) {
|
||||
let syncData = response.data;
|
||||
this.syncData = syncData;
|
||||
this.syncData[type] = response.data;
|
||||
return JSON.parse(this.syncData[type] || defaultValue);
|
||||
} else if (response.code === 401) {
|
||||
handleExitApp();
|
||||
@@ -282,5 +281,13 @@ class ConfigUtil {
|
||||
}
|
||||
}
|
||||
}
|
||||
static async isCloudEmpty() {
|
||||
let syncDataStr = await this.downloadConfig("sync");
|
||||
let syncData = JSON.parse(syncDataStr || "{}");
|
||||
if (!syncData || Object.keys(syncData).length === 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
export default ConfigUtil;
|
||||
|
||||
@@ -132,7 +132,7 @@ export const scrollChapter = async (
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let lastScaleTime = 0;
|
||||
export const bindHtmlEvent = (
|
||||
rendition: any,
|
||||
doc: any,
|
||||
@@ -152,10 +152,16 @@ export const bindHtmlEvent = (
|
||||
},
|
||||
{ passive: false }
|
||||
);
|
||||
|
||||
doc.addEventListener(
|
||||
"wheel",
|
||||
async (event) => {
|
||||
if (event.ctrlKey && readerMode !== "double") {
|
||||
const currentTime = Date.now();
|
||||
if (currentTime - lastScaleTime < 1500) {
|
||||
return;
|
||||
}
|
||||
lastScaleTime = currentTime;
|
||||
event.preventDefault();
|
||||
let scale = parseFloat(ConfigService.getReaderConfig("scale") || "1");
|
||||
if (event.deltaY < 0) {
|
||||
|
||||
@@ -2,18 +2,18 @@ import axios from "axios";
|
||||
import toast from "react-hot-toast";
|
||||
import i18n from "../../i18n";
|
||||
import { TokenService } from "../../assets/lib/kookit-extra-browser.min";
|
||||
import { reloadManager } from "../common";
|
||||
import { getServerRegion, reloadManager } from "../common";
|
||||
const PUBLIC_URL = "https://api.960960.xyz";
|
||||
const CN_PUBLIC_URL = "https://api.koodoreader.cn";
|
||||
export const getPublicUrl = () => {
|
||||
return getServerRegion() === "china" ? CN_PUBLIC_URL : PUBLIC_URL;
|
||||
};
|
||||
export const checkDeveloperUpdate = async () => {
|
||||
let res = await axios.get(
|
||||
PUBLIC_URL + `/api/update_dev?name=${navigator.language}`
|
||||
getPublicUrl() + `/api/update_dev?name=${navigator.language}`
|
||||
);
|
||||
return res.data.log;
|
||||
};
|
||||
export const getUploadUrl = async () => {
|
||||
let res = await axios.get(PUBLIC_URL + "/api/get_temp_upload_url");
|
||||
return res.data;
|
||||
};
|
||||
export const uploadFile = async (url: string, file: any) => {
|
||||
return new Promise<boolean>((resolve) => {
|
||||
axios
|
||||
@@ -29,7 +29,7 @@ export const uploadFile = async (url: string, file: any) => {
|
||||
};
|
||||
export const checkStableUpdate = async () => {
|
||||
let res = await axios.get(
|
||||
PUBLIC_URL + `/api/update?name=${navigator.language}`
|
||||
getPublicUrl() + `/api/update?name=${navigator.language}`
|
||||
);
|
||||
return res.data.log;
|
||||
};
|
||||
|
||||
@@ -7,6 +7,7 @@ import {
|
||||
import i18n from "../../i18n";
|
||||
import { handleExitApp } from "./common";
|
||||
import { officialDictList } from "../../constants/settingList";
|
||||
import { getServerRegion } from "../common";
|
||||
let readerRequest: ReaderRequest | undefined;
|
||||
export const getTransStream = async (
|
||||
text: string,
|
||||
@@ -81,7 +82,11 @@ export const getReaderRequest = async () => {
|
||||
if (readerRequest) {
|
||||
return readerRequest;
|
||||
}
|
||||
readerRequest = new ReaderRequest(TokenService, ConfigService);
|
||||
readerRequest = new ReaderRequest(
|
||||
TokenService,
|
||||
ConfigService,
|
||||
getServerRegion()
|
||||
);
|
||||
return readerRequest;
|
||||
};
|
||||
export const resetReaderRequest = () => {
|
||||
|
||||
@@ -7,12 +7,17 @@ import {
|
||||
} from "../../assets/lib/kookit-extra-browser.min";
|
||||
import i18n from "../../i18n";
|
||||
import { handleExitApp } from "./common";
|
||||
import { getServerRegion } from "../common";
|
||||
let thirdpartyRequest: ThirdpartyRequest | undefined;
|
||||
export const getThirdpartyRequest = async () => {
|
||||
if (thirdpartyRequest) {
|
||||
return thirdpartyRequest;
|
||||
}
|
||||
thirdpartyRequest = new ThirdpartyRequest(TokenService, ConfigService);
|
||||
thirdpartyRequest = new ThirdpartyRequest(
|
||||
TokenService,
|
||||
ConfigService,
|
||||
getServerRegion()
|
||||
);
|
||||
return thirdpartyRequest;
|
||||
};
|
||||
export const resetThirdpartyRequest = () => {
|
||||
@@ -24,22 +29,7 @@ export const onSyncCallback = async (service: string, authCode: string) => {
|
||||
let thirdpartyRequest = await getThirdpartyRequest();
|
||||
|
||||
let syncUtil = new SyncUtil(service, {}, thirdpartyRequest);
|
||||
let timer = setTimeout(() => {
|
||||
if (
|
||||
ConfigService.getItem("serverRegion") !== "china" &&
|
||||
navigator.language === "zh-CN"
|
||||
) {
|
||||
toast.error(
|
||||
i18n.t(
|
||||
"Request timed out, You may change the server region to China to solve the connection issue in mainland China. Go to Settings > Account"
|
||||
),
|
||||
{ id: "adding-sync-error", duration: 6000 }
|
||||
);
|
||||
return;
|
||||
}
|
||||
}, 10000);
|
||||
let result = await syncUtil.authToken(authCode);
|
||||
clearTimeout(timer);
|
||||
if (!result.refresh_token) {
|
||||
toast.error(i18n.t("Authorization failed"), { id: "adding-sync-id" });
|
||||
return;
|
||||
@@ -95,24 +85,9 @@ export const encryptToken = async (service: string, config: any) => {
|
||||
return { code: 200, msg: "success", data: syncToken };
|
||||
}
|
||||
let thirdpartyRequest = await getThirdpartyRequest();
|
||||
let timer = setTimeout(() => {
|
||||
if (
|
||||
ConfigService.getItem("serverRegion") !== "china" &&
|
||||
navigator.language === "zh-CN"
|
||||
) {
|
||||
toast.error(
|
||||
i18n.t(
|
||||
"Request timed out, You may change the server region to China to solve the connection issue in mainland China. Go to Settings > Account"
|
||||
),
|
||||
{ id: "adding-sync-error", duration: 6000 }
|
||||
);
|
||||
return;
|
||||
}
|
||||
}, 10000);
|
||||
let response = await thirdpartyRequest.encryptToken({
|
||||
token: syncToken,
|
||||
});
|
||||
clearTimeout(timer);
|
||||
if (response.code === 200) {
|
||||
await TokenService.setToken(
|
||||
service + "_token",
|
||||
@@ -143,22 +118,7 @@ export const decryptToken = async (service: string) => {
|
||||
};
|
||||
}
|
||||
let thirdpartyRequest = await getThirdpartyRequest();
|
||||
let timer = setTimeout(() => {
|
||||
if (
|
||||
ConfigService.getItem("serverRegion") !== "china" &&
|
||||
navigator.language === "zh-CN"
|
||||
) {
|
||||
toast.error(
|
||||
i18n.t(
|
||||
"Request timed out, You may change the server region to China to solve the connection issue in mainland China. Go to Settings > Account"
|
||||
),
|
||||
{ id: "adding-sync-error", duration: 6000 }
|
||||
);
|
||||
return;
|
||||
}
|
||||
}, 10000);
|
||||
let encryptedToken = await TokenService.getToken(service + "_token");
|
||||
clearTimeout(timer);
|
||||
if (!encryptedToken || encryptedToken === "{}") {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -15,31 +15,17 @@ import packageJson from "../../../package.json";
|
||||
import toast from "react-hot-toast";
|
||||
import i18n from "../../i18n";
|
||||
import { handleExitApp } from "./common";
|
||||
import { getServerRegion } from "../common";
|
||||
let userRequest: UserRequest | undefined;
|
||||
export const loginRegister = async (service: string, code: string) => {
|
||||
let deviceName = detectBrowser();
|
||||
let userRequest = await getUserRequest();
|
||||
let timer = setTimeout(() => {
|
||||
if (
|
||||
ConfigService.getItem("serverRegion") !== "china" &&
|
||||
navigator.language === "zh-CN"
|
||||
) {
|
||||
toast.error(
|
||||
i18n.t(
|
||||
"Request timed out, You may change the server region to China to solve the connection issue in mainland China. Go to Settings > Account"
|
||||
),
|
||||
{ id: "adding-sync-error", duration: 6000 }
|
||||
);
|
||||
return;
|
||||
}
|
||||
}, 10000);
|
||||
let response = await userRequest.loginRegister({
|
||||
code,
|
||||
provider: service,
|
||||
scope: KookitConfig.LoginAuthRequest[service].extraParams.scope,
|
||||
redirect_uri:
|
||||
ConfigService.getItem("serverRegion") === "china" &&
|
||||
service === "microsoft"
|
||||
getServerRegion() === "china" && service === "microsoft"
|
||||
? KookitConfig.ThirdpartyConfig.cnCallbackUrl
|
||||
: KookitConfig.ThirdpartyConfig.callbackUrl,
|
||||
device_name: deviceName,
|
||||
@@ -50,11 +36,11 @@ export const loginRegister = async (service: string, code: string) => {
|
||||
device_uuid: await TokenService.getFingerprint(),
|
||||
app_version: packageJson.version,
|
||||
});
|
||||
clearTimeout(timer);
|
||||
if (response.code === 200) {
|
||||
await TokenService.setToken("is_authed", "yes");
|
||||
await TokenService.setToken("access_token", response.data.access_token);
|
||||
await TokenService.setToken("refresh_token", response.data.refresh_token);
|
||||
ConfigService.setItem("serverRegion", getServerRegion());
|
||||
}
|
||||
return response;
|
||||
};
|
||||
@@ -93,7 +79,7 @@ export const getUserRequest = async () => {
|
||||
if (userRequest) {
|
||||
return userRequest;
|
||||
}
|
||||
userRequest = new UserRequest(TokenService, ConfigService);
|
||||
userRequest = new UserRequest(TokenService, ConfigService, getServerRegion());
|
||||
return userRequest;
|
||||
};
|
||||
export const resetUserRequest = () => {
|
||||
|
||||
Reference in New Issue
Block a user