Update to 1.2.0
Former-commit-id: 9e1d3f0fa36a28da2bfb0de2532737d41290ce89
12
README.md
@@ -80,12 +80,18 @@
|
||||
|
||||
## 使用方法
|
||||
|
||||
桌面端:前往这里下载最新的安装包(技术原因暂不支持 Windows7 系统) [点我前往](https://koodo.960960.xyz/download)
|
||||
桌面端:前往这里下载最新的安装包(暂不支持 Windows 7 系统) [点我前往](https://koodo.960960.xyz/download)
|
||||
|
||||
(国内网络下载速度慢的解决办法,复制下载链接到这个网站:https://d.serctl.com/ )
|
||||
|
||||
网页版:代码托管在 Vercel [点我前往](https://reader.960960.xyz)
|
||||
|
||||
[Homebrew](https://brew.sh/):
|
||||
|
||||
```shell
|
||||
brew install --cask koodo-reader
|
||||
```
|
||||
|
||||
## 运行源码
|
||||
|
||||
请确保您电脑的 node 的版本大于 10.0.0,已配置好 yarn,git 的运行环境。
|
||||
@@ -112,8 +118,8 @@
|
||||
|
||||
## 后续更新
|
||||
|
||||
我会根据大家的反馈不定时更新,当有新版本更新时,Github 会自动向您的客户端推送提醒
|
||||
我会根据大家的反馈不定时更新,当有新版本更新时,您将自动收到更新提示
|
||||
|
||||
## 帮助
|
||||
|
||||
您可以在 issue 区提问,或者通过邮箱 guo362429@gmail.com 与我取得联系
|
||||
您可以在[issue](https://github.com/troyeguo/koodo-reader/issues)提问,或者前往[这里]("https://koodo.960960.xyz/support")了解更多。
|
||||
|
||||
10
README_en.md
@@ -80,7 +80,7 @@
|
||||
|
||||
## Usage
|
||||
|
||||
Desktop : Download the latest software package(Windows7 is not supported yet) [Click me](https://koodo.960960.xyz/download)
|
||||
Desktop : Download the latest software package(Windows 7 is not supported yet) [Click me](https://koodo.960960.xyz/download)
|
||||
|
||||
Install with [Homebrew](https://brew.sh/):
|
||||
|
||||
@@ -100,14 +100,14 @@ Make sure node's version on your computer is larger than 10.0.0, yarn and git is
|
||||
git clone https://github.com/troyeguo/koodo-reader.git
|
||||
```
|
||||
|
||||
2. Enter desktop version
|
||||
2. Enter desktop mode
|
||||
|
||||
```
|
||||
yarn
|
||||
yarn dev
|
||||
```
|
||||
|
||||
3. Enter web version
|
||||
3. Enter web mode
|
||||
|
||||
```
|
||||
yarn
|
||||
@@ -116,8 +116,8 @@ Make sure node's version on your computer is larger than 10.0.0, yarn and git is
|
||||
|
||||
## Update
|
||||
|
||||
Whenever there is a update, a short message will show up in the software's header
|
||||
When an update is available, you will receive a notification when you open the software.
|
||||
|
||||
## Help
|
||||
|
||||
Click [here](https://github.com/troyeguo/koodo-reader/issues) to report your issue, or contact me with guo362429@gmail.com
|
||||
Click [here](https://github.com/troyeguo/koodo-reader/issues) to report your issue, or visit https://koodo.960960.xyz/support for help.
|
||||
|
||||
@@ -34,7 +34,7 @@
|
||||
}
|
||||
.launching {
|
||||
font-size: 19px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
line-height: 32px;
|
||||
color: #000000;
|
||||
margin-left: 10px;
|
||||
|
||||
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 266 KiB |
4
main.js
@@ -83,8 +83,8 @@ app.on("ready", () => {
|
||||
} else {
|
||||
dialog.showMessageBox({
|
||||
type: "warning",
|
||||
title: "Port is in use",
|
||||
message: "Please don't open multiple software at the same time",
|
||||
title: "Warning",
|
||||
message: "Another Koodo Reader is already running",
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "koodo-reader",
|
||||
"main": "main.js",
|
||||
"version": "1.1.9",
|
||||
"version": "1.2.0",
|
||||
"description": "A cross-platform open source Epub reader ",
|
||||
"author": {
|
||||
"name": "App by Troye",
|
||||
|
||||
83
public/assets/_empty.svg
Normal file
@@ -0,0 +1,83 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="987.234" height="565.416" viewBox="0 0 987.234 565.416">
|
||||
<defs>
|
||||
<linearGradient id="linear-gradient" x1="0.43" y1="0.005" x2="0.43" y2="0.577" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#dae0e6"/>
|
||||
<stop offset="1" stop-color="#eff1f3"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-2" x1="0.5" y1="1.739" x2="0.038" y2="-0.34" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#536db5" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#0e284b" stop-opacity="0.212"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-3" x1="1.146" y1="1" x2="0.038" y2="-0.34" xlink:href="#linear-gradient-2"/>
|
||||
</defs>
|
||||
<g id="组_664" data-name="组 664" transform="translate(-295.755 -235)">
|
||||
<path id="Rectangle_Copy" data-name="Rectangle Copy" d="M924.7,139.541s5.11,66.414,0,195.94c-54.321,0-473.383,1.025-757.763,0-130.459.181-114.97.147-172,0s-55.024.014-55.2,0c34-94.858,111.065-117.526,141.341-136.925,37.1-23.772,186.425-66.258,276.359-88.634S458.856,26.1,570.367,3.674C663.653-15.09,720.693,41.121,859,101.9,914.256,126.178,924.7,139.541,924.7,139.541Z" transform="translate(356.019 464.479)" opacity="0.61" fill="url(#linear-gradient)"/>
|
||||
<g id="shadow" transform="translate(1382.42 711.827) rotate(180)">
|
||||
<path id="shadow-2" data-name="shadow" d="M0,17.362l166.231,9.463V2.158L11.279,7.283Z" transform="translate(268.27 26.847) rotate(180)" fill="url(#linear-gradient-2)" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<path id="shadow-3" data-name="shadow" d="M0,17.362l165.85,9.485V2.158L6.973,7.283Z" transform="translate(268.27 26.847) rotate(180)" fill="rgba(216,216,216,0.08)" style="mix-blend-mode: darken;isolation: isolate"/>
|
||||
</g>
|
||||
<g id="shadow-4" data-name="shadow" transform="translate(1068.709 696.823) rotate(180)">
|
||||
<ellipse id="shadow-5" data-name="shadow" cx="28.937" cy="3.472" rx="28.937" ry="3.472" transform="translate(57.875 6.944) rotate(180)" fill="url(#linear-gradient-3)" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<ellipse id="shadow-6" data-name="shadow" cx="28.937" cy="3.472" rx="28.937" ry="3.472" transform="translate(57.875 6.944) rotate(180)" fill="rgba(216,216,216,0.08)" style="mix-blend-mode: darken;isolation: isolate"/>
|
||||
</g>
|
||||
<path id="Path_39" data-name="Path 39" d="M14.468,6.443a37.827,37.827,0,0,1,4.573,24.593c-2.287,13.934-2,34.451-2,34.451H9.461L0,3.373S10.745-.688,14.468.1,14.468,6.443,14.468,6.443Z" transform="translate(1179.929 626.963)" fill="#9ea4b8"/>
|
||||
<path id="Path_39_Copy" data-name="Path 39 Copy" d="M14.468,11.386a37.827,37.827,0,0,1,4.573,24.593c-2.287,13.934-2,34.451-2,34.451H9.461L0,8.316,17.552,0Z" transform="translate(1142.736 620.824) rotate(13)" fill="#9ea4b8"/>
|
||||
<path id="Rectangle_17" data-name="Rectangle 17" d="M27.444,2.8,18.17,0,11.934,2.8l-8.779.914a3.472,3.472,0,0,0-2.979,2.5h0a4.6,4.6,0,0,0,4.409,5.845H22.814a4.629,4.629,0,0,0,4.629-4.629Z" transform="translate(1169.747 689.395)" fill="#302c48"/>
|
||||
<path id="Rectangle_17_Copy" data-name="Rectangle 17 Copy" d="M27.444,2.8,18.17,0,11.934,2.8l-8.779.914a3.472,3.472,0,0,0-2.979,2.5h0a4.6,4.6,0,0,0,4.409,5.845H22.814a4.629,4.629,0,0,0,4.629-4.629Z" transform="translate(1116.502 689.395)" fill="#302c48"/>
|
||||
<path id="Path_31" data-name="Path 31" d="M62.628,62.167V0H7.125L0,62.167H25.335l7.8-32.008,5.5,32.008Z" transform="translate(1136.878 570.678)" fill="#302c48"/>
|
||||
<path id="Path_32" data-name="Path 32" d="M0,70.14C12.567,58.262,12.871,58.6,18.387,51.149c2.633-3.558,5.661-6.342,5.5-6.761C21.431,38.182,12.983,31.253,0,14.494L7.807,0C26.758,18.166,32.49,31.727,35.371,39.02c.7,1.767,1.927,4.976,1.613,7.052C35.6,55.212,23.25,65.773.853,77.662Z" transform="matrix(0.995, -0.105, 0.105, 0.995, 1190.725, 483.355)" fill="#9ea4b8"/>
|
||||
<g id="single_thread" data-name="single thread" transform="translate(1097.346 686.539) rotate(180)">
|
||||
<path id="Path_36" data-name="Path 36" d="M11.153,12.624S3.6,3.525,2.906.532C1.254-1.41,0,2.587,0,2.587S4.581,21.959,9.147,25.046s4.565,0,4.565,0Z" transform="translate(26.883 208.789) rotate(180)" fill="#9ea4b8"/>
|
||||
<path id="Path_37" data-name="Path 37" d="M6.567,205.841c-13.143-18.431-7.175-55.829,23.5-93.621S92.989,33.876,54.24,8.415C42.018.384,20.284-4.075,3.095,5.149" transform="translate(72.016 205.841) rotate(180)" fill="none" stroke="#cdd4e0" stroke-miterlimit="10" stroke-width="1.8"/>
|
||||
<path id="Path_35" data-name="Path 35" d="M3.706,20.974c2.721.651,4.213-9.617,1.492-11.5S3.768-.343,1.467.012.289,3.411.177,5.584.985,20.323,3.706,20.974Z" transform="translate(17.095 202.544) rotate(180)" fill="#9ea4b8"/>
|
||||
</g>
|
||||
<path id="Path_32_Copy" data-name="Path 32 Copy" d="M0,70.14C12.567,58.262,12.871,58.6,18.387,51.149c2.633-3.558,5.661-6.342,5.5-6.761C21.431,38.182,12.983,31.253,0,14.494L7.807,0C26.758,18.166,32.49,31.727,35.371,39.02,39.143,48.57,28.336,63.074.853,77.662Z" transform="translate(1156.074 491.021) rotate(82)" fill="#9ea4b8"/>
|
||||
<path id="Path_33" data-name="Path 33" d="M11.692,0S11.939,4.47,8.8,6.959C5.3,9.737,1.384,12.948.48,14.1-1.234,16.27,2.194,16.27,2.194,16.27L.48,30.311l14.26,6.381L11.692,48.578H28.776l2.151-11.887s-4.973-22.321-8.106-28.3C18.576.3,11.692,0,11.692,0Z" transform="translate(1157.71 429.263)" fill="#9ea4b8"/>
|
||||
<path id="Oval_8" data-name="Oval 8" d="M15.756,49.185c-7.26,0-8.271-8.555-12.515-14.11C.011,30.847,0,27.269,0,21.4,0,7.818,2.971,0,15.756,0s23.15,11.01,23.15,24.592S23.8,43.24,15.756,49.185Z" transform="translate(1171.017 417.337)" fill="#302c48"/>
|
||||
<ellipse id="Oval" cx="8.102" cy="7.522" rx="8.102" ry="7.522" transform="translate(1172.883 414.444)" fill="#302c48"/>
|
||||
<ellipse id="Oval_Copy" data-name="Oval Copy" cx="5.209" cy="4.836" rx="5.209" ry="4.836" transform="translate(1184.458 414.444)" fill="#302c48"/>
|
||||
<ellipse id="Oval_Copy_2" data-name="Oval Copy 2" cx="8.102" cy="7.522" rx="8.102" ry="7.522" transform="translate(1190.246 419.073)" fill="#302c48"/>
|
||||
<ellipse id="Oval_Copy_6" data-name="Oval Copy 6" cx="8.102" cy="7.522" rx="8.102" ry="7.522" transform="translate(1194.876 427.174)" fill="#302c48"/>
|
||||
<ellipse id="Oval_Copy_3" data-name="Oval Copy 3" cx="4.051" cy="3.761" rx="4.051" ry="3.761" transform="translate(1192.561 416.758)" fill="#302c48"/>
|
||||
<ellipse id="Oval_Copy_4" data-name="Oval Copy 4" cx="4.051" cy="3.761" rx="4.051" ry="3.761" transform="translate(1169.411 419.073)" fill="#302c48"/>
|
||||
<ellipse id="Oval_Copy_5" data-name="Oval Copy 5" cx="4.051" cy="3.761" rx="4.051" ry="3.761" transform="translate(1167.096 424.859)" fill="#302c48"/>
|
||||
<ellipse id="Oval_2" data-name="Oval 2" cx="4.63" cy="5.208" rx="4.63" ry="5.208" transform="translate(1167.096 442.219)" fill="#9ea4b8"/>
|
||||
<path id="Path_30" data-name="Path 30" d="M92.413,27.082,67.785,4.247S55.934,0,48.224,0h-11.4C32,0,18.195,4.247,18.195,4.247L0,27.082l11.549,16.4,12.633-16.4-14.09,78.261s14.3,4.767,26.736,4.767,30.957-4.629,30.957-4.629V32.657l9.1,10.82Z" transform="translate(1132.132 474.623)" fill="#fcfcfc"/>
|
||||
<path id="Path_34" data-name="Path 34" d="M5.431,44.328,4.061,0,0,12.311Z" transform="translate(1170.112 588.604)" fill="#3b3c45" opacity="0.195" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<path id="Path_38" data-name="Path 38" d="M0,50.671,14.863,0s-6.1,1.908-6.442,4.355S0,50.671,0,50.671Z" transform="translate(1147.833 497.706)" fill="#deeaf4" opacity="0.55" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<g id="Thread" transform="translate(1046.717 694.508) rotate(180)">
|
||||
<ellipse id="Oval_9_Copy" data-name="Oval 9 Copy" cx="4.051" cy="10.416" rx="4.051" ry="10.416" transform="translate(33.567 21.989) rotate(180)" fill="#302c48"/>
|
||||
<rect id="Rectangle" width="25.465" height="15.045" transform="translate(28.937 18.517) rotate(180)" fill="#302c48"/>
|
||||
<path id="Rectangle_Copy-2" data-name="Rectangle Copy" d="M12.732,0H2.315S0,2.487,0,7.416a12.284,12.284,0,0,0,2.315,7.629H12.732a14.017,14.017,0,0,1-2.315-7.2A17.951,17.951,0,0,1,12.732,0Z" transform="translate(24.307 18.517) rotate(180)" fill="#fff"/>
|
||||
<ellipse id="Oval_9" data-name="Oval 9" cx="4.051" cy="11.573" rx="4.051" ry="11.573" transform="translate(8.102 23.146) rotate(180)" fill="#686b89"/>
|
||||
</g>
|
||||
<g id="Kite" transform="translate(993.463 393.948) rotate(180)">
|
||||
<g id="Group_6" data-name="Group 6" transform="matrix(0.883, -0.469, 0.469, 0.883, 56.551, 113.53)">
|
||||
<path id="Combined_Shape" data-name="Combined Shape" d="M0,0V24.41H16.529Z" transform="translate(16.529 51.438) rotate(180)" fill="#52556e"/>
|
||||
<path id="Rectangle_18_Copy" data-name="Rectangle 18 Copy" d="M16.529,0V24.41H0Z" transform="translate(35.281 51.438) rotate(180)" fill="#9ea4b8"/>
|
||||
<path id="Rectangle_18_Copy_3" data-name="Rectangle 18 Copy 3" d="M16.529,0V24.41H0Z" transform="translate(0 0)" fill="#9ea4b8"/>
|
||||
<path id="Rectangle_18_Copy_2" data-name="Rectangle 18 Copy 2" d="M0,0V24.41H16.529Z" transform="translate(18.752 0)" fill="#52556e"/>
|
||||
</g>
|
||||
<g id="Group_9" data-name="Group 9" transform="translate(56.359 129.838)">
|
||||
<path id="Triangle_2" data-name="Triangle 2" d="M3.646,0,0,9.356H7.293Z" transform="translate(7.181 5.062) rotate(25)" fill="#52556e"/>
|
||||
<path id="Triangle_2_Copy_7" data-name="Triangle 2 Copy 7" d="M3.646,0,7.293,9.356H0Z" transform="translate(10.757 2.105) rotate(103)" fill="#9ea4b8"/>
|
||||
</g>
|
||||
<g id="Group_8" data-name="Group 8" transform="matrix(-1, 0.017, -0.017, -1, 111.023, 125.412)">
|
||||
<path id="Triangle_2_Copy_9" data-name="Triangle 2 Copy 9" d="M3.646,0,0,9.356H7.293Z" transform="translate(7.181 5.062) rotate(25)" fill="#52556e"/>
|
||||
<path id="Triangle_2_Copy_8" data-name="Triangle 2 Copy 8" d="M3.646,0,7.293,9.356H0Z" transform="translate(10.757 2.105) rotate(103)" fill="#9ea4b8"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(61.224 0)">
|
||||
<path id="Path_41" data-name="Path 41" stroke="#fff" d="M30.055,0c0,3.984,9.7,21.376-15.555,43.447s-12.37,50.917,0,60.569" fill="none" transform="translate(40.847 104.016) rotate(180)" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="3.24" opacity="0.7"/>
|
||||
<path id="Triangle_2-2" data-name="Triangle 2" d="M3.646,0,0,9.356H7.293Z" transform="matrix(-0.602, 0.799, -0.799, -0.602, 11.861, 83.405)" fill="#52556e"/>
|
||||
<path id="Triangle_2_Copy_7-2" data-name="Triangle 2 Copy 7" d="M3.646,0,7.293,9.356H0Z" transform="matrix(0.588, -0.809, 0.809, 0.588, 7.295, 87.86)" fill="#9ea4b8"/>
|
||||
<path id="Triangle_2_Copy" data-name="Triangle 2 Copy" d="M3.646,0,0,9.356H7.293Z" transform="translate(24.755 63.33) rotate(155)" fill="#9ea4b8"/>
|
||||
<path id="Triangle_2_Copy_6" data-name="Triangle 2 Copy 6" d="M3.646,0,7.293,9.356H0Z" transform="matrix(0.914, -0.407, 0.407, 0.914, 18.411, 66.157)" fill="#52556e"/>
|
||||
<path id="Triangle_2_Copy_2" data-name="Triangle 2 Copy 2" d="M3.646,0,0,9.356H7.293Z" transform="translate(40.715 37.911) rotate(109)" fill="#52556e"/>
|
||||
<path id="Triangle_2_Copy_5" data-name="Triangle 2 Copy 5" d="M3.646,0,7.293,9.356H0Z" transform="matrix(0.407, -0.914, 0.914, 0.407, 37.683, 44.383)" fill="#9ea4b8"/>
|
||||
<path id="Triangle_2_Copy_3" data-name="Triangle 2 Copy 3" d="M3.646,0,0,9.356H7.293Z" transform="translate(35.635 10.22) rotate(76)" fill="#9ea4b8"/>
|
||||
<path id="Triangle_2_Copy_4" data-name="Triangle 2 Copy 4" d="M3.646,0,7.293,9.356H0Z" transform="translate(37.156 16.999) rotate(-97)" fill="#52556e"/>
|
||||
</g>
|
||||
<path id="Path_40" data-name="Path 40" d="M82.34,85.36c-15.2-.889-38.511-9.777-44.068-38.656S17.838,3.77,0,0" transform="translate(82.34 127.666) rotate(180)" fill="none" stroke="#cdd4e0" stroke-miterlimit="10" stroke-width="1.62"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 12 KiB |
@@ -1,24 +1,19 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="987.234" height="565.416" viewBox="0 0 987.234 565.416">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1371.37" height="565.416" viewBox="0 0 1371.37 565.416">
|
||||
<defs>
|
||||
<linearGradient id="linear-gradient" x1="0.43" y1="0.005" x2="0.43" y2="0.577" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#dae0e6"/>
|
||||
<stop offset="1" stop-color="#eff1f3"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-2" x1="0.5" y1="1.739" x2="0.038" y2="-0.34" gradientUnits="objectBoundingBox">
|
||||
<linearGradient id="linear-gradient-2" x1="1.146" y1="1" x2="0.038" y2="-0.34" gradientUnits="objectBoundingBox">
|
||||
<stop offset="0" stop-color="#536db5" stop-opacity="0"/>
|
||||
<stop offset="1" stop-color="#0e284b" stop-opacity="0.212"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="linear-gradient-3" x1="1.146" y1="1" x2="0.038" y2="-0.34" xlink:href="#linear-gradient-2"/>
|
||||
</defs>
|
||||
<g id="组_664" data-name="组 664" transform="translate(-295.755 -235)">
|
||||
<path id="Rectangle_Copy" data-name="Rectangle Copy" d="M924.7,139.541s5.11,66.414,0,195.94c-54.321,0-473.383,1.025-757.763,0-130.459.181-114.97.147-172,0s-55.024.014-55.2,0c34-94.858,111.065-117.526,141.341-136.925,37.1-23.772,186.425-66.258,276.359-88.634S458.856,26.1,570.367,3.674C663.653-15.09,720.693,41.121,859,101.9,914.256,126.178,924.7,139.541,924.7,139.541Z" transform="translate(356.019 464.479)" opacity="0.61" fill="url(#linear-gradient)"/>
|
||||
<g id="shadow" transform="translate(1382.42 711.827) rotate(180)">
|
||||
<path id="shadow-2" data-name="shadow" d="M0,17.362l166.231,9.463V2.158L11.279,7.283Z" transform="translate(268.27 26.847) rotate(180)" fill="url(#linear-gradient-2)" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<path id="shadow-3" data-name="shadow" d="M0,17.362l165.85,9.485V2.158L6.973,7.283Z" transform="translate(268.27 26.847) rotate(180)" fill="rgba(216,216,216,0.08)" style="mix-blend-mode: darken;isolation: isolate"/>
|
||||
</g>
|
||||
<g id="shadow-4" data-name="shadow" transform="translate(1068.709 696.823) rotate(180)">
|
||||
<ellipse id="shadow-5" data-name="shadow" cx="28.937" cy="3.472" rx="28.937" ry="3.472" transform="translate(57.875 6.944) rotate(180)" fill="url(#linear-gradient-3)" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<ellipse id="shadow-6" data-name="shadow" cx="28.937" cy="3.472" rx="28.937" ry="3.472" transform="translate(57.875 6.944) rotate(180)" fill="rgba(216,216,216,0.08)" style="mix-blend-mode: darken;isolation: isolate"/>
|
||||
<g id="组_763" data-name="组 763" transform="translate(-295.755 -235)">
|
||||
<path id="Rectangle_Copy" data-name="Rectangle Copy" d="M1311.106,335.481H924.7c-54.321,0-473.383,1.025-757.763,0-130.459.181-114.97.147-172,0s-55.024.014-55.2,0c34-94.858,111.065-117.526,141.341-136.925,37.1-23.772,186.425-66.258,276.359-88.634S458.856,26.1,570.367,3.674C663.653-15.09,760.674,41.28,889.9,132.376c106.941,77.594,154.175,95.475,273.271,129.213S1311.106,335.481,1311.106,335.481Z" transform="translate(356.019 464.479)" opacity="0.61" fill="url(#linear-gradient)"/>
|
||||
<g id="shadow" transform="translate(1068.709 696.823) rotate(180)">
|
||||
<ellipse id="shadow-2" data-name="shadow" cx="28.937" cy="3.472" rx="28.937" ry="3.472" transform="translate(57.875 6.944) rotate(180)" fill="url(#linear-gradient-2)" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<ellipse id="shadow-3" data-name="shadow" cx="28.937" cy="3.472" rx="28.937" ry="3.472" transform="translate(57.875 6.944) rotate(180)" fill="rgba(216,216,216,0.08)" style="mix-blend-mode: darken;isolation: isolate"/>
|
||||
</g>
|
||||
<path id="Path_39" data-name="Path 39" d="M14.468,6.443a37.827,37.827,0,0,1,4.573,24.593c-2.287,13.934-2,34.451-2,34.451H9.461L0,3.373S10.745-.688,14.468.1,14.468,6.443,14.468,6.443Z" transform="translate(1179.929 626.963)" fill="#9ea4b8"/>
|
||||
<path id="Path_39_Copy" data-name="Path 39 Copy" d="M14.468,11.386a37.827,37.827,0,0,1,4.573,24.593c-2.287,13.934-2,34.451-2,34.451H9.461L0,8.316,17.552,0Z" transform="translate(1142.736 620.824) rotate(13)" fill="#9ea4b8"/>
|
||||
@@ -67,7 +62,7 @@
|
||||
<path id="Triangle_2_Copy_8" data-name="Triangle 2 Copy 8" d="M3.646,0,7.293,9.356H0Z" transform="translate(10.757 2.105) rotate(103)" fill="#9ea4b8"/>
|
||||
</g>
|
||||
<g id="Group_7" data-name="Group 7" transform="translate(61.224 0)">
|
||||
<path id="Path_41" data-name="Path 41" stroke="#fff" d="M30.055,0c0,3.984,9.7,21.376-15.555,43.447s-12.37,50.917,0,60.569" fill="none" transform="translate(40.847 104.016) rotate(180)" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="3.24" opacity="0.7"/>
|
||||
<path id="Path_41" data-name="Path 41" d="M30.055,0c0,3.984,9.7,21.376-15.555,43.447s-12.37,50.917,0,60.569" transform="translate(40.847 104.016) rotate(180)" fill="none" stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-miterlimit="10" stroke-width="3.24" opacity="0.7"/>
|
||||
<path id="Triangle_2-2" data-name="Triangle 2" d="M3.646,0,0,9.356H7.293Z" transform="matrix(-0.602, 0.799, -0.799, -0.602, 11.861, 83.405)" fill="#52556e"/>
|
||||
<path id="Triangle_2_Copy_7-2" data-name="Triangle 2 Copy 7" d="M3.646,0,7.293,9.356H0Z" transform="matrix(0.588, -0.809, 0.809, 0.588, 7.295, 87.86)" fill="#9ea4b8"/>
|
||||
<path id="Triangle_2_Copy" data-name="Triangle 2 Copy" d="M3.646,0,0,9.356H7.293Z" transform="translate(24.755 63.33) rotate(155)" fill="#9ea4b8"/>
|
||||
@@ -79,5 +74,9 @@
|
||||
</g>
|
||||
<path id="Path_40" data-name="Path 40" d="M82.34,85.36c-15.2-.889-38.511-9.777-44.068-38.656S17.838,3.77,0,0" transform="translate(82.34 127.666) rotate(180)" fill="none" stroke="#cdd4e0" stroke-miterlimit="10" stroke-width="1.62"/>
|
||||
</g>
|
||||
<g id="shadow-4" data-name="shadow" transform="translate(1296.024 708.416) rotate(180)">
|
||||
<ellipse id="shadow-5" data-name="shadow" cx="91.095" cy="6.269" rx="91.095" ry="6.269" transform="translate(182.19 12.537) rotate(180)" fill="url(#linear-gradient-2)" style="mix-blend-mode: multiply;isolation: isolate"/>
|
||||
<ellipse id="shadow-6" data-name="shadow" cx="91.095" cy="6.269" rx="91.095" ry="6.269" transform="translate(182.19 12.537) rotate(180)" fill="rgba(216,216,216,0.08)" style="mix-blend-mode: darken;isolation: isolate"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 12 KiB |
@@ -41,7 +41,7 @@
|
||||
}
|
||||
.launching {
|
||||
font-size: 19px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
line-height: 32px;
|
||||
color: #000000;
|
||||
margin-left: 10px;
|
||||
@@ -93,10 +93,12 @@
|
||||
</div>
|
||||
<script>
|
||||
let words = [
|
||||
"悲伤的情绪是一张向两面观望着的脸,一面朝着恐怖,一面朝着怜悯,而这两者都不过是它的两个不同的阶段。",
|
||||
"我曾努力过,去爱上帝。他最后说道。不过现在看来,我失败了。那样做很难。我曾努力一点一点地把自己的意志同上帝的意志结合起来,也不是完全没有办到,或许我会继续这么做。",
|
||||
"我几乎没有耐心来严肃地生活,既然这正儿八经的生活挡在我和我的愿望中间,那在我看来它就好像是儿戏,丑陋单调的儿戏。",
|
||||
"我除了几句日常客气话,再没有对她说过什么,可是她的名字却像一声呼唤,会调动我全身血液喷发愚蠢的激情。",
|
||||
"人类一向有这个独特之处:它保留了两套法则——一套私下的,一套真正的;一套公开的,一套矫揉造作的。",
|
||||
"人类中绝大多数人,不论是野蛮的或是文明的,在暗地里都是心地善良和畏畏缩缩地不敢叫人受苦的人,可是当着一小撮专事侵略和残酷无情的人面前,他们就不敢固执己见。",
|
||||
"如果你照顾一只肚子饿的狗,给它食物,让它过好日子,这只狗绝对不会反咬你一口,这就是狗与人类最主要的不同。",
|
||||
"跳舞,像没有人看着那样;热恋,像从未受伤一样;唱歌,像无人听着那样;活着,就把人间当天堂。",
|
||||
"这些贵妇仿佛一大片花海,五光十色,灿烂耀眼,她们身上的钻石熠熠生辉,连成一片,仿佛天上的银河。",
|
||||
"永远要像你不需要金钱那样地工作,永远要像你不曾被伤害过那样地爱,永远要像没有人在注视你那样地跳舞,永远要像在天堂那样地生活。",
|
||||
];
|
||||
let number = Math.floor(Math.random() * words.length);
|
||||
let word = words[number];
|
||||
|
||||
|
Before Width: | Height: | Size: 220 KiB After Width: | Height: | Size: 266 KiB |
@@ -5,7 +5,7 @@
|
||||
<link rel="icon" href="%PUBLIC_URL%/favicon.png" />
|
||||
<link rel="manifest" href="%PUBLIC_URL%/manifest.json" />
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+TC"
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+TC:400,500,600"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<link rel="dns-prefetch" href="https://reader.960960.xyz" />
|
||||
@@ -19,19 +19,16 @@
|
||||
itemprop="description"
|
||||
content="Koodo Reader is a open-source epub reader with backup and restore support, runs on Windows, Mac and Web"
|
||||
/>
|
||||
<script
|
||||
async
|
||||
src="https://www.googletagmanager.com/gtag/js?id=G-P4ZLVVECVF"
|
||||
></script>
|
||||
<script>
|
||||
window.dataLayer = window.dataLayer || [];
|
||||
function gtag() {
|
||||
dataLayer.push(arguments);
|
||||
}
|
||||
gtag("js", new Date());
|
||||
|
||||
gtag("config", "G-P4ZLVVECVF");
|
||||
var _hmt = _hmt || [];
|
||||
(function () {
|
||||
var hm = document.createElement("script");
|
||||
hm.src = "https://hm.baidu.com/hm.js?358570be1bfc40e01db43adefade5ad5";
|
||||
var s = document.getElementsByTagName("script")[0];
|
||||
s.parentNode.insertBefore(hm, s);
|
||||
})();
|
||||
</script>
|
||||
|
||||
<style>
|
||||
#root {
|
||||
height: 100%;
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
"This action will clear and remove this shelf": "此操作会清空并删除此书架",
|
||||
"Scale": "页面缩放",
|
||||
"Delete this tag": "删除此标签",
|
||||
"Don't show footer and header": "不显示页眉页脚",
|
||||
"Don't show footer": "不显示页脚",
|
||||
"Don't show header": "不显示页眉",
|
||||
"Default expand all content": "默认展开所有目录",
|
||||
"This action will clear and remove this tag": "此操作会清空并删除此标签",
|
||||
"Dont't use mimical background": "不使用仿真背景",
|
||||
@@ -33,7 +34,7 @@
|
||||
"Current Font Size": "当前大小",
|
||||
"Import from Local": "从本地导入",
|
||||
"Backup and Restore": "备份和恢复",
|
||||
"Search My Library": "搜索我的书库",
|
||||
"Search my library": "搜索我的书库",
|
||||
"Card Mode": "卡片模式",
|
||||
"List Mode": "列表模式",
|
||||
"Work": "工作学习",
|
||||
@@ -110,6 +111,8 @@
|
||||
"Chapter Scroll": "分章滚动",
|
||||
"Turn off audio": "关闭听书",
|
||||
"Search the book": "全书搜索",
|
||||
"Search my notes": "搜索我的笔记",
|
||||
"Search my digests": "搜索我的书摘",
|
||||
"Book size is over 20M": "图书大小超过20兆",
|
||||
"Wrong bookmark": "书签出问题了",
|
||||
"Last Step": "上一步",
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
"My Favorites": "Favorites",
|
||||
"My Notes": "Notes",
|
||||
"My Digests": "Digests",
|
||||
"My Shelves": "Shelves",
|
||||
"My Shelves": "Shelf",
|
||||
"Sort": "Sort",
|
||||
"Import Failed": "Import Failed",
|
||||
"New Version Available": "New Version Available",
|
||||
@@ -18,7 +18,9 @@
|
||||
"Uploading": "Uploading, please wait",
|
||||
"Import from Local": "Import from Local",
|
||||
"Backup and Restore": "Backup and Restore",
|
||||
"Search My Library": "Search My Library",
|
||||
"Search my library": "Search my library",
|
||||
"Search my notes": "Search my notes",
|
||||
"Search my digests": "Search my digests",
|
||||
"Card Mode": "Card",
|
||||
"List Mode": "List",
|
||||
"Work": "Work",
|
||||
@@ -60,10 +62,10 @@
|
||||
"Edit Book": "Edit Book",
|
||||
"Edit Successfully": "Edit Successfully",
|
||||
"Book Name": "Name",
|
||||
"Sort by Date": "by Date",
|
||||
"Sort by Date": "Date",
|
||||
"Descending Order": "Descend",
|
||||
"Ascending Order": "Ascend",
|
||||
"Sort by Name": "by Name",
|
||||
"Sort by Name": "Name",
|
||||
"Bind": "Bind",
|
||||
"Token": "Token",
|
||||
"Book not exsit": "Book not exsit",
|
||||
@@ -82,8 +84,8 @@
|
||||
"Do you want to backup or restore?": "Do You Want To Backup Or Restore?",
|
||||
"Where is your data?": "Where is your data?",
|
||||
"Where to keep your data?": "Where to keep your data?",
|
||||
"I want to backup": "I want to backup",
|
||||
"I want to restore": "I want to restore",
|
||||
"I want to backup": "Backup",
|
||||
"I want to restore": "Restore",
|
||||
"Delete this shelf": "Delete this shelf",
|
||||
"This action will clear and remove this shelf": "This action will clear and remove this shelf",
|
||||
"Delete this tag": "Delete this tag",
|
||||
@@ -99,7 +101,8 @@
|
||||
"Scale": "Page Scale",
|
||||
"Digest": "Digest",
|
||||
"Default expand all content": "Default expand all content",
|
||||
"Don't show footer and header": "Hide footer and header",
|
||||
"Don't show footer": "Hide footer",
|
||||
"Don't show header": "Hide header",
|
||||
"Book size is over 20M": "Book size is over 20M",
|
||||
"Current Font Size": "Current Font Size",
|
||||
"Current Chapter": "Current Chapter",
|
||||
@@ -151,7 +154,7 @@
|
||||
"More Notes": "More Notes",
|
||||
"Pick Up Color": "Pick Up Color",
|
||||
"Highlight Successfully": "Highlight Successfully",
|
||||
"Take Notes": "Take Notes",
|
||||
"Take Notes": "Note",
|
||||
"Highlight": "Highlight",
|
||||
"Copy Successfully": "Copy Successfully",
|
||||
"Copy ": "Copy",
|
||||
@@ -160,11 +163,11 @@
|
||||
"Restore": "Restore",
|
||||
"Deleted Books": "Deleted",
|
||||
"Delete All Books": "Delete All Books",
|
||||
"Sort by Duration": "by Duration",
|
||||
"Sort by Author": "by Author",
|
||||
"Sort by Duration": "Duration",
|
||||
"Sort by Author": "Author",
|
||||
"Audio is not ready yet": "Audio is not ready yet",
|
||||
"Drop your books here": "Drop your books here",
|
||||
"Sort by Percentage": "by Percentage",
|
||||
"Sort by Percentage": "Percentage",
|
||||
"This action will remove all the books in recycle bin,together with their notes, bookmarks and digests": "This action will permanently remove all the books in recycle bin,together with their notes, bookmarks and digests",
|
||||
"Batch import only support epub or pdf files": "Batch import only support epub or pdf files",
|
||||
"Drag any book to the Deleted tab to add it to Recycle Bin": "Drag any book to the Deleted tab to add it to Recycle Bin",
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
"Uploading": "上傳中,請稍候",
|
||||
"Import from Local": "從本機導入",
|
||||
"Backup and Restore": "備份和還原",
|
||||
"Search My Library": "搜尋我的書庫",
|
||||
"Search my library": "搜尋我的書庫",
|
||||
"Card Mode": "卡片模式",
|
||||
"List Mode": "列表模式",
|
||||
"More Digests": "顯示書摘出處",
|
||||
@@ -181,7 +181,8 @@
|
||||
"This action will clear and remove this tag": "此操作会清空并删除此标签",
|
||||
"Scale": "页面缩放",
|
||||
"Next Chapter": "下一章",
|
||||
"Don't show footer and header": "不显示页眉页脚",
|
||||
"Don't show footer": "不显示页脚",
|
||||
"Don't show header": "不显示页眉",
|
||||
"Default expand all content": "默认展开所有目录",
|
||||
"Prev Chapter": "上一章",
|
||||
"Current Reading Time": "本次阅读时间:{{count}}分钟",
|
||||
@@ -209,6 +210,7 @@
|
||||
"Drop your books here": "拖拽图书到此处",
|
||||
"Export": "导出",
|
||||
"Text Color": "文字颜色",
|
||||
|
||||
"Search my notes": "搜索我的笔记",
|
||||
"Search my digests": "搜索我的书摘",
|
||||
"Sort by Percentage": "按阅读进度"
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@
|
||||
<glyph unicode="" glyph-name="fullscreen" d="M930.902 960c51.351-0.118 92.933-41.773 92.933-93.14 0 0 0 0 0 0v0-837.762c-0.118-51.278-41.655-92.815-92.921-92.933h-837.773c0 0 0 0 0 0-51.367 0-93.022 41.582-93.14 92.921v837.773c0 51.44 41.7 93.14 93.14 93.14v0zM599.876 103.627l258.528-2.073-2.073 258.528-93.927 0.705 0.87-98.28-150.549 150.591-65.824-65.824 150.591-150.549-98.28 0.87 0.705-93.927zM421.637 795.026l-258.736 2.073 2.073-258.528 93.927-0.705-0.87 98.28 150.591-150.591 65.824 65.824-150.591 150.591 98.28-0.87-0.663 93.927z" />
|
||||
<glyph unicode="" glyph-name="googledrive" horiz-adv-x="1212" d="M404.326 941.271l-404.305-716.399 214.37-286.638 409.383 621.627-219.449 381.409zM1210.918 240.151h-762.819l-205.408-304.151h843.441l124.785 304.151zM807.416 958.98l-369.907 1.020 392.89-690.942 381.518 1.020-404.522 688.924zM807.459 958.98l-369.907 1.020 392.846-690.942 381.518 1.020-404.457 688.902z" />
|
||||
<glyph unicode="" glyph-name="list" d="M160 224h-128c-17.673 0-32-14.327-32-32v0-128c0-17.673 14.327-32 32-32v0h128c17.673 0 32 14.327 32 32v0 128c0 17.673-14.327 32-32 32v0zM160 864h-128c-17.673 0-32-14.327-32-32v0-128c0-17.673 14.327-32 32-32v0h128c17.673 0 32 14.327 32 32v0 128c0 17.673-14.327 32-32 32v0zM160 544h-128c-17.673 0-32-14.327-32-32v0-128c0-17.673 14.327-32 32-32v0h128c17.673 0 32 14.327 32 32v0 128c0 17.673-14.327 32-32 32v0zM992 192h-640c-17.673 0-32-14.327-32-32v0-64c0-17.673 14.327-32 32-32v0h640c17.673 0 32 14.327 32 32v0 64c0 17.673-14.327 32-32 32v0zM992 832h-640c-17.673 0-32-14.327-32-32v0-64c0-17.673 14.327-32 32-32v0h640c17.673 0 32 14.327 32 32v0 64c0 17.673-14.327 32-32 32v0zM992 512h-640c-17.673 0-32-14.327-32-32v0-64c0-17.673 14.327-32 32-32v0h640c17.673 0 32 14.327 32 32v0 64c0 17.673-14.327 32-32 32v0z" />
|
||||
<glyph unicode="" glyph-name="more" d="M4.684 446.491c0-62.26 50.472-112.732 112.732-112.732s112.732 50.472 112.732 112.732v0c0 62.26-50.472 112.732-112.732 112.732s-112.732-50.472-112.732-112.732v0zM399.249 446.491c0-62.26 50.472-112.732 112.732-112.732s112.732 50.472 112.732 112.732v0c0 62.26-50.472 112.732-112.732 112.732s-112.732-50.472-112.732-112.732v0zM793.815 446.491c0-62.26 50.472-112.732 112.732-112.732s112.732 50.472 112.732 112.732v0c0 62.26-50.472 112.732-112.732 112.732s-112.732-50.472-112.732-112.732v0z" />
|
||||
<glyph unicode="" glyph-name="more" d="M513.509-59.316c62.26 0 112.732 50.472 112.732 112.732s-50.472 112.732-112.732 112.732v0c-62.26 0-112.732-50.472-112.732-112.732s50.472-112.732 112.732-112.732v0zM513.509 335.249c62.26 0 112.732 50.472 112.732 112.732s-50.472 112.732-112.732 112.732v0c-62.26 0-112.732-50.472-112.732-112.732s50.472-112.732 112.732-112.732v0zM513.509 729.815c62.26 0 112.732 50.472 112.732 112.732s-50.472 112.732-112.732 112.732v0c-62.26 0-112.732-50.472-112.732-112.732s50.472-112.732 112.732-112.732v0z" />
|
||||
<glyph unicode="" glyph-name="bookmark" d="M149.847 960v-1024l362.153 249.752 362.153-249.752v1024z" />
|
||||
<glyph unicode="" glyph-name="shelf" d="M314.343-36.583h235.688v942.524h-235.688zM392.906 630.994h78.563v-392.768h-78.563zM860.747 931.838l-232.153-40.957 164.013-928.152 232.153 41.049zM753.808 633.887l77.369 13.775 68.369-386.707-77.369-13.775zM0-33.139h235.734v942.524h-235.734zM78.563 634.438h78.563v-392.492h-78.563z" />
|
||||
<glyph unicode="" glyph-name="idea" d="M487.345 959.079c-181.191-13.547-323.069-163.888-323.069-347.365 0-86.92 31.841-166.403 84.495-227.421l-0.378 0.448c39.112-44.631 66.291-100.639 76.011-162.444l0.237-1.833c2.832-20.078 19.89-35.358 40.52-35.38h293.752c20.633 0.022 37.69 15.302 40.497 35.163l0.025 0.217c9.286 63.089 36.102 118.686 75.279 163.124l-0.297-0.343c52.895 60.769 85.139 140.726 85.139 228.214 0 192.434-155.999 348.432-348.432 348.432-8.367 0-16.666-0.295-24.886-0.875l1.106 0.063zM510.906 816.521c-107.672-0.338-195.763-83.713-203.608-189.425l-0.040-0.677c0.032-0.43 0.050-0.931 0.050-1.437 0-11.317-9.174-20.492-20.492-20.492s-20.492 9.174-20.492 20.492c0 1.806 0.234 3.557 0.672 5.225l-0.032-0.143c9.817 127.647 115.785 227.509 245.087 227.556h0.005c11.092-0.321 19.962-9.389 19.962-20.53 0-11.343-9.195-20.538-20.538-20.538-0.202 0-0.404 0.003-0.605 0.009l0.030-0.001zM629.865-64h-235.345c-72.488 0-91.022 103.877-29.356 103.877h293.98c61.551 0 43.324-103.877-29.356-103.877zM696.443 123.263v-21.95c0-11.317-9.174-20.492-20.492-20.492h-327.749c-11.317 0-20.492 9.174-20.492 20.492v22.103c0 11.317 9.174 20.492 20.492 20.492v0h327.672c11.301-0.022 20.453-9.188 20.453-20.491 0 0 0 0 0 0v0z" />
|
||||
|
||||
|
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 53 KiB |
@@ -1,10 +1,10 @@
|
||||
@font-face {
|
||||
font-family: 'icomoon';
|
||||
src: url('fonts/icomoon.eot?x6b7dj');
|
||||
src: url('fonts/icomoon.eot?x6b7dj#iefix') format('embedded-opentype'),
|
||||
url('fonts/icomoon.ttf?x6b7dj') format('truetype'),
|
||||
url('fonts/icomoon.woff?x6b7dj') format('woff'),
|
||||
url('fonts/icomoon.svg?x6b7dj#icomoon') format('svg');
|
||||
src: url('fonts/icomoon.eot?r0ucr2');
|
||||
src: url('fonts/icomoon.eot?r0ucr2#iefix') format('embedded-opentype'),
|
||||
url('fonts/icomoon.ttf?r0ucr2') format('truetype'),
|
||||
url('fonts/icomoon.woff?r0ucr2') format('woff'),
|
||||
url('fonts/icomoon.svg?r0ucr2#icomoon') format('svg');
|
||||
font-weight: normal;
|
||||
font-style: normal;
|
||||
font-display: block;
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
height: 137px;
|
||||
background: white;
|
||||
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.22);
|
||||
opacity: 0.73;
|
||||
opacity: 1;
|
||||
margin: 15px 15px 5px 15px;
|
||||
cursor: pointer;
|
||||
overflow: hidden;
|
||||
@@ -25,13 +25,10 @@
|
||||
opacity: 1;
|
||||
text-align: center;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
display: -webkit-box;
|
||||
-webkit-box-orient: vertical;
|
||||
-webkit-line-clamp: 2;
|
||||
white-space: normal;
|
||||
word-break: keep-all;
|
||||
overflow: hidden;
|
||||
overflow: visible;
|
||||
position: relative;
|
||||
}
|
||||
.book-item-config {
|
||||
@@ -64,11 +61,11 @@
|
||||
position: absolute;
|
||||
top: 23px;
|
||||
right: 17px;
|
||||
transform: rotate(90deg);
|
||||
font-size: 18px;
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
text-shadow: 0px 0px 5px rgba(75, 75, 75, 0.6);
|
||||
animation: slide-down-rotate 0.1s ease-in-out 0s 1;
|
||||
}
|
||||
.reading-progress-icon {
|
||||
position: absolute;
|
||||
@@ -83,6 +80,37 @@
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
transform: scale(0.9);
|
||||
animation: slide-down 0.1s ease-in-out 0s 1;
|
||||
}
|
||||
@keyframes slide-down {
|
||||
0% {
|
||||
transform: translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes slide-down-rotate {
|
||||
0% {
|
||||
transform: translateY(-20px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes slide-up {
|
||||
0% {
|
||||
transform: translateY(20px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateY(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.reading-percentage-char {
|
||||
display: inline-block;
|
||||
@@ -97,6 +125,7 @@
|
||||
cursor: pointer;
|
||||
z-index: 1;
|
||||
text-shadow: 0px 0px 5px rgba(75, 75, 75, 0.6);
|
||||
animation: slide-up 0.1s ease-in-out 0s 1;
|
||||
}
|
||||
.book-loved-icon {
|
||||
position: absolute;
|
||||
@@ -142,7 +171,7 @@
|
||||
position: absolute;
|
||||
top: 115px;
|
||||
left: 15px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
width: 106px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
height: 74px;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.22);
|
||||
opacity: 0.73;
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
}
|
||||
.book-item-list-title,
|
||||
|
||||
@@ -165,9 +165,3 @@
|
||||
bottom: 5px;
|
||||
margin-left: calc(50% - 6px);
|
||||
}
|
||||
/* 控制小于888px是书脊消失 */
|
||||
@media screen and (max-width: 888px) {
|
||||
.card-list-item-citation {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,9 +79,12 @@ class CardList extends React.Component<CardListProps, CardListStates> {
|
||||
}}
|
||||
style={this.props.mode === "note" ? { height: "250px" } : {}}
|
||||
>
|
||||
{this.state.deleteKey === item.key ? (
|
||||
<DeleteIcon {...cardProps} />
|
||||
) : null}
|
||||
<div style={{ position: "relative", bottom: "25px" }}>
|
||||
{this.state.deleteKey === item.key ? (
|
||||
<DeleteIcon {...cardProps} />
|
||||
) : null}
|
||||
</div>
|
||||
|
||||
<div className="card-list-item-card">
|
||||
<div className="card-list-item-text-parent">
|
||||
<div className="card-list-item-text">
|
||||
|
||||
@@ -1,20 +1,23 @@
|
||||
.color-option-container {
|
||||
width: 100%;
|
||||
width: 90%;
|
||||
height: 40px;
|
||||
margin-left: 5%;
|
||||
position: relative;
|
||||
top: 8px;
|
||||
top: 15px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.color-option {
|
||||
width: 30px;
|
||||
height: 30px;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
background: rgba(228, 255, 154, 1);
|
||||
border-radius: 50%;
|
||||
opacity: 1;
|
||||
box-sizing: border-box;
|
||||
position: relative;
|
||||
bottom: 5px;
|
||||
cursor: pointer;
|
||||
animation: slide-left 0.2s ease-in-out 0s 1;
|
||||
}
|
||||
.popup-color-more {
|
||||
display: inline-block;
|
||||
@@ -36,6 +39,27 @@
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
animation: slide-right 0.2s ease-in-out 0s 1;
|
||||
}
|
||||
@keyframes slide-right {
|
||||
0% {
|
||||
transform: translateX(30px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
@keyframes slide-left {
|
||||
0% {
|
||||
transform: translateX(-50px);
|
||||
opacity: 0;
|
||||
}
|
||||
100% {
|
||||
transform: translateX(0px);
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
.demo-line {
|
||||
width: 100%;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
top: 2px !important;
|
||||
right: 2px !important;
|
||||
z-index: 10;
|
||||
animation: popup 0.1s ease-in-out 0s 1;
|
||||
}
|
||||
.delete-digest-icon {
|
||||
position: relative;
|
||||
|
||||
@@ -94,7 +94,6 @@ class DropdownList extends React.Component<
|
||||
value={[subItem, index.toString()]}
|
||||
className="general-setting-option"
|
||||
key={index}
|
||||
style={item.id === 1 ? { fontFamily: subItem } : {}}
|
||||
>
|
||||
{subItem}
|
||||
</option>
|
||||
|
||||
@@ -8,7 +8,9 @@
|
||||
.general-setting-title {
|
||||
font-size: 16px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
margin: 15px 0px 17px 0px;
|
||||
font-weight: 500;
|
||||
margin-top: 15px;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.general-setting-dropdown {
|
||||
width: 220px;
|
||||
|
||||
@@ -40,6 +40,7 @@ class ImageViewer extends React.Component<ImageViewerProps, ImageViewerStates> {
|
||||
this.props.handleLeaveReader("bottom");
|
||||
}
|
||||
let href =
|
||||
event.target ||
|
||||
event.target.href ||
|
||||
event.target.parentNode.href ||
|
||||
event.target.parentNode.parentNode.href;
|
||||
|
||||
@@ -423,7 +423,9 @@ class ImportLocal extends React.Component<ImportLocalProps, ImportLocalState> {
|
||||
className="import-from-local"
|
||||
{...getRootProps()}
|
||||
style={
|
||||
OtherUtil.getReaderConfig("lang") === "en" ? { right: 390 } : {}
|
||||
OtherUtil.getReaderConfig("lang") === "en"
|
||||
? { fontSize: "14px" }
|
||||
: {}
|
||||
}
|
||||
>
|
||||
<Trans>Import from Local</Trans>
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
color: white;
|
||||
cursor: pointer;
|
||||
z-index: 50;
|
||||
transition: 0.1s;
|
||||
}
|
||||
.import-from-local:hover {
|
||||
background-color: rgba(75, 75, 75, 0.9);
|
||||
|
||||
@@ -45,18 +45,7 @@ class ModeControl extends React.Component<ModeControlProps, ModeControlState> {
|
||||
<Trans>Double-Page Mode</Trans>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
className="double-mode-container"
|
||||
onClick={() => {
|
||||
this.handleChangeMode("scroll");
|
||||
}}
|
||||
style={this.state.readerMode === "scroll" ? {} : { opacity: 0.4 }}
|
||||
>
|
||||
<span className="icon-scroll1 two-page-icon"></span>
|
||||
<div className="double-mode-text">
|
||||
<Trans>Chapter Scroll</Trans>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="double-mode-container"
|
||||
onClick={() => {
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
.single-control-container {
|
||||
width: calc(100% - 10px);
|
||||
width: calc(100% - 30px);
|
||||
height: 80px;
|
||||
margin: 0px 5px 0px 5px;
|
||||
margin: 0px 15px 0px 15px;
|
||||
display: flex;
|
||||
justify-content: space-around;
|
||||
}
|
||||
.single-page-icon,
|
||||
.two-page-icon {
|
||||
font-size: 50px;
|
||||
font-size: 60px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
@@ -71,7 +71,9 @@ class NoteTag extends React.Component<NoteTagProps, NoteTagState> {
|
||||
this.props.handleTag(this.indextoTag([]));
|
||||
};
|
||||
handleInput = () => {
|
||||
this.setState({ isInput: true });
|
||||
this.setState({ isInput: true }, () => {
|
||||
document.getElementById("newTag")?.focus();
|
||||
});
|
||||
};
|
||||
render() {
|
||||
const renderTag = () => {
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
color: #4b4b4b;
|
||||
opacity: 1;
|
||||
margin-left: 10px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
}
|
||||
.tag-container {
|
||||
display: inline-block;
|
||||
|
||||
@@ -57,7 +57,7 @@
|
||||
position: absolute;
|
||||
bottom: 15px;
|
||||
right: 15px;
|
||||
width: 100px;
|
||||
width: 120px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
}
|
||||
@@ -74,6 +74,7 @@
|
||||
color: rgba(0, 0, 0, 1);
|
||||
opacity: 1;
|
||||
cursor: pointer;
|
||||
margin-right: 20px;
|
||||
}
|
||||
.note-tags {
|
||||
width: 100%;
|
||||
|
||||
@@ -9,10 +9,9 @@
|
||||
.digest-option,
|
||||
.translation-option,
|
||||
.copy-option {
|
||||
height: 55px;
|
||||
height: 69px;
|
||||
width: 69px;
|
||||
font-size: 14px !important;
|
||||
|
||||
line-height: 15px !important;
|
||||
color: rgba(0, 0, 0, 1);
|
||||
opacity: 1;
|
||||
@@ -20,10 +19,17 @@
|
||||
display: flex;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
|
||||
transition: 0.1s;
|
||||
/* align-items: center; */
|
||||
justify-content: center;
|
||||
}
|
||||
.note-option:hover,
|
||||
.digest-option:hover,
|
||||
.translation-option:hover,
|
||||
.copy-option:hover {
|
||||
background-color: rgba(75, 75, 75, 0.035);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.digest-option {
|
||||
margin-top: 5px;
|
||||
margin-right: 10px;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
import React from "react";
|
||||
import "./searchBox.css";
|
||||
import OtherUtil from "../../utils/otherUtil";
|
||||
import { Trans } from "react-i18next";
|
||||
import { Trans, withNamespaces } from "react-i18next";
|
||||
import { SearchBoxProps } from "./interface";
|
||||
class SearchBox extends React.Component<SearchBoxProps> {
|
||||
componentDidMount() {
|
||||
@@ -100,12 +100,12 @@ class SearchBox extends React.Component<SearchBoxProps> {
|
||||
}}
|
||||
placeholder={
|
||||
this.props.isNavSearch || this.props.mode === "nav"
|
||||
? "搜索全书"
|
||||
? this.props.t("Search the book")
|
||||
: this.props.tabMode === "note"
|
||||
? "搜索我的笔记"
|
||||
? this.props.t("Search my notes")
|
||||
: this.props.tabMode === "digest"
|
||||
? "搜索我的书摘"
|
||||
: "搜索我的书库"
|
||||
? this.props.t("Search my digests")
|
||||
: this.props.t("Search my library")
|
||||
}
|
||||
style={
|
||||
this.props.mode === "nav"
|
||||
@@ -137,4 +137,4 @@ class SearchBox extends React.Component<SearchBoxProps> {
|
||||
}
|
||||
}
|
||||
|
||||
export default SearchBox;
|
||||
export default withNamespaces()(SearchBox as any);
|
||||
|
||||
@@ -16,4 +16,5 @@ export interface SearchBoxProps {
|
||||
handleSearch: (isSearch: boolean) => void;
|
||||
handleSearchState: (isSearch: boolean) => void;
|
||||
handleSearchList: (searchList: any) => void;
|
||||
t: any;
|
||||
}
|
||||
|
||||
@@ -19,8 +19,6 @@ class SettingDialog extends React.Component<
|
||||
isTouch: OtherUtil.getReaderConfig("isTouch") === "yes",
|
||||
isOpenBook: OtherUtil.getReaderConfig("isOpenBook") === "yes",
|
||||
isExpandContent: OtherUtil.getReaderConfig("isExpandContent") === "yes",
|
||||
isUseBackground: OtherUtil.getReaderConfig("isUseBackground") === "yes",
|
||||
isShowFooter: OtherUtil.getReaderConfig("isShowFooter") !== "no",
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
@@ -79,28 +77,7 @@ class SettingDialog extends React.Component<
|
||||
: this.props.handleMessage("Turn On Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
handleChangeBackground = () => {
|
||||
this.setState({ isUseBackground: !this.state.isUseBackground });
|
||||
OtherUtil.setReaderConfig(
|
||||
"isUseBackground",
|
||||
this.state.isUseBackground ? "no" : "yes"
|
||||
);
|
||||
this.state.isUseBackground
|
||||
? this.props.handleMessage("Turn Off Successfully")
|
||||
: this.props.handleMessage("Turn On Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
handleFooterHeader = () => {
|
||||
this.setState({ isShowFooter: !this.state.isShowFooter });
|
||||
OtherUtil.setReaderConfig(
|
||||
"isShowFooter",
|
||||
this.state.isShowFooter ? "no" : "yes"
|
||||
);
|
||||
this.state.isShowFooter
|
||||
? this.props.handleMessage("Turn On Successfully")
|
||||
: this.props.handleMessage("Turn Off Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
|
||||
render() {
|
||||
return (
|
||||
<div className="setting-dialog-container">
|
||||
@@ -115,12 +92,15 @@ class SettingDialog extends React.Component<
|
||||
<Trans>Date</Trans>
|
||||
{updateLog.date}
|
||||
</p>
|
||||
<span
|
||||
className="icon-close setting-close"
|
||||
onClick={() => {
|
||||
this.props.handleSetting(false);
|
||||
}}
|
||||
></span>
|
||||
<div className="setting-close-container">
|
||||
<span
|
||||
className="icon-close setting-close"
|
||||
onClick={() => {
|
||||
this.props.handleSetting(false);
|
||||
}}
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div className="setting-dialog-info">
|
||||
<div className="setting-dialog-new-title">
|
||||
{this.state.isTouch ? (
|
||||
@@ -203,56 +183,6 @@ class SettingDialog extends React.Component<
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="setting-dialog-new-title">
|
||||
<Trans>Don't show footer and header</Trans>
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
this.handleFooterHeader();
|
||||
}}
|
||||
style={{ float: "right" }}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={
|
||||
this.state.isShowFooter
|
||||
? {
|
||||
transform: "translateX(0px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
: {
|
||||
transform: "translateX(20px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="setting-dialog-new-title">
|
||||
<Trans>Dont't use mimical background</Trans>
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
this.handleChangeBackground();
|
||||
}}
|
||||
style={{ float: "right" }}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={
|
||||
this.state.isUseBackground
|
||||
? {
|
||||
transform: "translateX(20px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
: {
|
||||
transform: "translateX(0px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
<div className="setting-dialog-new-title">
|
||||
<Trans>语言 / Language</Trans>
|
||||
@@ -294,23 +224,13 @@ class SettingDialog extends React.Component<
|
||||
<div
|
||||
className="setting-dialog-subtitle"
|
||||
onClick={() => {
|
||||
this.handleJump("https://github.com/troyeguo");
|
||||
this.handleJump("https://960960.xyz");
|
||||
}}
|
||||
>
|
||||
<Trans>About author</Trans>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<img
|
||||
src={
|
||||
process.env.NODE_ENV === "production"
|
||||
? "./assets/empty.svg"
|
||||
: "../../assets/empty.svg"
|
||||
}
|
||||
alt=""
|
||||
className="setting-dialog-illustration"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -7,7 +7,5 @@ export interface SettingInfoState {
|
||||
language: string;
|
||||
isTouch: boolean;
|
||||
isOpenBook: boolean;
|
||||
isUseBackground: boolean;
|
||||
isShowFooter: boolean;
|
||||
isExpandContent: boolean;
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
.setting-dialog-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
@@ -85,15 +85,23 @@
|
||||
font-size: 25px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
}
|
||||
.setting-close {
|
||||
.setting-close-container {
|
||||
position: absolute;
|
||||
top: 10px;
|
||||
right: 10px;
|
||||
transition: 0.1s;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
|
||||
.setting-close-container:hover {
|
||||
background-color: rgba(75, 75, 75, 0.035);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.about-this-project {
|
||||
position: absolute;
|
||||
bottom: 20px;
|
||||
left: 40px;
|
||||
left: 100px;
|
||||
width: 150px;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
|
||||
@@ -12,7 +12,9 @@ class SliderList extends React.Component<SliderListProps, SliderListState> {
|
||||
value:
|
||||
this.props.mode === "fontSize"
|
||||
? OtherUtil.getReaderConfig("fontSize") || "17"
|
||||
: OtherUtil.getReaderConfig("scale") || "1",
|
||||
: this.props.mode === "scale"
|
||||
? OtherUtil.getReaderConfig("scale") || "1"
|
||||
: OtherUtil.getReaderConfig("margin") || "30",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -26,11 +28,14 @@ class SliderList extends React.Component<SliderListProps, SliderListState> {
|
||||
"font-size": `${fontSize || 17}px !important`,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
} else if (this.props.mode === "scale") {
|
||||
const scale = event.target.value;
|
||||
this.setState({ value: scale });
|
||||
OtherUtil.setReaderConfig("scale", scale);
|
||||
window.location.reload();
|
||||
} else {
|
||||
const margin = event.target.value;
|
||||
this.setState({ value: margin });
|
||||
OtherUtil.setReaderConfig("margin", margin);
|
||||
}
|
||||
};
|
||||
//使进度百分比随拖动实时变化
|
||||
@@ -46,25 +51,27 @@ class SliderList extends React.Component<SliderListProps, SliderListState> {
|
||||
<Trans>Font Size</Trans>
|
||||
<span>{this.state.value}px</span>
|
||||
</>
|
||||
) : (
|
||||
) : this.props.mode === "scale" ? (
|
||||
<>
|
||||
<Trans>Scale</Trans>
|
||||
<span>
|
||||
{parseInt((parseFloat(this.state.value) * 100).toString())}%
|
||||
</span>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<Trans>Margin</Trans>
|
||||
<span>{this.state.value}px</span>
|
||||
</>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<span
|
||||
className="ultra-small-size"
|
||||
style={
|
||||
this.props.mode === "fontSize"
|
||||
? {}
|
||||
: { position: "relative", right: 7 }
|
||||
}
|
||||
>
|
||||
{this.props.mode === "fontSize" ? "A" : "1"}
|
||||
<span className="ultra-small-size">
|
||||
{this.props.mode === "fontSize"
|
||||
? "A"
|
||||
: this.props.mode === "scale"
|
||||
? "1"
|
||||
: "0"}
|
||||
</span>
|
||||
<div className="font-size-selector">
|
||||
<input
|
||||
@@ -73,23 +80,39 @@ class SliderList extends React.Component<SliderListProps, SliderListState> {
|
||||
type="range"
|
||||
max={this.props.maxValue}
|
||||
min={this.props.minValue}
|
||||
step={this.props.mode === "fontSize" ? "1" : "0.1"}
|
||||
step={
|
||||
this.props.mode === "fontSize"
|
||||
? "1"
|
||||
: this.props.mode === "scale"
|
||||
? "0.1"
|
||||
: "5"
|
||||
}
|
||||
onInput={(event) => {
|
||||
this.onValueChange(event);
|
||||
}}
|
||||
onChange={(event) => {
|
||||
this.onValueInput(event);
|
||||
}}
|
||||
onMouseUp={() => {
|
||||
window.location.reload();
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
{this.props.mode === "fontSize" ? (
|
||||
<span className="ultra-large-size">A</span>
|
||||
) : this.props.mode === "scale" ? (
|
||||
<span
|
||||
className="ultra-large-size"
|
||||
style={{ fontSize: "16px", right: "5px" }}
|
||||
>
|
||||
2
|
||||
</span>
|
||||
) : (
|
||||
<span
|
||||
className="ultra-large-size"
|
||||
style={{ fontSize: "16px", left: 5 }}
|
||||
style={{ fontSize: "16px", right: "5px" }}
|
||||
>
|
||||
2
|
||||
50
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
|
||||
@@ -8,12 +8,16 @@
|
||||
line-height: 27px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
padding-bottom: 10px;
|
||||
font-weight: 500;
|
||||
margin-bottom: -5px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.ultra-small-size {
|
||||
float: left;
|
||||
font-size: 16px;
|
||||
line-height: 27px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.ultra-large-size {
|
||||
@@ -23,7 +27,7 @@
|
||||
color: rgba(75, 75, 75, 1);
|
||||
position: relative;
|
||||
bottom: 49px;
|
||||
left: 5px;
|
||||
text-align: left;
|
||||
}
|
||||
.font-size-selector {
|
||||
width: 205px;
|
||||
|
||||
@@ -24,7 +24,7 @@ class ThemeList extends React.Component<ThemeListProps, ThemeListState> {
|
||||
currentTextIndex: textList.findIndex((item) => {
|
||||
return (
|
||||
item.theme ===
|
||||
(OtherUtil.getReaderConfig("textColor") || "rgba(255,255,255,1)")
|
||||
(OtherUtil.getReaderConfig("textColor") || "rgba(0,0,0,1)")
|
||||
);
|
||||
}),
|
||||
isShowTextPicker: false,
|
||||
@@ -42,6 +42,15 @@ class ThemeList extends React.Component<ThemeListProps, ThemeListState> {
|
||||
color: `white !important`,
|
||||
},
|
||||
});
|
||||
} else if (
|
||||
index === 2 &&
|
||||
OtherUtil.getReaderConfig("backgroundColor") === "rgba(255,255,255,1)"
|
||||
) {
|
||||
this.props.currentEpub.rendition.themes.default({
|
||||
"a, article, cite, code, div, li, p, pre, span, table": {
|
||||
color: `black !important`,
|
||||
},
|
||||
});
|
||||
} else {
|
||||
this.props.currentEpub.rendition.themes.default({
|
||||
"a, article, cite, code, div, li, p, pre, span, table": {
|
||||
|
||||
@@ -7,7 +7,9 @@
|
||||
width: 100%;
|
||||
font-size: 16px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
margin: 6px 0px;
|
||||
font-weight: 500;
|
||||
margin-bottom: -5px;
|
||||
margin-top: 15px;
|
||||
}
|
||||
.background-color-list {
|
||||
margin: 10px 0px 0px;
|
||||
|
||||
@@ -59,21 +59,6 @@ class UpdateDialog extends React.Component<UpdateInfoProps, UpdateInfoState> {
|
||||
>
|
||||
<Trans>Confirm</Trans>
|
||||
</div>
|
||||
<p className="update-dialog-url">
|
||||
<span style={{ color: "#959595" }}>
|
||||
<Trans>Our Website</Trans>
|
||||
</span>
|
||||
koodo.960960.xyz
|
||||
</p>
|
||||
<img
|
||||
src={
|
||||
process.env.NODE_ENV === "production"
|
||||
? "./assets/empty.svg"
|
||||
: "../../assets/empty.svg"
|
||||
}
|
||||
alt=""
|
||||
className="update-dialog-illustration"
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
}
|
||||
.update-dialog-title {
|
||||
font-size: 20px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
line-height: 15px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
@@ -44,7 +44,7 @@
|
||||
}
|
||||
.update-dialog-info {
|
||||
margin-top: 10px;
|
||||
height: 300px;
|
||||
height: 330px;
|
||||
overflow-y: scroll;
|
||||
width: 346px;
|
||||
}
|
||||
|
||||
@@ -32,12 +32,7 @@
|
||||
place-content: center; */
|
||||
overflow: hidden;
|
||||
}
|
||||
/* 控制小于888px是书脊消失 */
|
||||
@media screen and (max-width: 888px) {
|
||||
.background-box3 {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.book-spine {
|
||||
position: absolute;
|
||||
width: 1px;
|
||||
@@ -86,7 +81,6 @@
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
line-height: 30px;
|
||||
color: rgba(191, 191, 191, 1);
|
||||
text-align: center;
|
||||
}
|
||||
.progress-chapter-name {
|
||||
@@ -104,7 +98,6 @@
|
||||
position: absolute;
|
||||
bottom: 10px;
|
||||
line-height: 30px;
|
||||
color: rgba(191, 191, 191, 1);
|
||||
text-align: center;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ class Background extends React.Component<BackgroundProps, BackgroundState> {
|
||||
nextPage: 0,
|
||||
scale: OtherUtil.getReaderConfig("scale") || 1,
|
||||
isShowFooter: OtherUtil.getReaderConfig("isShowFooter") !== "no",
|
||||
isShowHeader: OtherUtil.getReaderConfig("isShowHeader") !== "no",
|
||||
isUseBackground: OtherUtil.getReaderConfig("isUseBackground") === "yes",
|
||||
};
|
||||
this.isFirst = true;
|
||||
@@ -53,8 +54,15 @@ class Background extends React.Component<BackgroundProps, BackgroundState> {
|
||||
render() {
|
||||
if (this.state.isUseBackground) {
|
||||
return (
|
||||
<div className="background">
|
||||
{this.state.isShowFooter && this.state.currentChapter && (
|
||||
<div
|
||||
className="background"
|
||||
style={{
|
||||
color: OtherUtil.getReaderConfig("textColor")
|
||||
? OtherUtil.getReaderConfig("textColor")
|
||||
: "",
|
||||
}}
|
||||
>
|
||||
{this.state.isShowHeader && this.state.currentChapter && (
|
||||
<p
|
||||
className="progress-chapter-name"
|
||||
style={
|
||||
@@ -69,7 +77,7 @@ class Background extends React.Component<BackgroundProps, BackgroundState> {
|
||||
<Trans>{this.state.currentChapter}</Trans>
|
||||
</p>
|
||||
)}
|
||||
{this.state.isShowFooter && !this.state.isSingle && (
|
||||
{this.state.isShowHeader && !this.state.isSingle && (
|
||||
<p
|
||||
className="progress-book-name"
|
||||
style={
|
||||
@@ -120,8 +128,15 @@ class Background extends React.Component<BackgroundProps, BackgroundState> {
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="background">
|
||||
{this.state.isShowFooter && this.state.currentChapter && (
|
||||
<div
|
||||
className="background"
|
||||
style={{
|
||||
color: OtherUtil.getReaderConfig("textColor")
|
||||
? OtherUtil.getReaderConfig("textColor")
|
||||
: "",
|
||||
}}
|
||||
>
|
||||
{this.state.isShowHeader && this.state.currentChapter && (
|
||||
<p
|
||||
className="progress-chapter-name"
|
||||
style={
|
||||
@@ -137,7 +152,7 @@ class Background extends React.Component<BackgroundProps, BackgroundState> {
|
||||
</p>
|
||||
)}
|
||||
|
||||
{this.state.isShowFooter && !this.state.isSingle && (
|
||||
{this.state.isShowHeader && !this.state.isSingle && (
|
||||
<p
|
||||
className="progress-book-name"
|
||||
style={
|
||||
|
||||
@@ -10,6 +10,7 @@ export interface BackgroundProps {
|
||||
export interface BackgroundState {
|
||||
isSingle: boolean;
|
||||
isShowFooter: boolean;
|
||||
isShowHeader: boolean;
|
||||
isUseBackground: boolean;
|
||||
currentChapter: string;
|
||||
prevPage: number;
|
||||
|
||||
@@ -97,6 +97,13 @@
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
cursor: pointer;
|
||||
transition: 0.1s;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
.backup-page-close-icon:hover {
|
||||
background-color: rgba(75, 75, 75, 0.035);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.backup-page-option {
|
||||
width: 100%;
|
||||
|
||||
@@ -206,12 +206,15 @@ class BackupDialog extends React.Component<
|
||||
style={{ marginLeft: "252px" }}
|
||||
></div>
|
||||
) : null}
|
||||
<span
|
||||
className="icon-close backup-page-close-icon"
|
||||
onClick={() => {
|
||||
this.handleClose();
|
||||
}}
|
||||
></span>
|
||||
<div className="backup-page-close-icon">
|
||||
<span
|
||||
className="icon-close "
|
||||
onClick={() => {
|
||||
this.handleClose();
|
||||
}}
|
||||
></span>
|
||||
</div>
|
||||
|
||||
{this.state.currentStep === 1 ? (
|
||||
<div
|
||||
className="backup-page-next"
|
||||
|
||||
@@ -50,15 +50,19 @@
|
||||
float: left;
|
||||
line-height: 17px;
|
||||
cursor: pointer;
|
||||
height: 27px;
|
||||
padding: 5px;
|
||||
}
|
||||
.list-view-mode {
|
||||
min-width: 51px;
|
||||
height: 17px;
|
||||
height: 27px;
|
||||
float: left;
|
||||
line-height: 17px;
|
||||
margin-left: 15px;
|
||||
cursor: pointer;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.book-list-item-box {
|
||||
position: relative;
|
||||
top: 0px;
|
||||
@@ -72,12 +76,7 @@
|
||||
top: 1px;
|
||||
margin-right: 5px;
|
||||
}
|
||||
.booklist-shelf-container {
|
||||
position: absolute;
|
||||
top: 80px;
|
||||
left: calc(50vw - 100px);
|
||||
width: 400px;
|
||||
}
|
||||
|
||||
.booklist-shelf-list {
|
||||
width: 169px;
|
||||
height: 31px;
|
||||
|
||||
@@ -128,13 +128,15 @@ class BookList extends React.Component<BookListProps, BookListState> {
|
||||
? this.handleShelf(this.props.books, this.props.shelfIndex)
|
||||
: this.props.mode === "favorite" && !this.props.isSort
|
||||
? this.handleKeyFilter(this.props.books, AddFavorite.getAllFavorite())
|
||||
: this.props.mode === "favorite" && this.props.isSort
|
||||
: this.props.mode === "favorite" &&
|
||||
this.props.isSort &&
|
||||
!this.props.noteSortCode
|
||||
? this.handleIndexFilter(
|
||||
this.handleKeyFilter(this.props.books, AddFavorite.getAllFavorite()),
|
||||
//返回排序后的图书index
|
||||
SortUtil.sortBooks(this.props.books, this.props.bookSortCode) || []
|
||||
)
|
||||
: this.props.isSort
|
||||
: this.props.isSort && !this.props.noteSortCode
|
||||
? this.handleIndexFilter(
|
||||
this.props.books,
|
||||
//返回排序后的图书index
|
||||
@@ -217,6 +219,7 @@ class BookList extends React.Component<BookListProps, BookListState> {
|
||||
this.setState({ isOpenDelete });
|
||||
};
|
||||
render() {
|
||||
console.log(this.state.favoriteBooks, "this.state.favoriteBooks");
|
||||
if (
|
||||
(this.state.favoriteBooks === 0 && this.props.mode === "favorite") ||
|
||||
!this.props.books ||
|
||||
|
||||
@@ -17,6 +17,7 @@ const mappropsToProps = (state: stateType) => {
|
||||
isSort: state.manager.isSort,
|
||||
isList: state.manager.isList,
|
||||
bookSortCode: state.manager.bookSortCode,
|
||||
noteSortCode: state.manager.noteSortCode,
|
||||
};
|
||||
};
|
||||
const actionCreator = {
|
||||
|
||||
@@ -9,6 +9,7 @@ export interface BookListProps extends RouteComponentProps<any> {
|
||||
isSort: boolean;
|
||||
isList: string;
|
||||
bookSortCode: { sort: number; order: number };
|
||||
noteSortCode: { sort: number; order: number };
|
||||
handleFetchList: () => void;
|
||||
handleMode: (mode: string) => void;
|
||||
handleShelfIndex: (index: number) => void;
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
height: 117px;
|
||||
background: rgba(0, 0, 0, 0);
|
||||
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.22);
|
||||
opacity: 0.73;
|
||||
opacity: 1;
|
||||
margin: 10px;
|
||||
margin-left: 15px;
|
||||
cursor: pointer;
|
||||
|
||||
@@ -1,14 +1,13 @@
|
||||
.delete-dialog-container {
|
||||
width: 309px;
|
||||
height: 189px;
|
||||
width: 319px;
|
||||
height: 199px;
|
||||
background: rgba(255, 255, 255, 1);
|
||||
box-shadow: 0px 0px 16px rgba(0, 0, 0, 0.34);
|
||||
opacity: 1;
|
||||
position: fixed;
|
||||
left: calc(50% - 155px);
|
||||
top: calc(50% - 95px);
|
||||
left: calc(50% - 160px);
|
||||
top: calc(50% - 100px);
|
||||
z-index: 10;
|
||||
padding: 5px;
|
||||
animation: popup 0.1s ease-in-out 0s 1;
|
||||
}
|
||||
.delete-dialog-title {
|
||||
@@ -49,7 +48,9 @@
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
top: 106px;
|
||||
width: 100%;
|
||||
padding-left: 5px;
|
||||
padding-right: 5px;
|
||||
width: calc(100% - 10px);
|
||||
/* margin-left: 25px; */
|
||||
}
|
||||
.icon-check {
|
||||
@@ -69,7 +70,7 @@
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
left: 147px;
|
||||
top: 144px;
|
||||
top: 154px;
|
||||
|
||||
font-size: 14px;
|
||||
|
||||
@@ -86,9 +87,8 @@
|
||||
opacity: 1;
|
||||
position: absolute;
|
||||
left: 227px;
|
||||
top: 144px;
|
||||
top: 154px;
|
||||
font-size: 14px;
|
||||
|
||||
line-height: 30px;
|
||||
color: white;
|
||||
opacity: 1;
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
margin-left: 16px;
|
||||
font-size: 15px;
|
||||
line-height: 31px;
|
||||
cursor: pointer;
|
||||
}
|
||||
.delete-shelf-icon {
|
||||
cursor: pointer;
|
||||
|
||||
@@ -54,7 +54,7 @@ class BookList extends React.Component<BookListProps, BookListState> {
|
||||
//根据不同的场景获取不同的图书数据
|
||||
let books = !this.props.isSort
|
||||
? this.handleKeyFilter(this.props.deletedBooks, AddTrash.getAllTrash())
|
||||
: this.props.isSort
|
||||
: this.props.isSort && !this.props.noteSortCode
|
||||
? this.handleIndexFilter(
|
||||
this.handleKeyFilter(this.props.deletedBooks, AddTrash.getAllTrash()),
|
||||
//返回排序后的图书index
|
||||
@@ -63,7 +63,7 @@ class BookList extends React.Component<BookListProps, BookListState> {
|
||||
this.props.bookSortCode
|
||||
) || []
|
||||
)
|
||||
: this.props.isSort
|
||||
: this.props.isSort && !this.props.noteSortCode
|
||||
? this.handleIndexFilter(
|
||||
this.props.deletedBooks,
|
||||
//返回排序后的图书index
|
||||
|
||||
@@ -15,6 +15,7 @@ const mappropsToProps = (state: stateType) => {
|
||||
isSort: state.manager.isSort,
|
||||
isList: state.manager.isList,
|
||||
bookSortCode: state.manager.bookSortCode,
|
||||
noteSortCode: state.manager.noteSortCode,
|
||||
};
|
||||
};
|
||||
const actionCreator = {
|
||||
|
||||
@@ -7,6 +7,7 @@ export interface BookListProps extends RouteComponentProps<any> {
|
||||
isSort: boolean;
|
||||
isList: string;
|
||||
bookSortCode: { sort: number; order: number };
|
||||
noteSortCode: { sort: number; order: number };
|
||||
handleFetchList: () => void;
|
||||
handleMode: (mode: string) => void;
|
||||
handleDeleteDialog: (isShow: boolean) => void;
|
||||
|
||||
@@ -29,15 +29,21 @@ class EmptyPage extends React.Component<EmptyPageProps, EmptyPageState> {
|
||||
};
|
||||
return (
|
||||
<div className="empty-page-container">
|
||||
<img
|
||||
src={
|
||||
process.env.NODE_ENV === "production"
|
||||
? "./assets/empty.svg"
|
||||
: "../../assets/empty.svg"
|
||||
}
|
||||
alt=""
|
||||
className="empty-page-illustration"
|
||||
/>
|
||||
<div
|
||||
className="empty-illustration-container"
|
||||
style={{ width: "calc(100% - 50px)" }}
|
||||
>
|
||||
<img
|
||||
src={
|
||||
process.env.NODE_ENV === "production"
|
||||
? "./assets/empty.svg"
|
||||
: "../../assets/empty.svg"
|
||||
}
|
||||
alt=""
|
||||
className="empty-page-illustration"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{renderEmptyList()}
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -7,11 +7,16 @@
|
||||
overflow: hidden;
|
||||
}
|
||||
.empty-page-illustration {
|
||||
height: 100%;
|
||||
}
|
||||
.empty-illustration-container {
|
||||
height: 450px;
|
||||
position: absolute;
|
||||
right: 0;
|
||||
bottom: 0;
|
||||
width: 787px;
|
||||
|
||||
z-index: -1;
|
||||
overflow: hidden;
|
||||
}
|
||||
.empty-page-info-container {
|
||||
position: absolute;
|
||||
|
||||
@@ -26,6 +26,7 @@ class Reader extends React.Component<ReaderProps, ReaderState> {
|
||||
isMessage: false,
|
||||
rendition: null,
|
||||
scale: OtherUtil.getReaderConfig("scale") || 1,
|
||||
margin: OtherUtil.getReaderConfig("margin") || 30,
|
||||
time: ReadingTime.getTime(this.props.currentBook.key),
|
||||
isTouch: OtherUtil.getReaderConfig("isTouch") === "yes",
|
||||
readerMode: OtherUtil.getReaderConfig("readerMode") || "double",
|
||||
@@ -57,12 +58,7 @@ class Reader extends React.Component<ReaderProps, ReaderState> {
|
||||
this.rendition = epub.renderTo(page, {
|
||||
manager:
|
||||
this.state.readerMode === "continuous" ? "continuous" : "default",
|
||||
flow:
|
||||
this.state.readerMode === "scroll"
|
||||
? "scrolled-doc"
|
||||
: this.state.readerMode === "continuous"
|
||||
? "scrolled"
|
||||
: "auto",
|
||||
flow: this.state.readerMode === "continuous" ? "scrolled" : "auto",
|
||||
width: "100%",
|
||||
height: "100%",
|
||||
snap: true,
|
||||
@@ -70,9 +66,7 @@ class Reader extends React.Component<ReaderProps, ReaderState> {
|
||||
OtherUtil.getReaderConfig("readerMode") === "single" ? "none" : "",
|
||||
});
|
||||
this.setState({ rendition: this.rendition });
|
||||
this.state.readerMode !== "scroll" &&
|
||||
this.state.readerMode !== "continuous" &&
|
||||
MouseEvent(this.rendition); // 绑定事件
|
||||
this.state.readerMode !== "continuous" && MouseEvent(this.rendition); // 绑定事件
|
||||
this.tickTimer = setInterval(() => {
|
||||
let time = this.state.time;
|
||||
time += 1;
|
||||
@@ -168,6 +162,17 @@ class Reader extends React.Component<ReaderProps, ReaderState> {
|
||||
>
|
||||
<span className="icon-dropdown next-chapter-single"></span>
|
||||
</div>
|
||||
<div
|
||||
className="reader-setting-icon-container"
|
||||
onClick={() => {
|
||||
this.handleEnterReader("left");
|
||||
this.handleEnterReader("right");
|
||||
this.handleEnterReader("bottom");
|
||||
this.handleEnterReader("top");
|
||||
}}
|
||||
>
|
||||
<span className="icon-setting reader-setting-icon"></span>
|
||||
</div>
|
||||
{this.state.isMessage ? <MessageBox /> : null}
|
||||
<div
|
||||
className="left-panel"
|
||||
@@ -294,7 +299,6 @@ class Reader extends React.Component<ReaderProps, ReaderState> {
|
||||
className="view-area-page"
|
||||
id="page-area"
|
||||
style={
|
||||
this.state.readerMode === "scroll" ||
|
||||
this.state.readerMode === "continuous"
|
||||
? {
|
||||
left: `calc(50vw - ${270 * parseFloat(this.state.scale)}px)`,
|
||||
@@ -307,6 +311,11 @@ class Reader extends React.Component<ReaderProps, ReaderState> {
|
||||
left: `calc(50vw - ${270 * parseFloat(this.state.scale)}px)`,
|
||||
right: `calc(50vw - ${270 * parseFloat(this.state.scale)}px)`,
|
||||
}
|
||||
: this.state.readerMode === "double"
|
||||
? {
|
||||
left: this.state.margin + "px",
|
||||
right: this.state.margin + "px",
|
||||
}
|
||||
: {}
|
||||
}
|
||||
></div>
|
||||
|
||||
@@ -21,4 +21,5 @@ export interface ReaderState {
|
||||
rendition: any;
|
||||
time: number;
|
||||
scale: string;
|
||||
margin: string;
|
||||
}
|
||||
|
||||
@@ -133,8 +133,8 @@
|
||||
}
|
||||
.view-area-page {
|
||||
position: absolute;
|
||||
left: 30px;
|
||||
right: 30px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
top: 30px;
|
||||
bottom: 30px;
|
||||
/* width: calc(100% - 100px);
|
||||
@@ -155,7 +155,7 @@
|
||||
font-size: 30px;
|
||||
transform: rotate(90deg);
|
||||
cursor: pointer;
|
||||
opacity: 0.1;
|
||||
opacity: 0.05;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -173,7 +173,7 @@
|
||||
right: 20px;
|
||||
transform: rotate(-90deg);
|
||||
cursor: pointer;
|
||||
opacity: 0.1;
|
||||
opacity: 0.05;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
@@ -193,3 +193,12 @@
|
||||
font-size: 20px;
|
||||
height: 20px;
|
||||
}
|
||||
.reader-setting-icon-container {
|
||||
position: absolute;
|
||||
top: 15px;
|
||||
right: 20px;
|
||||
font-size: 27px;
|
||||
opacity: 0.1;
|
||||
cursor: pointer;
|
||||
z-index: 10;
|
||||
}
|
||||
|
||||
@@ -71,6 +71,11 @@ class Header extends React.Component<HeaderProps, HeaderState> {
|
||||
onClick={() => {
|
||||
this.props.handleBackupDialog(true);
|
||||
}}
|
||||
style={
|
||||
OtherUtil.getReaderConfig("lang") === "en"
|
||||
? { fontSize: "14px" }
|
||||
: {}
|
||||
}
|
||||
>
|
||||
<Trans>Backup and Restore</Trans>
|
||||
</div>
|
||||
|
||||
@@ -10,6 +10,16 @@
|
||||
left: 265px;
|
||||
top: 29px;
|
||||
cursor: pointer;
|
||||
transition: 0.1s;
|
||||
width: 48px;
|
||||
height: 27px;
|
||||
padding-left: 8px;
|
||||
transition: 0.1s;
|
||||
}
|
||||
.header-sort-container:hover,
|
||||
.setting-icon-container:hover {
|
||||
background-color: rgba(75, 75, 75, 0.035);
|
||||
border-radius: 8px;
|
||||
}
|
||||
.header-sort-text,
|
||||
.download-demo-book {
|
||||
@@ -73,6 +83,7 @@
|
||||
color: #4b4b4b;
|
||||
box-sizing: border-box;
|
||||
cursor: pointer;
|
||||
transition: 0.1s;
|
||||
}
|
||||
.import-from-cloud:hover {
|
||||
background-color: rgba(75, 75, 75, 0.035);
|
||||
@@ -113,12 +124,15 @@
|
||||
font-size: 25px;
|
||||
}
|
||||
.setting-icon-container {
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
width: 32px;
|
||||
height: 35px;
|
||||
font-size: 25px;
|
||||
line-height: 37px;
|
||||
position: absolute;
|
||||
left: 335px;
|
||||
top: 33px;
|
||||
top: 25px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
cursor: pointer;
|
||||
transition: 0.1s;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
@@ -145,14 +145,17 @@ class NavigationPanel extends React.Component<
|
||||
<div className="navigation-panel">
|
||||
{this.state.isSearch ? (
|
||||
<>
|
||||
<span
|
||||
className="icon-close nav-close-icon"
|
||||
onClick={() => {
|
||||
this.handleSearchState(false);
|
||||
this.props.handleSearch(false);
|
||||
this.setState({ searchList: null });
|
||||
}}
|
||||
></span>
|
||||
<div className="nav-close-icon">
|
||||
<span
|
||||
className="icon-close"
|
||||
onClick={() => {
|
||||
this.handleSearchState(false);
|
||||
this.props.handleSearch(false);
|
||||
this.setState({ searchList: null });
|
||||
}}
|
||||
></span>
|
||||
</div>
|
||||
|
||||
<div
|
||||
className="header-search-container"
|
||||
style={this.state.isSearch ? { left: 40 } : {}}
|
||||
|
||||
@@ -142,6 +142,13 @@
|
||||
right: 10px;
|
||||
top: 10px;
|
||||
font-size: 20px;
|
||||
transition: 0.1s;
|
||||
width: 38px;
|
||||
height: 38px;
|
||||
}
|
||||
.nav-close-icon:hover {
|
||||
background-color: rgba(75, 75, 75, 0.035);
|
||||
border-radius: 50%;
|
||||
}
|
||||
.nav-search-list {
|
||||
position: absolute;
|
||||
@@ -159,7 +166,7 @@
|
||||
}
|
||||
.content-search-text {
|
||||
color: red !important;
|
||||
font-weight: bold !important;
|
||||
font-weight: 600 !important;
|
||||
}
|
||||
.nav-search-page {
|
||||
position: absolute;
|
||||
|
||||
@@ -18,7 +18,10 @@ class SettingPanel extends React.Component<
|
||||
this.state = {
|
||||
isSupported: false,
|
||||
isAudioOn: false,
|
||||
readerMode: OtherUtil.getReaderConfig("readerMode"),
|
||||
readerMode: OtherUtil.getReaderConfig("readerMode") || "double",
|
||||
isUseBackground: OtherUtil.getReaderConfig("isUseBackground") === "yes",
|
||||
isShowFooter: OtherUtil.getReaderConfig("isShowFooter") !== "no",
|
||||
isShowHeader: OtherUtil.getReaderConfig("isShowHeader") !== "no",
|
||||
};
|
||||
}
|
||||
componentDidMount() {
|
||||
@@ -76,6 +79,45 @@ class SettingPanel extends React.Component<
|
||||
};
|
||||
});
|
||||
};
|
||||
handleChangeBackground = () => {
|
||||
this.setState({ isUseBackground: !this.state.isUseBackground });
|
||||
OtherUtil.setReaderConfig(
|
||||
"isUseBackground",
|
||||
this.state.isUseBackground ? "no" : "yes"
|
||||
);
|
||||
this.state.isUseBackground
|
||||
? this.props.handleMessage("Turn Off Successfully")
|
||||
: this.props.handleMessage("Turn On Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
};
|
||||
handleFooter = () => {
|
||||
this.setState({ isShowFooter: !this.state.isShowFooter });
|
||||
OtherUtil.setReaderConfig(
|
||||
"isShowFooter",
|
||||
this.state.isShowFooter ? "no" : "yes"
|
||||
);
|
||||
this.state.isShowFooter
|
||||
? this.props.handleMessage("Turn On Successfully")
|
||||
: this.props.handleMessage("Turn Off Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
};
|
||||
handleHeader = () => {
|
||||
this.setState({ isShowHeader: !this.state.isShowHeader });
|
||||
OtherUtil.setReaderConfig(
|
||||
"isShowHeader",
|
||||
this.state.isShowHeader ? "no" : "yes"
|
||||
);
|
||||
this.state.isShowHeader
|
||||
? this.props.handleMessage("Turn On Successfully")
|
||||
: this.props.handleMessage("Turn Off Successfully");
|
||||
this.props.handleMessageBox(true);
|
||||
setTimeout(() => {
|
||||
window.location.reload();
|
||||
}, 500);
|
||||
};
|
||||
render() {
|
||||
return (
|
||||
<div className="setting-panel-parent">
|
||||
@@ -85,35 +127,6 @@ class SettingPanel extends React.Component<
|
||||
</div>
|
||||
<ModeControl />
|
||||
|
||||
{this.state.isSupported ? (
|
||||
<div className="single-control-switch-container">
|
||||
<span className="single-control-switch-title">
|
||||
{this.state.isAudioOn ? (
|
||||
<Trans>Turn off audio</Trans>
|
||||
) : (
|
||||
<Trans>Turn on audio</Trans>
|
||||
)}
|
||||
</span>
|
||||
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
if (this.props.locations) {
|
||||
this.handleChangeAudio();
|
||||
} else {
|
||||
this.props.handleMessage("Audio is not ready yet");
|
||||
this.props.handleMessageBox(true);
|
||||
}
|
||||
}}
|
||||
style={this.props.locations ? {} : { opacity: 0.5 }}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={this.state.isAudioOn ? { float: "right" } : {}}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
<ThemeList />
|
||||
<SliderList
|
||||
{...{
|
||||
@@ -122,6 +135,13 @@ class SettingPanel extends React.Component<
|
||||
mode: "fontSize",
|
||||
}}
|
||||
/>
|
||||
<SliderList
|
||||
{...{
|
||||
maxValue: 50,
|
||||
minValue: 0,
|
||||
mode: "margin",
|
||||
}}
|
||||
/>
|
||||
{this.state.readerMode && this.state.readerMode !== "double" ? (
|
||||
<SliderList
|
||||
{...{
|
||||
@@ -133,6 +153,152 @@ class SettingPanel extends React.Component<
|
||||
) : null}
|
||||
|
||||
<DropdownList />
|
||||
{this.state.isSupported ? (
|
||||
<div className="single-control-switch-container">
|
||||
<span className="single-control-switch-title">
|
||||
<Trans>Turn on audio</Trans>
|
||||
</span>
|
||||
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
if (this.props.locations) {
|
||||
this.handleChangeAudio();
|
||||
} else {
|
||||
this.props.handleMessage("Audio is not ready yet");
|
||||
this.props.handleMessageBox(true);
|
||||
}
|
||||
}}
|
||||
style={
|
||||
this.props.locations
|
||||
? this.state.isAudioOn
|
||||
? { background: "rgba(46, 170, 220)" }
|
||||
: {}
|
||||
: { opacity: 0.5 }
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={
|
||||
this.state.isAudioOn
|
||||
? {
|
||||
transform: "translateX(20px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
: {
|
||||
transform: "translateX(0px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
) : null}
|
||||
<div
|
||||
className="single-control-switch-container"
|
||||
style={
|
||||
this.state.isAudioOn ? { background: "rgba(46, 170, 220)" } : {}
|
||||
}
|
||||
>
|
||||
<span className="single-control-switch-title">
|
||||
<Trans>Don't show footer</Trans>
|
||||
</span>
|
||||
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
this.handleFooter();
|
||||
}}
|
||||
style={
|
||||
!this.state.isShowFooter
|
||||
? { background: "rgba(46, 170, 220)", float: "right" }
|
||||
: { float: "right" }
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={
|
||||
this.state.isShowFooter
|
||||
? {
|
||||
transform: "translateX(0px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
: {
|
||||
transform: "translateX(20px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
className="single-control-switch-container"
|
||||
style={
|
||||
this.state.isAudioOn ? { background: "rgba(46, 170, 220)" } : {}
|
||||
}
|
||||
>
|
||||
<span className="single-control-switch-title">
|
||||
<Trans>Don't show header</Trans>
|
||||
</span>
|
||||
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
this.handleHeader();
|
||||
}}
|
||||
style={
|
||||
!this.state.isShowHeader
|
||||
? { background: "rgba(46, 170, 220)", float: "right" }
|
||||
: { float: "right" }
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={
|
||||
this.state.isShowHeader
|
||||
? {
|
||||
transform: "translateX(0px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
: {
|
||||
transform: "translateX(20px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
<div className="single-control-switch-container">
|
||||
<span className="single-control-switch-title">
|
||||
<Trans>Dont't use mimical background</Trans>
|
||||
</span>
|
||||
<span
|
||||
className="single-control-switch"
|
||||
onClick={() => {
|
||||
this.handleChangeBackground();
|
||||
}}
|
||||
style={
|
||||
this.state.isUseBackground
|
||||
? { background: "rgba(46, 170, 220)", float: "right" }
|
||||
: { float: "right" }
|
||||
}
|
||||
>
|
||||
<span
|
||||
className="single-control-button"
|
||||
style={
|
||||
this.state.isUseBackground
|
||||
? {
|
||||
transform: "translateX(20px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
: {
|
||||
transform: "translateX(0px)",
|
||||
transition: "transform 0.5s ease",
|
||||
}
|
||||
}
|
||||
></span>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -9,4 +9,7 @@ export interface SettingPanelState {
|
||||
isSupported: boolean;
|
||||
isAudioOn: boolean;
|
||||
readerMode: string;
|
||||
isUseBackground: boolean;
|
||||
isShowFooter: boolean;
|
||||
isShowHeader: boolean;
|
||||
}
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
align-items: center;
|
||||
width: calc(100% - 44px);
|
||||
height: 38px;
|
||||
font-size: 16px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
font-weight: 500;
|
||||
margin: 6px 22px;
|
||||
}
|
||||
.setting-panel-parent {
|
||||
@@ -28,27 +28,27 @@
|
||||
overflow-y: scroll;
|
||||
padding-right: 17px; /* Increase/decrease this value for cross-browser compatibility */
|
||||
box-sizing: content-box;
|
||||
|
||||
/* display: none; */
|
||||
}
|
||||
.single-control-switch-container {
|
||||
margin: 10px 0px 15px;
|
||||
margin-left: 50px;
|
||||
margin: 15px 20px 10px;
|
||||
height: 20px;
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
cursor: pointer;
|
||||
}
|
||||
.single-control-switch-title {
|
||||
font-size: 16px;
|
||||
line-height: 16px;
|
||||
color: #4b4b4b;
|
||||
opacity: 1;
|
||||
margin: 0px 10px 0px 30px;
|
||||
position: relative;
|
||||
bottom: 2px;
|
||||
color: rgba(75, 75, 75, 1);
|
||||
font-weight: 500;
|
||||
}
|
||||
.single-control-switch {
|
||||
display: inline-block;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
background: #000000;
|
||||
background: rgba(75, 75, 75, 1);
|
||||
opacity: 1;
|
||||
border-radius: 10px;
|
||||
position: relative;
|
||||
@@ -60,6 +60,6 @@
|
||||
height: 16px;
|
||||
width: 16px;
|
||||
border-radius: 50%;
|
||||
border: 2px solid black;
|
||||
background-color: white;
|
||||
margin: 2px;
|
||||
}
|
||||
|
||||
@@ -88,15 +88,7 @@
|
||||
color: rgba(75, 75, 75, 0.5);
|
||||
opacity: 1;
|
||||
}
|
||||
.icon-more {
|
||||
margin-left: 93px;
|
||||
/* line-height: 29px; */
|
||||
position: relative;
|
||||
top: 6px;
|
||||
}
|
||||
.icon-shelf {
|
||||
/* margin-right: 12px; */
|
||||
}
|
||||
|
||||
.sidebar-dropdown {
|
||||
font-size: 13px;
|
||||
}
|
||||
|
||||
@@ -154,23 +154,27 @@ class Manager extends React.Component<ManagerProps, ManagerState> {
|
||||
)}
|
||||
<Sidebar />
|
||||
<Header {...{ handleDrag: this.handleDrag }} />
|
||||
<div className="manager-dialog-container">
|
||||
{this.props.isOpenDeleteDialog ? (
|
||||
<DeleteDialog />
|
||||
) : this.props.isOpenEditDialog ? (
|
||||
<EditDialog />
|
||||
) : this.props.isOpenAddDialog ? (
|
||||
<AddDialog />
|
||||
) : null}
|
||||
</div>
|
||||
{this.props.isMessage ? <MessageBox /> : null}
|
||||
{this.props.isSortDisplay ? <SortDialog /> : null}
|
||||
{this.props.isBackup ? <BackupDialog /> : null}
|
||||
{this.props.isFirst === "yes" ? <WelcomeDialog /> : null}
|
||||
{this.state.isUpdated && this.props.isFirst === "no" ? (
|
||||
{this.props.isOpenDeleteDialog && <DeleteDialog />}
|
||||
{this.props.isOpenEditDialog && <EditDialog />}
|
||||
{this.props.isOpenAddDialog && <AddDialog />}
|
||||
{(this.props.isSettingOpen ||
|
||||
this.props.isBackup ||
|
||||
this.props.isOpenDeleteDialog ||
|
||||
this.props.isOpenEditDialog ||
|
||||
this.props.isOpenAddDialog ||
|
||||
this.props.isFirst === "yes" ||
|
||||
(this.state.isUpdated && this.props.isFirst === "no")) && (
|
||||
<div className="drag-background"></div>
|
||||
)}
|
||||
|
||||
{this.props.isMessage && <MessageBox />}
|
||||
{this.props.isSortDisplay && <SortDialog />}
|
||||
{this.props.isBackup && <BackupDialog />}
|
||||
{this.props.isFirst === "yes" && <WelcomeDialog />}
|
||||
{this.state.isUpdated && this.props.isFirst === "no" && (
|
||||
<UpdateDialog {...updateDialogProps} />
|
||||
) : null}
|
||||
{this.props.isSettingOpen ? <SettingDialog /> : null}
|
||||
)}
|
||||
{this.props.isSettingOpen && <SettingDialog />}
|
||||
{(!books || books.length === 0) && this.state.totalBooks ? (
|
||||
<Redirect to="/manager/loading" />
|
||||
) : (
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
height: 100%;
|
||||
top: 0px;
|
||||
left: 0px;
|
||||
z-index: 10;
|
||||
z-index: 9;
|
||||
}
|
||||
.drag-info {
|
||||
width: 200px;
|
||||
@@ -50,7 +50,7 @@
|
||||
text-align: center;
|
||||
margin: 50px 0px 20px;
|
||||
font-size: 40px;
|
||||
font-weight: bold;
|
||||
font-weight: 600;
|
||||
}
|
||||
.waring-pic {
|
||||
width: 100vw;
|
||||
|
||||