mirror of
https://github.com/koodo-reader/koodo-reader.git
synced 2026-06-19 05:11:09 -04:00
Update to 1.2.0
Former-commit-id: e5a60d54360126da49f31c2dd891d79129ce0bf9
This commit is contained in:
36
package.json
36
package.json
@@ -99,8 +99,40 @@
|
||||
},
|
||||
"linux": {
|
||||
"icon": "assets/icons",
|
||||
"category": "Office",
|
||||
"target": "AppImage"
|
||||
"target": [
|
||||
{
|
||||
"target": "deb",
|
||||
"arch": [
|
||||
"x64",
|
||||
"ia32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "rpm",
|
||||
"arch": [
|
||||
"x64",
|
||||
"ia32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "tar.gz",
|
||||
"arch": [
|
||||
"x64",
|
||||
"ia32"
|
||||
]
|
||||
},
|
||||
{
|
||||
"target": "freebsd",
|
||||
"arch": [
|
||||
"x64",
|
||||
"ia32"
|
||||
]
|
||||
},
|
||||
"AppImage",
|
||||
"snap",
|
||||
"pacman"
|
||||
],
|
||||
"category": "Office"
|
||||
},
|
||||
"portable": {
|
||||
"artifactName": "${productName}-${version}-Portable.${ext}"
|
||||
|
||||
@@ -165,7 +165,7 @@
|
||||
"Publisher": "Publisher",
|
||||
"Added at": "Added at",
|
||||
"Margin": "Margin",
|
||||
"Open link in browser": "Open link in browser",
|
||||
"Open link in browser": "Open in browser",
|
||||
"Do you want to open this link in browser": "Do you want to open this link in browser",
|
||||
"Webdav Info": "Webdav is an easy to use and efficent backup solution, here we recommand using webdav service provided by jianguoyun",
|
||||
"Please Wait a moment": "Please Wait a moment",
|
||||
|
||||
@@ -171,62 +171,62 @@
|
||||
"语言 / Language": "語言 / Language",
|
||||
"Cancel Successfully": "取消成功",
|
||||
"Dont't use mimical background": "不使用仿真背景",
|
||||
"Please continue in desktop version": "仅客户端版本支持",
|
||||
"Auto hide cursor when reading": "阅读时自动隐藏鼠标",
|
||||
"Book not exsit": "书籍不存在",
|
||||
"Delete this shelf": "删除此书架",
|
||||
"This action will clear and remove this shelf": "此操作会清空并删除此书架",
|
||||
"Delete this tag": "删除此标签",
|
||||
"This action will clear and remove this tag": "此操作会清空并删除此标签",
|
||||
"Scale": "页面缩放",
|
||||
"Next Chapter": "下一章",
|
||||
"Don't show footer": "不显示页脚",
|
||||
"Don't show header": "不显示页眉",
|
||||
"Default expand all content": "默认展开所有目录",
|
||||
"Prev Chapter": "上一章",
|
||||
"Current Reading Time": "本次阅读时间:{{count}}分钟",
|
||||
"Finish Reading Time": "读完本章需要:{{count}}分钟",
|
||||
"Book Page": "第{{count}}页",
|
||||
"Current Chapter Pages": "本章页数",
|
||||
"Chapter Redirect": "章节跳转",
|
||||
"Continuous Scroll": "连续滚动",
|
||||
"Chapter Scroll": "分章滚动",
|
||||
"Only Desktop support this format": "仅客户端版本支持 mobi 和 txt 格式",
|
||||
"Only Desktop support this service": "仅客户端支持该备份方式",
|
||||
"Please Wait a moment": "请稍侯",
|
||||
"Please continue in desktop version": "僅客戶端版本支持",
|
||||
"Auto hide cursor when reading": "閱讀時自動隱藏鼠標",
|
||||
"Book not exsit": "書籍不存在",
|
||||
"Delete this shelf": "刪除此書架",
|
||||
"This action will clear and remove this shelf": "此操作會清空並刪除此書架",
|
||||
"Delete this tag": "刪除此標簽",
|
||||
"This action will clear and remove this tag": "此操作會清空並刪除此標簽",
|
||||
"Scale": "頁面縮放",
|
||||
"Next Chapter": "下壹章",
|
||||
"Don't show footer": "不顯示頁腳",
|
||||
"Don't show header": "不顯示頁眉",
|
||||
"Default expand all content": "默認展開所有目錄",
|
||||
"Prev Chapter": "上壹章",
|
||||
"Current Reading Time": "本次閱讀時間:{{count}}分鐘",
|
||||
"Finish Reading Time": "讀完本章需要:{{count}}分鐘",
|
||||
"Book Page": "第{{count}}頁",
|
||||
"Current Chapter Pages": "本章頁數",
|
||||
"Chapter Redirect": "章節跳轉",
|
||||
"Continuous Scroll": "連續滾動",
|
||||
"Chapter Scroll": "分章滾動",
|
||||
"Only Desktop support this format": "僅客戶端版本支持 mobi 和 txt 格式",
|
||||
"Only Desktop support this service": "僅客戶端支持該備份方式",
|
||||
"Please Wait a moment": "請稍侯",
|
||||
|
||||
"It seems like you're lost": "你要访问的内容走丢了",
|
||||
"Return to home": "返回主页",
|
||||
"It seems like you're lost": "妳要訪問的內容走丟了",
|
||||
"Return to home": "返回主頁",
|
||||
"Deleted Books": "我的回收",
|
||||
"This action will move this book and its the notes, bookmarks and digests of this book to the recycle bin": "将本书以及本书的书签,笔记,书摘移至回收站",
|
||||
"Delete All Books": "清空所有图书",
|
||||
"This action will remove all the books in recycle bin,together with their notes, bookmarks and digests": "此操作会彻底删除回收站中的所有图书和它们的书签,笔记和书摘",
|
||||
"Restore": "还原",
|
||||
"Batch import only support epub or pdf files": "批量导入仅支持epub或pdf格式",
|
||||
"Drag any book to the Deleted tab to add it to Recycle Bin": "将任意图书拖拽到我的回收标签页,将其添加到回收站",
|
||||
"Empty Recycle Bin": "回收站为空",
|
||||
"Sort by Duration": "按阅读时长",
|
||||
"This action will move this book and its the notes, bookmarks and digests of this book to the recycle bin": "將本書以及本書的書簽,筆記,書摘移至回收站",
|
||||
"Delete All Books": "清空所有圖書",
|
||||
"This action will remove all the books in recycle bin,together with their notes, bookmarks and digests": "此操作會徹底刪除回收站中的所有圖書和它們的書簽,筆記和書摘",
|
||||
"Restore": "還原",
|
||||
"Batch import only support epub or pdf files": "批量導入僅支持epub或pdf格式",
|
||||
"Drag any book to the Deleted tab to add it to Recycle Bin": "將任意圖書拖拽到我的回收標簽頁,將其添加到回收站",
|
||||
"Empty Recycle Bin": "回收站為空",
|
||||
"Sort by Duration": "按閱讀時長",
|
||||
"Sort by Author": "按作者名",
|
||||
"Sort by Name": "按书名",
|
||||
"Audio is not ready yet": "图书解析中,请稍后再试",
|
||||
"Drop your books here": "拖拽图书到此处",
|
||||
"Export": "导出",
|
||||
"Text Color": "文字颜色",
|
||||
"Search my notes": "搜索我的笔记",
|
||||
"Search my digests": "搜索我的书摘",
|
||||
"Sort by Percentage": "按阅读进度",
|
||||
"Sort by Name": "按書名",
|
||||
"Audio is not ready yet": "圖書解析中,請稍後再試",
|
||||
"Drop your books here": "拖拽圖書到此處",
|
||||
"Export": "導出",
|
||||
"Text Color": "文字顏色",
|
||||
"Search my notes": "搜索我的筆記",
|
||||
"Search my digests": "搜索我的書摘",
|
||||
"Sort by Percentage": "按閱讀進度",
|
||||
"Publisher": "出版商",
|
||||
"Added at": "添加于",
|
||||
"Added at": "添加於",
|
||||
"Description": "描述",
|
||||
"Export Successfully": "导出成功",
|
||||
"Too many images": "图书包含过多图片会严重影响解析速度",
|
||||
"Margin": "页边距",
|
||||
"Open link in browser": "使用浏览器打开",
|
||||
"Server Address": "服务器地址",
|
||||
"Username": "用户名",
|
||||
"Password": "密码",
|
||||
"Do you want to open this link in browser": "是否使用浏览器打开此链接",
|
||||
"Webdav Info": "Webdav是一种简单高效的数据备份方式,这里推荐使用坚果云提供的Webdav服务",
|
||||
"For better user experince, please visit this site on a computer": "Koodo Reader专为桌面端设计打造,暂未适配移动端,请在电脑上打开本网站",
|
||||
"Sort by Recent": "按最近阅读"
|
||||
"Export Successfully": "導出成功",
|
||||
"Too many images": "圖書包含過多圖片會嚴重影響解析速度",
|
||||
"Margin": "頁邊距",
|
||||
"Open link in browser": "使用瀏覽器打開",
|
||||
"Server Address": "服務器地址",
|
||||
"Username": "用戶名",
|
||||
"Password": "密碼",
|
||||
"Do you want to open this link in browser": "是否使用瀏覽器打開此鏈接",
|
||||
"Webdav Info": "Webdav是壹種簡單高效的數據備份方式,這裏推薦使用堅果雲提供的Webdav服務",
|
||||
"For better user experince, please visit this site on a computer": "Koodo Reader專為桌面端設計打造,暫未適配移動端,請在電腦上打開本網站",
|
||||
"Sort by Recent": "按最近閱讀"
|
||||
}
|
||||
|
||||
1
src/assets/new.json
Normal file
1
src/assets/new.json
Normal file
File diff suppressed because one or more lines are too long
@@ -137,41 +137,3 @@
|
||||
z-index: 2;
|
||||
text-shadow: 0px 0px 5px rgba(75, 75, 75, 0.6);
|
||||
}
|
||||
.book-item-cover-img {
|
||||
width: 90px;
|
||||
height: 100px;
|
||||
background: linear-gradient(
|
||||
197deg,
|
||||
rgba(45, 162, 255, 1) 0%,
|
||||
rgba(105, 235, 222, 1) 100%
|
||||
);
|
||||
margin-left: 15px;
|
||||
opacity: 1;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
}
|
||||
.book-item-cover-title {
|
||||
height: 30px;
|
||||
font-size: 8px;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
float: left;
|
||||
font-size: 14px;
|
||||
height: 15px;
|
||||
|
||||
line-height: 30px;
|
||||
color: black;
|
||||
opacity: 1;
|
||||
width: 150px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
position: absolute;
|
||||
top: 115px;
|
||||
left: 15px;
|
||||
font-weight: 600;
|
||||
width: 106px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
@@ -4,7 +4,7 @@ import "./imageViewer.css";
|
||||
import { ImageViewerProps, ImageViewerStates } from "./interface";
|
||||
import StyleUtil from "../../utils/styleUtil";
|
||||
import FileSaver from "file-saver";
|
||||
import { withNamespaces } from "react-i18next";
|
||||
|
||||
const isElectron = require("is-electron");
|
||||
|
||||
declare var window: any;
|
||||
@@ -202,4 +202,4 @@ class ImageViewer extends React.Component<ImageViewerProps, ImageViewerStates> {
|
||||
}
|
||||
}
|
||||
|
||||
export default withNamespaces()(ImageViewer as any);
|
||||
export default ImageViewer;
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
import { connect } from "react-redux";
|
||||
import { stateType } from "../../store";
|
||||
import ImageViewer from "./component";
|
||||
|
||||
import { withNamespaces } from "react-i18next";
|
||||
const mapStateToProps = (state: stateType) => {
|
||||
return {};
|
||||
};
|
||||
const actionCreator = {};
|
||||
|
||||
export default connect(mapStateToProps, actionCreator)(ImageViewer);
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
actionCreator
|
||||
)(withNamespaces()(ImageViewer as any));
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useEffect } from "react";
|
||||
import React from "react";
|
||||
import "./loadingDialog.css";
|
||||
import Lottie from "react-lottie";
|
||||
import animationData from "../../assets/loading.json";
|
||||
@@ -12,7 +12,6 @@ const defaultOptions = {
|
||||
},
|
||||
};
|
||||
const LoadingDialog = (props) => {
|
||||
useEffect(() => {}, []);
|
||||
return (
|
||||
<div className="loading-dialog">
|
||||
<div className="loading-dialog-title">
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
color: #4b4b4b;
|
||||
opacity: 1;
|
||||
margin-left: 10px;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
}
|
||||
.tag-container {
|
||||
display: inline-block;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React from "react";
|
||||
import "./searchBox.css";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
import { Trans, withNamespaces } from "react-i18next";
|
||||
import { Trans } from "react-i18next";
|
||||
import { SearchBoxProps } from "./interface";
|
||||
class SearchBox extends React.Component<SearchBoxProps> {
|
||||
componentDidMount() {
|
||||
@@ -137,4 +137,4 @@ class SearchBox extends React.Component<SearchBoxProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export default withNamespaces()(SearchBox as any);
|
||||
export default SearchBox;
|
||||
|
||||
@@ -4,7 +4,7 @@ import "./settingDialog.css";
|
||||
import { SettingInfoProps, SettingInfoState } from "./interface";
|
||||
import { Trans } from "react-i18next";
|
||||
import i18n from "../../i18n";
|
||||
import { updateLog } from "../../constants/updateLog";
|
||||
import { version } from "../../../package.json";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
const isElectron = require("is-electron");
|
||||
|
||||
@@ -85,11 +85,7 @@ class SettingDialog extends React.Component<
|
||||
</p>
|
||||
<p className="setting-subtitle">
|
||||
<Trans>Version</Trans>
|
||||
{updateLog.version}
|
||||
</p>
|
||||
<p className="setting-subtitle">
|
||||
<Trans>Date</Trans>
|
||||
{updateLog.date}
|
||||
{version}
|
||||
</p>
|
||||
<div className="setting-close-container">
|
||||
<span
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
.setting-dialog-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
font-weight: 500;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React, { Component } from "react";
|
||||
import "./tokenDialog.css";
|
||||
import copy from "copy-text-to-clipboard";
|
||||
import { Trans, withNamespaces } from "react-i18next";
|
||||
import { Trans } from "react-i18next";
|
||||
import { TokenDialogProps, TokenDialogState } from "./interface";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
|
||||
@@ -123,4 +123,4 @@ class TokenDialog extends Component<TokenDialogProps, TokenDialogState> {
|
||||
}
|
||||
}
|
||||
|
||||
export default withNamespaces()(TokenDialog as any);
|
||||
export default TokenDialog;
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
//更新提示弹窗
|
||||
import React from "react";
|
||||
import "./updateDialog.css";
|
||||
import { UpdateInfoProps, UpdateInfoState } from "./interface";
|
||||
import { Trans } from "react-i18next";
|
||||
import { updateLog } from "../../constants/updateLog";
|
||||
|
||||
class UpdateDialog extends React.Component<UpdateInfoProps, UpdateInfoState> {
|
||||
constructor(props: UpdateInfoProps) {
|
||||
super(props);
|
||||
this.state = { downlownLink: "" };
|
||||
}
|
||||
renderList = (arr: any[]) => {
|
||||
return arr.map((item, index) => {
|
||||
return (
|
||||
<li className="update-dialog-list" key={index}>
|
||||
<span style={{ color: "black" }}>{index + 1 + ". "}</span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="update-dialog-container">
|
||||
<p className="update-dialog-title">
|
||||
<Trans>What's new about this version</Trans>
|
||||
</p>
|
||||
<p className="update-dialog-subtitle">
|
||||
<Trans>Version</Trans>
|
||||
{updateLog.version}
|
||||
</p>
|
||||
<p className="update-dialog-subtitle">
|
||||
<Trans>Date</Trans>
|
||||
{updateLog.date}
|
||||
</p>
|
||||
|
||||
<div className="update-dialog-info">
|
||||
<p className="update-dialog-new-title">
|
||||
<Trans>What's New</Trans>
|
||||
</p>
|
||||
<ul className="update-dialog-new-container">
|
||||
{this.renderList(updateLog.new)}
|
||||
</ul>
|
||||
<p className="update-dialog-fix-title">
|
||||
<Trans>What's been fixed</Trans>
|
||||
</p>
|
||||
<ul className="update-dialog-fix-container">
|
||||
{this.renderList(updateLog.fix)}
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="update-dialog-container-button"
|
||||
onClick={() => {
|
||||
this.props.handleUpdateDialog();
|
||||
}}
|
||||
>
|
||||
<Trans>Confirm</Trans>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export default UpdateDialog;
|
||||
@@ -1,5 +0,0 @@
|
||||
//左下角的图标外链
|
||||
import UpdateDialog from "./component";
|
||||
import { withNamespaces } from "react-i18next";
|
||||
|
||||
export default withNamespaces()(UpdateDialog as any);
|
||||
@@ -1,4 +0,0 @@
|
||||
export interface UpdateInfoProps {
|
||||
handleUpdateDialog: () => void;
|
||||
}
|
||||
export interface UpdateInfoState {}
|
||||
@@ -1,86 +0,0 @@
|
||||
.update-dialog-container {
|
||||
width: 346px;
|
||||
height: 480px;
|
||||
position: absolute;
|
||||
left: calc(50% - 173px);
|
||||
top: calc(50% - 240px);
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.34);
|
||||
opacity: 1;
|
||||
z-index: 20;
|
||||
animation: popup 0.1s ease-in-out 0s 1;
|
||||
}
|
||||
.update-dialog-title {
|
||||
font-size: 20px;
|
||||
font-weight: 600;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
margin: 20px 0px 10px;
|
||||
text-align: center;
|
||||
width: 346px;
|
||||
}
|
||||
.update-dialog-new-title,
|
||||
.update-dialog-fix-title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
margin-top: 10px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.update-dialog-list {
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
color: rgba(149, 149, 149, 1);
|
||||
opacity: 1;
|
||||
margin: 7px;
|
||||
}
|
||||
.update-dialog-new-container,
|
||||
.update-dialog-fix-container {
|
||||
margin: 20px 30px;
|
||||
}
|
||||
.update-dialog-info {
|
||||
margin-top: 10px;
|
||||
height: 330px;
|
||||
overflow-y: scroll;
|
||||
width: 346px;
|
||||
}
|
||||
.update-dialog-illustration {
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
z-index: 20;
|
||||
}
|
||||
.update-dialog-container-button {
|
||||
width: 75px;
|
||||
height: 32px;
|
||||
background: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
margin: 12px 130px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
z-index: 25;
|
||||
}
|
||||
.update-dialog-url {
|
||||
width: 200px;
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
left: 10px;
|
||||
user-select: text;
|
||||
z-index: 30;
|
||||
line-height: 16px;
|
||||
}
|
||||
.update-dialog-subtitle {
|
||||
font-size: 13px;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
}
|
||||
@@ -2,27 +2,46 @@
|
||||
import React from "react";
|
||||
import "./updateInfo.css";
|
||||
import { UpdateInfoProps, UpdateInfoState } from "./interface";
|
||||
import { updateLog } from "../../constants/updateLog";
|
||||
import { version } from "../../../package.json";
|
||||
import { Trans } from "react-i18next";
|
||||
import axios from "axios";
|
||||
import Lottie from "react-lottie";
|
||||
import animationData from "../../assets/new.json";
|
||||
import copy from "copy-text-to-clipboard";
|
||||
const isElectron = require("is-electron");
|
||||
const defaultOptions = {
|
||||
loop: false,
|
||||
autoplay: true,
|
||||
animationData: animationData,
|
||||
rendererSettings: {
|
||||
preserveAspectRatio: "xMidYMid slice",
|
||||
},
|
||||
};
|
||||
|
||||
declare var window: any;
|
||||
|
||||
class UpdateInfo extends React.Component<UpdateInfoProps, UpdateInfoState> {
|
||||
constructor(props: UpdateInfoProps) {
|
||||
super(props);
|
||||
this.state = { downlownLink: "" };
|
||||
this.state = {
|
||||
downlownLink: "",
|
||||
updateLog: "",
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
console.log(this.state.updateLog, "this.state.updateLog");
|
||||
!this.props.currentBook.key &&
|
||||
axios
|
||||
.get("https://koodo.960960.xyz/api/update")
|
||||
.then((res) => {
|
||||
console.log(res);
|
||||
const download = res.data.download;
|
||||
const version = res.data.log.version;
|
||||
if (this.compareVersion(updateLog.version, version)) {
|
||||
const newVersion = res.data.log.version;
|
||||
|
||||
if (version !== newVersion) {
|
||||
this.setState({ updateLog: res.data.log });
|
||||
this.props.handleNewDialog(true);
|
||||
|
||||
navigator.platform.indexOf("Linux") > -1
|
||||
? this.setState({ downlownLink: download[2].url })
|
||||
: navigator.platform.indexOf("Mac") > -1
|
||||
@@ -34,33 +53,88 @@ class UpdateInfo extends React.Component<UpdateInfoProps, UpdateInfoState> {
|
||||
console.log(err);
|
||||
});
|
||||
}
|
||||
|
||||
renderList = (arr: any[]) => {
|
||||
return arr.map((item, index) => {
|
||||
return (
|
||||
<li className="update-dialog-list" key={index}>
|
||||
<span style={{ color: "black" }}>{index + 1 + ". "}</span>
|
||||
<span>{item}</span>
|
||||
</li>
|
||||
);
|
||||
});
|
||||
};
|
||||
handleJump = () => {
|
||||
isElectron() &&
|
||||
window.require("electron").shell.openExternal(this.state.downlownLink);
|
||||
};
|
||||
compareVersion = (ver1: string, ver2: string) => {
|
||||
const ver1Arr = ver1.split(".");
|
||||
const ver2Arr = ver2.split(".");
|
||||
|
||||
for (let i = 0; i < ver1Arr.length; i++) {
|
||||
if (parseInt(ver1Arr[i]) < parseInt(ver2Arr[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
handleClose = () => {
|
||||
this.setState({ updateLog: "" });
|
||||
this.props.handleNewDialog(false);
|
||||
};
|
||||
render() {
|
||||
return (
|
||||
<div
|
||||
className="update-info-container"
|
||||
style={this.state.downlownLink ? {} : { display: "none" }}
|
||||
onClick={() => {
|
||||
this.handleJump();
|
||||
}}
|
||||
>
|
||||
<Trans>New Version Available</Trans>
|
||||
</div>
|
||||
<>
|
||||
<div
|
||||
className="update-info-container"
|
||||
style={this.state.downlownLink ? {} : { display: "none" }}
|
||||
onClick={() => {
|
||||
this.handleJump();
|
||||
}}
|
||||
>
|
||||
<Trans>New Version Available</Trans>
|
||||
</div>
|
||||
{this.state.updateLog && (
|
||||
<div className="new-version">
|
||||
<div className="new-version-title">
|
||||
<Trans>New Version Available</Trans>
|
||||
</div>
|
||||
<div className="setting-close-container">
|
||||
<span
|
||||
className="icon-close setting-close"
|
||||
onClick={() => {
|
||||
this.handleClose();
|
||||
}}
|
||||
></span>
|
||||
</div>
|
||||
<div className="update-dialog-info" style={{ height: 420 }}>
|
||||
<div className="new-version-animation">
|
||||
<Lottie options={defaultOptions} height={240} width={240} />
|
||||
</div>
|
||||
<div
|
||||
className="new-version-open"
|
||||
onClick={() => {
|
||||
this.handleJump();
|
||||
}}
|
||||
>
|
||||
<Trans>Open link in browser</Trans>
|
||||
</div>
|
||||
<div
|
||||
className="new-version-copy"
|
||||
onClick={() => {
|
||||
copy(this.state.downlownLink);
|
||||
this.props.handleMessage("Copy Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
}}
|
||||
>
|
||||
<Trans>Copy Link</Trans>
|
||||
</div>
|
||||
|
||||
<p className="update-dialog-new-title">
|
||||
<Trans>What's New</Trans>
|
||||
</p>
|
||||
<ul className="update-dialog-new-container">
|
||||
{this.renderList(this.state.updateLog.new)}
|
||||
</ul>
|
||||
<p className="update-dialog-fix-title">
|
||||
<Trans>What's been fixed</Trans>
|
||||
</p>
|
||||
<ul className="update-dialog-fix-container">
|
||||
{this.renderList(this.state.updateLog.fix)}
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
//左下角的图标外链
|
||||
import { connect } from "react-redux";
|
||||
import { handleMessageBox, handleMessage } from "../../store/actions/manager";
|
||||
import {
|
||||
handleMessageBox,
|
||||
handleMessage,
|
||||
handleNewDialog,
|
||||
} from "../../store/actions/manager";
|
||||
import UpdateInfo from "./component";
|
||||
import { withNamespaces } from "react-i18next";
|
||||
import { stateType } from "../../store";
|
||||
@@ -14,6 +18,7 @@ const mapStateToProps = (state: stateType) => {
|
||||
const actionCreator = {
|
||||
handleMessageBox,
|
||||
handleMessage,
|
||||
handleNewDialog,
|
||||
};
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
|
||||
@@ -4,7 +4,9 @@ export interface UpdateInfoProps {
|
||||
books: BookModel[];
|
||||
handleMessage: (message: string) => void;
|
||||
handleMessageBox: (isShow: boolean) => void;
|
||||
handleNewDialog: (isShowNew: boolean) => void;
|
||||
}
|
||||
export interface UpdateInfoState {
|
||||
downlownLink: string;
|
||||
updateLog: any;
|
||||
}
|
||||
|
||||
@@ -3,10 +3,121 @@
|
||||
height: 50px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
position: relative;
|
||||
left: 380px;
|
||||
position: absolute;
|
||||
left: 590px;
|
||||
top: 18px;
|
||||
color: blue;
|
||||
cursor: pointer;
|
||||
/* bottom: 120px; */
|
||||
}
|
||||
.new-version {
|
||||
width: 346px;
|
||||
height: 480px;
|
||||
position: absolute;
|
||||
left: calc(50% - 173px);
|
||||
top: calc(50% - 240px);
|
||||
overflow: hidden;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.34);
|
||||
opacity: 1;
|
||||
z-index: 20;
|
||||
animation: popup 0.1s ease-in-out 0s 1;
|
||||
}
|
||||
.new-version-title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
margin: 20px 0px 10px;
|
||||
text-align: center;
|
||||
width: 346px;
|
||||
}
|
||||
.new-version-open {
|
||||
margin-left: 100px;
|
||||
margin-top: -10px;
|
||||
width: 138px;
|
||||
padding: 0px 10px;
|
||||
height: 42px;
|
||||
background: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
border-radius: 25px;
|
||||
line-height: 42px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
z-index: 50;
|
||||
transition: 0.1s;
|
||||
}
|
||||
.new-version-copy {
|
||||
margin-left: 142px;
|
||||
margin-top: 5px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
cursor: pointer;
|
||||
font-size: 17px;
|
||||
font-weight: 500;
|
||||
line-height: 25px;
|
||||
}
|
||||
.update-dialog-new-title,
|
||||
.update-dialog-fix-title {
|
||||
font-size: 20px;
|
||||
font-weight: 500;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
margin-top: 10px;
|
||||
margin-left: 20px;
|
||||
}
|
||||
.update-dialog-list {
|
||||
font-size: 16px;
|
||||
line-height: 18px;
|
||||
color: rgba(149, 149, 149, 1);
|
||||
opacity: 1;
|
||||
margin: 7px;
|
||||
}
|
||||
.update-dialog-new-container,
|
||||
.update-dialog-fix-container {
|
||||
margin: 20px 30px;
|
||||
}
|
||||
.update-dialog-info {
|
||||
margin-top: 10px;
|
||||
height: 330px;
|
||||
overflow-y: scroll;
|
||||
width: 346px;
|
||||
}
|
||||
.update-dialog-illustration {
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
bottom: 0px;
|
||||
right: 0px;
|
||||
z-index: 20;
|
||||
}
|
||||
.update-dialog-container-button {
|
||||
width: 75px;
|
||||
height: 32px;
|
||||
background: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
line-height: 32px;
|
||||
text-align: center;
|
||||
color: white;
|
||||
margin: 12px 130px;
|
||||
position: absolute;
|
||||
cursor: pointer;
|
||||
z-index: 25;
|
||||
}
|
||||
.update-dialog-url {
|
||||
width: 200px;
|
||||
font-size: 14px;
|
||||
position: absolute;
|
||||
bottom: 6px;
|
||||
left: 10px;
|
||||
user-select: text;
|
||||
z-index: 30;
|
||||
line-height: 16px;
|
||||
}
|
||||
.update-dialog-subtitle {
|
||||
font-size: 13px;
|
||||
margin: 5px;
|
||||
text-align: center;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
}
|
||||
|
||||
@@ -85,6 +85,7 @@ class BackupDialog extends React.Component<
|
||||
case 3:
|
||||
if (!isElectron()) {
|
||||
this.showMessage("Only Desktop support this service");
|
||||
break;
|
||||
}
|
||||
if (!OtherUtil.getReaderConfig("webdav_token")) {
|
||||
this.props.handleTokenDialog(true);
|
||||
|
||||
@@ -111,7 +111,7 @@
|
||||
text-decoration: underline;
|
||||
width: 200px;
|
||||
position: absolute;
|
||||
left: 530px;
|
||||
left: 690px;
|
||||
top: 29px;
|
||||
cursor: pointer;
|
||||
color: blue;
|
||||
|
||||
@@ -13,8 +13,6 @@ import { ManagerProps, ManagerState } from "./interface";
|
||||
import { Trans } from "react-i18next";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
import AddFavorite from "../../utils/addFavorite";
|
||||
import { updateLog } from "../../constants/updateLog";
|
||||
import UpdateDialog from "../../components/updataDialog";
|
||||
import SettingDialog from "../../components/settingDialog";
|
||||
import { isMobileOnly } from "react-device-detect";
|
||||
import { Route, Switch, Redirect } from "react-router-dom";
|
||||
@@ -82,19 +80,13 @@ class Manager extends React.Component<ManagerProps, ManagerState> {
|
||||
}
|
||||
componentDidMount() {
|
||||
setTimeout(() => {
|
||||
this.setState({
|
||||
isUpdated: OtherUtil.getReaderConfig("version") !== updateLog.version,
|
||||
});
|
||||
this.props.handleFirst(OtherUtil.getReaderConfig("isFirst") || "yes");
|
||||
}, 1000);
|
||||
if (is_touch_device() && !OtherUtil.getReaderConfig("isTouch")) {
|
||||
OtherUtil.setReaderConfig("isTouch", "yes");
|
||||
}
|
||||
}
|
||||
handleUpdateDialog = () => {
|
||||
this.setState({ isUpdated: false });
|
||||
OtherUtil.setReaderConfig("version", updateLog.version);
|
||||
};
|
||||
|
||||
handleDrag = (isDrag: boolean) => {
|
||||
this.setState({ isDrag });
|
||||
};
|
||||
@@ -104,9 +96,6 @@ class Manager extends React.Component<ManagerProps, ManagerState> {
|
||||
|
||||
render() {
|
||||
let { books } = this.props;
|
||||
const updateDialogProps = {
|
||||
handleUpdateDialog: this.handleUpdateDialog,
|
||||
};
|
||||
if (isMobileOnly) {
|
||||
return (
|
||||
<>
|
||||
@@ -159,12 +148,12 @@ class Manager extends React.Component<ManagerProps, ManagerState> {
|
||||
{this.props.isShowLoading && <LoadingDialog />}
|
||||
{(this.props.isSettingOpen ||
|
||||
this.props.isBackup ||
|
||||
this.props.isShowNew ||
|
||||
this.props.isOpenDeleteDialog ||
|
||||
this.props.isOpenEditDialog ||
|
||||
this.props.isOpenAddDialog ||
|
||||
this.props.isShowLoading ||
|
||||
this.props.isFirst === "yes" ||
|
||||
(this.state.isUpdated && this.props.isFirst === "no")) && (
|
||||
this.props.isFirst === "yes") && (
|
||||
<div className="drag-background"></div>
|
||||
)}
|
||||
|
||||
@@ -172,9 +161,6 @@ class Manager extends React.Component<ManagerProps, ManagerState> {
|
||||
{this.props.isSortDisplay && <SortDialog />}
|
||||
{this.props.isBackup && <BackupDialog />}
|
||||
{this.props.isFirst === "yes" && <WelcomeDialog />}
|
||||
{this.state.isUpdated && this.props.isFirst === "no" && (
|
||||
<UpdateDialog {...updateDialogProps} />
|
||||
)}
|
||||
{this.props.isSettingOpen && <SettingDialog />}
|
||||
{(!books || books.length === 0) && this.state.totalBooks ? (
|
||||
<Redirect to="/manager/loading" />
|
||||
|
||||
@@ -31,6 +31,7 @@ const mapStateToProps = (state: stateType) => {
|
||||
isBookSort: state.manager.isBookSort,
|
||||
isSortDisplay: state.manager.isSortDisplay,
|
||||
isShowLoading: state.manager.isShowLoading,
|
||||
isShowNew: state.manager.isShowNew,
|
||||
isMessage: state.manager.isMessage,
|
||||
isBackup: state.backupPage.isBackup,
|
||||
isFirst: state.manager.isFirst,
|
||||
|
||||
@@ -20,6 +20,7 @@ export interface ManagerProps extends RouteComponentProps<any> {
|
||||
isBackup: boolean;
|
||||
isSettingOpen: boolean;
|
||||
isShowLoading: boolean;
|
||||
isShowNew: boolean;
|
||||
dragItem: string;
|
||||
handleFetchBooks: () => void;
|
||||
handleFetchNotes: () => void;
|
||||
|
||||
@@ -41,6 +41,9 @@ export function handleSortDisplay(isSortDisplay: boolean) {
|
||||
export function handleLoadingDialog(isShowLoading: boolean) {
|
||||
return { type: "HANDLE_SHOW_LOADING", payload: isShowLoading };
|
||||
}
|
||||
export function handleNewDialog(isShowNew: boolean) {
|
||||
return { type: "HANDLE_SHOW_NEW", payload: isShowNew };
|
||||
}
|
||||
export function handleBookSort(isBookSort: boolean) {
|
||||
return { type: "HANDLE_BOOK_SORT", payload: isBookSort };
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ export type stateType = {
|
||||
isList: string;
|
||||
isSortDisplay: boolean;
|
||||
isShowLoading: boolean;
|
||||
isShowNew: boolean;
|
||||
bookSortCode: { sort: number; order: number };
|
||||
noteSortCode: { sort: number; order: number };
|
||||
isMessage: boolean;
|
||||
|
||||
@@ -11,6 +11,7 @@ const initState = {
|
||||
isList: "card",
|
||||
isSortDisplay: false,
|
||||
isShowLoading: false,
|
||||
isShowNew: false,
|
||||
bookSortCode: { sort: 0, order: 1 },
|
||||
noteSortCode: OtherUtil.getNoteSortCode(),
|
||||
isMessage: false,
|
||||
@@ -76,6 +77,11 @@ export function manager(
|
||||
...state,
|
||||
isShowLoading: action.payload,
|
||||
};
|
||||
case "HANDLE_SHOW_NEW":
|
||||
return {
|
||||
...state,
|
||||
isShowNew: action.payload,
|
||||
};
|
||||
case "HANDLE_MESSAGE":
|
||||
return {
|
||||
...state,
|
||||
|
||||
Reference in New Issue
Block a user