Compare commits

...

14 Commits

Author SHA1 Message Date
Aria Moradi d2a72526f6 bump to v0.3.6
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-18 21:40:42 +04:30
Aria Moradi 0a9f57b32b cleanup 2021-05-18 21:38:41 +04:30
Aria Moradi 180f210536 update windows instructions 2021-05-18 21:35:57 +04:30
Aria Moradi c1baa31eed the new and simple way of packaging windows 2021-05-18 21:31:25 +04:30
Aria Moradi cacc97cec7 bump to v0.3.5
CI Publish / Validate Gradle Wrapper (push) Successful in 11s
CI Publish / Build FatJar (push) Failing after 16s
2021-05-18 02:39:00 +04:30
Aria Moradi d5691fd81c show last read page on initial load 2021-05-18 02:26:45 +04:30
Aria Moradi 49dc9fe5f6 fix wrong chapter count, abstract next page 2021-05-18 01:10:28 +04:30
Aria Moradi c0b49c7428 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-18 00:45:42 +04:30
Aria Moradi fa345af42d use Dispatchers.IO 2021-05-18 00:43:32 +04:30
Aria Moradi db3cc786a1 rename the job 2021-05-18 00:43:21 +04:30
Aria Moradi fe879ae51d [SKIP CI] update windows instructions 2021-05-18 00:01:04 +04:30
Aria Moradi 2f55460ffb unzip the jre
CI Publish / Validate Gradle Wrapper (push) Successful in 14s
CI Publish / Build FatJar (push) Failing after 17s
2021-05-17 23:33:54 +04:30
Aria Moradi fbc5bd4642 bump to v0.3.4 2021-05-17 23:29:36 +04:30
Aria Moradi 5e0c7d3c9d ditch packr because it can't load extension jars 2021-05-17 23:28:23 +04:30
17 changed files with 99 additions and 59 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ jobs:
uses: gradle/wrapper-validation-action@v1 uses: gradle/wrapper-validation-action@v1
build: build:
name: Build FatJar name: Build artifacts and deploy preview
needs: check_wrapper needs: check_wrapper
if: "!startsWith(github.event.head_commit.message, '[SKIP CI]')" if: "!startsWith(github.event.head_commit.message, '[SKIP CI]')"
runs-on: ubuntu-latest runs-on: ubuntu-latest
+1 -1
View File
@@ -38,7 +38,7 @@ Run `./gradlew :webUI:copyBuild server:shadowJar`, the resulting built jar file
### building without `webUI` bundled(server only) ### building without `webUI` bundled(server only)
Delete the `server/src/main/resources/react` directory if exists from previous runs, then run `./gradlew server:shadowJar`, the resulting built jar file will be `server/build/Tachidesk-vX.Y.Z-rxxx.jar`. Delete the `server/src/main/resources/react` directory if exists from previous runs, then run `./gradlew server:shadowJar`, the resulting built jar file will be `server/build/Tachidesk-vX.Y.Z-rxxx.jar`.
### building the Windows package ### building the Windows package
Run `./gradlew :server:windowsPackage` to build a server only bundle and `./gradlew :webUI:copyBuild :server:windowsPackage` to get a full bundle , the resulting built zip package file will be `server/build/Tachidesk-vX.Y.Z-rxxx-win32.zip`. First Build the jar, then cd into the `scripts` directory and run `./windows-bundler.sh`, the resulting built zip package file will be `server/build/Tachidesk-vX.Y.Z-rxxx-win64.zip`.
## Running in development mode ## Running in development mode
First satistify [the prerequisites](#prerequisites) First satistify [the prerequisites](#prerequisites)
### server ### server
+1 -1
View File
@@ -37,7 +37,7 @@ Double click on the jar file or run `java -jar Tachidesk-vX.Y.Z-rxxx.jar` (or `j
### Windows ### Windows
Download the latest win32 release from [the releases section](https://github.com/Suwayomi/Tachidesk/releases). Download the latest win32 release from [the releases section](https://github.com/Suwayomi/Tachidesk/releases).
The Windows specific build has java bundled inside, so you don't have to install java to use it. Unzip `Tachidesk-vX.Y.Z-rxxx-win32.zip` and run `server.exe`. The rest works like the previous section. The Windows specific build has java bundled inside, so you don't have to install java to use it. Unzip `Tachidesk-vX.Y.Z-rxxx-win64.zip` and run `Tachidesk.bat`. The rest works like the previous section.
### Arch Linux ### Arch Linux
You can install Tachidesk from the AUR You can install Tachidesk from the AUR
+1
View File
@@ -0,0 +1 @@
start "" jre/bin/javaw -jar Tachidesk.jar
+5
View File
@@ -0,0 +1,5 @@
#include <stdlib.h>
int main() {
system("start jre\\bin\\javaw -jar Tachidesk.jar");
}
Binary file not shown.
+3
View File
@@ -0,0 +1,3 @@
# Building `Tachidesk Launcher.exe`
1. compile `Tachidesk Launcher.c` statically using GCC MinGW: `gcc -o "Tachidesk Launcher.exe" "Tachidesk Launcher.c"`
2. Add `server/src/main/resources/icon/faviconlogo.ico` into the exe with `rcedit` from the electron project: `rcedit "Tachidesk Launcher.exe" --set-icon "faviconlogo.ico"`
+17 -17
View File
@@ -6,15 +6,12 @@
# License, v. 2.0. If a copy of the MPL was not distributed with this # License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at https://mozilla.org/MPL/2.0/. # file, You can obtain one at https://mozilla.org/MPL/2.0/.
echo "Downloading packr jar..."
packr="packr-all-4.0.0.jar"
curl -L "https://github.com/libgdx/packr/releases/download/4.0.0/packr-all-4.0.0.jar" -o $packr
echo "Downloading jre..." echo "Downloading jre..."
jre="OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip" jre="OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip"
curl -L "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip" -o $jre if [ ! -f $jre ]; then
curl -L "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip" -o $jre
fi
echo "creating windows bundle" echo "creating windows bundle"
@@ -22,20 +19,23 @@ jar=$(ls ../server/build/Tachidesk-*.jar)
jar_name=$(echo $jar | cut -d'/' -f4) jar_name=$(echo $jar | cut -d'/' -f4)
release_name=$(echo $jar_name | cut -d'.' -f4 --complement)-win64 release_name=$(echo $jar_name | cut -d'.' -f4 --complement)-win64
cp $jar "Tachidesk.jar" # make release dir
mkdir $release_name
java -jar $packr \ unzip $jre
--platform windows64 \
--jdk $jre \
--executable Tachidesk \
--classpath Tachidesk.jar \
--mainclass ir.armor.tachidesk.MainKt \
--vmargs Xmx4G \
--output $release_name
cp resources/Tachidesk-debug.bat $release_name # move jre
mv jdk8u292-b10-jre $release_name/jre
cp $jar $release_name/Tachidesk.jar
cp "resources/Tachidesk Launcher.exe" $release_name
cp "resources/Tachidesk Launcher.bat" $release_name
cp "resources/Tachidesk Debug Launcher.bat" $release_name
zip_name=$release_name.zip zip_name=$release_name.zip
zip -9 -r $zip_name $release_name zip -9 -r $zip_name $release_name
cp $zip_name ../server/build/ rm -rf $release_name
mv $zip_name ../server/build/
+3 -18
View File
@@ -8,7 +8,6 @@ plugins {
application application
id("com.github.johnrengelman.shadow") version "7.0.0" id("com.github.johnrengelman.shadow") version "7.0.0"
id("org.jmailen.kotlinter") version "3.4.3" id("org.jmailen.kotlinter") version "3.4.3"
id("edu.sc.seis.launch4j") version "2.5.0"
id("de.fuerstenau.buildconfig") version "1.1.8" id("de.fuerstenau.buildconfig") version "1.1.8"
} }
@@ -97,7 +96,7 @@ sourceSets {
} }
// should be bumped with each stable release // should be bumped with each stable release
val tachideskVersion = "v0.3.3" val tachideskVersion = "v0.3.6"
// counts commit count on master // counts commit count on master
val tachideskRevision = Runtime val tachideskRevision = Runtime
@@ -126,18 +125,8 @@ buildConfig {
buildConfigField("boolean", "debug", project.hasProperty("debugApp").toString()) buildConfigField("boolean", "debug", project.hasProperty("debugApp").toString())
} }
launch4j { //used for windows
mainClassName = MainClass
bundledJrePath = "jre"
bundledJre64Bit = true
jreMinVersion = "8"
outputDir = "${rootProject.name}-$tachideskVersion-$tachideskRevision-win64"
icon = "${projectDir}/src/main/resources/icon/faviconlogo.ico"
jar = "${projectDir}/build/${rootProject.name}-$tachideskVersion-$tachideskRevision.jar"
}
tasks { tasks {
jar { shadowJar {
manifest { manifest {
attributes( attributes(
mapOf( mapOf(
@@ -149,9 +138,6 @@ tasks {
) )
) )
} }
}
shadowJar {
manifest.inheritFrom(jar.get().manifest) //will make your shadowJar (produced by jar task) runnable
archiveBaseName.set(rootProject.name) archiveBaseName.set(rootProject.name)
archiveVersion.set(tachideskVersion) archiveVersion.set(tachideskVersion)
archiveClassifier.set(tachideskRevision) archiveClassifier.set(tachideskRevision)
@@ -165,11 +151,11 @@ tasks {
) )
} }
} }
test { test {
useJUnit() useJUnit()
} }
withType<ShadowJar> { withType<ShadowJar> {
destinationDirectory.set(File("$rootDir/server/build")) destinationDirectory.set(File("$rootDir/server/build"))
dependsOn("formatKotlin", "lintKotlin") dependsOn("formatKotlin", "lintKotlin")
@@ -192,4 +178,3 @@ tasks {
source(files("src")) source(files("src"))
} }
} }
@@ -22,7 +22,6 @@ import org.jetbrains.exposed.sql.and
import org.jetbrains.exposed.sql.deleteWhere import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.select import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update import org.jetbrains.exposed.sql.update
@@ -139,7 +138,7 @@ object Chapter {
).awaitSingle() ).awaitSingle()
val chapterId = chapterEntry[ChapterTable.id].value val chapterId = chapterEntry[ChapterTable.id].value
val chapterCount = transaction { ChapterTable.selectAll().count() } val chapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }
// update page list for this chapter // update page list for this chapter
transaction { transaction {
@@ -36,14 +36,14 @@ import ir.armor.tachidesk.impl.backup.legacy.LegacyBackupImport.restoreLegacyBac
import ir.armor.tachidesk.server.internal.About.getAbout import ir.armor.tachidesk.server.internal.About.getAbout
import ir.armor.tachidesk.server.util.openInBrowser import ir.armor.tachidesk.server.util.openInBrowser
import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.asCoroutineDispatcher import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.future.future import kotlinx.coroutines.future.future
import mu.KotlinLogging import mu.KotlinLogging
import java.io.IOException import java.io.IOException
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.concurrent.CompletableFuture import java.util.concurrent.CompletableFuture
import java.util.concurrent.Executors
import kotlin.concurrent.thread import kotlin.concurrent.thread
/* /*
@@ -56,7 +56,7 @@ import kotlin.concurrent.thread
object JavalinSetup { object JavalinSetup {
private val logger = KotlinLogging.logger {} private val logger = KotlinLogging.logger {}
private val scope = CoroutineScope(Executors.newFixedThreadPool(200).asCoroutineDispatcher()) private val scope = CoroutineScope(SupervisorJob() + Dispatchers.IO)
private fun <T> future(block: suspend CoroutineScope.() -> T): CompletableFuture<T> { private fun <T> future(block: suspend CoroutineScope.() -> T): CompletableFuture<T> {
return scope.future(block = block) return scope.future(block = block)
+11 -7
View File
@@ -60,11 +60,13 @@ function LazyImage(props: IProps) {
}; };
useEffect(() => { useEffect(() => {
window.addEventListener('scroll', handleScroll); if (settings.readerType === 'Webtoon' || settings.readerType === 'ContinuesVertical') {
window.addEventListener('scroll', handleScroll);
return () => { return () => {
window.removeEventListener('scroll', handleScroll); window.removeEventListener('scroll', handleScroll);
}; };
} return () => {};
}, [handleScroll]); }, [handleScroll]);
useEffect(() => { useEffect(() => {
@@ -92,14 +94,14 @@ function LazyImage(props: IProps) {
); );
} }
export default function Page(props: IProps) { const Page = React.forwardRef((props: IProps, ref: any) => {
const { const {
src, index, setCurPage, settings, src, index, setCurPage, settings,
} = props; } = props;
const classes = useStyles(settings)(); const classes = useStyles(settings)();
return ( return (
<div style={{ margin: '0 auto' }}> <div ref={ref} style={{ margin: '0 auto' }}>
<LazyImage <LazyImage
src={src} src={src}
index={index} index={index}
@@ -108,4 +110,6 @@ export default function Page(props: IProps) {
/> />
</div> </div>
); );
} });
export default Page;
@@ -24,7 +24,7 @@ const useStyles = makeStyles({
export default function PagedReader(props: IReaderProps) { export default function PagedReader(props: IReaderProps) {
const { const {
pages, settings, setCurPage, curPage, manga, chapter, pages, settings, setCurPage, curPage, manga, chapter, nextChapter,
} = props; } = props;
const classes = useStyles(); const classes = useStyles();
@@ -36,7 +36,7 @@ export default function PagedReader(props: IReaderProps) {
if (curPage < pages.length - 1) { if (curPage < pages.length - 1) {
setCurPage(curPage + 1); setCurPage(curPage + 1);
} else if (settings.loadNextonEnding) { } else if (settings.loadNextonEnding) {
history.push(`/manga/${manga.id}/chapter/${chapter.index + 1}`); nextChapter();
} }
} }
@@ -7,7 +7,7 @@
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */ * file, You can obtain one at https://mozilla.org/MPL/2.0/. */
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import React, { useEffect } from 'react'; import React, { useEffect, useRef, useState } from 'react';
import { useHistory } from 'react-router-dom'; import { useHistory } from 'react-router-dom';
import Page from '../Page'; import Page from '../Page';
@@ -23,16 +23,18 @@ const useStyles = makeStyles({
export default function VerticalReader(props: IReaderProps) { export default function VerticalReader(props: IReaderProps) {
const { const {
pages, settings, setCurPage, curPage, manga, chapter, pages, settings, setCurPage, curPage, manga, chapter, nextChapter,
} = props; } = props;
const classes = useStyles(); const classes = useStyles();
const history = useHistory(); const history = useHistory();
const [initialScroll, setInitialScroll] = useState(-1);
const initialPageRef = useRef<HTMLDivElement>(null);
const handleLoadNextonEnding = () => { const handleLoadNextonEnding = () => {
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) { if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight) {
setCurPage(0); nextChapter();
history.push(`/manga/${manga.id}/chapter/${chapter.index + 1}`);
} }
}; };
useEffect(() => { useEffect(() => {
@@ -43,6 +45,18 @@ export default function VerticalReader(props: IReaderProps) {
}; };
}, []); }, []);
useEffect(() => {
if ((chapter as IChapter).lastPageRead > -1) {
setInitialScroll((chapter as IChapter).lastPageRead);
}
}, []);
useEffect(() => {
if (initialScroll > -1) {
initialPageRef.current?.scrollIntoView();
}
}, [initialScroll, initialPageRef.current]);
return ( return (
<div className={classes.reader}> <div className={classes.reader}>
{ {
@@ -53,6 +67,7 @@ export default function VerticalReader(props: IReaderProps) {
src={page.src} src={page.src}
setCurPage={setCurPage} setCurPage={setCurPage}
settings={settings} settings={settings}
ref={page.index === initialScroll ? initialPageRef : null}
/> />
)) ))
} }
+29 -2
View File
@@ -9,7 +9,7 @@
import CircularProgress from '@material-ui/core/CircularProgress'; import CircularProgress from '@material-ui/core/CircularProgress';
import { makeStyles } from '@material-ui/core/styles'; import { makeStyles } from '@material-ui/core/styles';
import React, { useContext, useEffect, useState } from 'react'; import React, { useContext, useEffect, useState } from 'react';
import { useParams } from 'react-router-dom'; import { useHistory, useParams } from 'react-router-dom';
import HorizontalPager from '../components/reader/pager/HorizontalPager'; import HorizontalPager from '../components/reader/pager/HorizontalPager';
import Page from '../components/reader/Page'; import Page from '../components/reader/Page';
import PageNumber from '../components/reader/PageNumber'; import PageNumber from '../components/reader/PageNumber';
@@ -63,6 +63,7 @@ export default function Reader() {
const [settings, setSettings] = useLocalStorage<IReaderSettings>('readerSettings', defaultReaderSettings); const [settings, setSettings] = useLocalStorage<IReaderSettings>('readerSettings', defaultReaderSettings);
const classes = useStyles(settings)(); const classes = useStyles(settings)();
const history = useHistory();
const [serverAddress] = useLocalStorage<String>('serverBaseURL', ''); const [serverAddress] = useLocalStorage<String>('serverBaseURL', '');
@@ -117,14 +118,28 @@ export default function Reader() {
useEffect(() => { useEffect(() => {
setChapter(initialChapter); setChapter(initialChapter);
setCurPage(0);
client.get(`/api/v1/manga/${mangaId}/chapter/${chapterIndex}`) client.get(`/api/v1/manga/${mangaId}/chapter/${chapterIndex}`)
.then((response) => response.data) .then((response) => response.data)
.then((data:IChapter) => { .then((data:IChapter) => {
setChapter(data); setChapter(data);
setCurPage(data.lastPageRead);
}); });
}, [chapterIndex]); }, [chapterIndex]);
useEffect(() => {
if (curPage !== -1) {
const formData = new FormData();
formData.append('lastPageRead', curPage.toString());
client.patch(`/api/v1/manga/${manga.id}/chapter/${chapter.index}`, formData);
}
if (curPage === chapter.pageCount - 1) {
const formDataRead = new FormData();
formDataRead.append('read', 'true');
client.patch(`/api/v1/manga/${manga.id}/chapter/${chapter.index}`, formDataRead);
}
}, [curPage]);
if (chapter.pageCount === -1) { if (chapter.pageCount === -1) {
return ( return (
<div className={classes.loading}> <div className={classes.loading}>
@@ -133,6 +148,17 @@ export default function Reader() {
); );
} }
const nextChapter = () => {
if (chapter.index < chapter.chapterCount) {
const formData = new FormData();
formData.append('lastPageRead', `${chapter.pageCount - 1}`);
formData.append('read', 'true');
client.patch(`/api/v1/manga/${manga.id}/chapter/${chapter.index}`, formData);
history.push(`/manga/${manga.id}/chapter/${chapter.index + 1}`);
}
};
const pages = range(chapter.pageCount).map((index) => ({ const pages = range(chapter.pageCount).map((index) => ({
index, index,
src: `${serverAddress}/api/v1/manga/${mangaId}/chapter/${chapterIndex}/page/${index}`, src: `${serverAddress}/api/v1/manga/${mangaId}/chapter/${chapterIndex}/page/${index}`,
@@ -155,6 +181,7 @@ export default function Reader() {
settings={settings} settings={settings}
manga={manga} manga={manga}
chapter={chapter} chapter={chapter}
nextChapter={nextChapter}
/> />
</div> </div>
); );
+1
View File
@@ -116,4 +116,5 @@ interface IReaderProps {
settings: IReaderSettings settings: IReaderSettings
manga: IMangaCard | IManga manga: IMangaCard | IManga
chapter: IChapter | IPartialChpter chapter: IChapter | IPartialChpter
nextChapter: () => void
} }