Compare commits

...

23 Commits

Author SHA1 Message Date
Aria Moradi
84206a7074 bump to v0.3.7 2021-05-19 03:52:55 +04:30
Aria Moradi
d1500baae1 try with access token 2021-05-19 03:21:47 +04:30
Aria Moradi
045801dd1a push to Suwayomi/Tachidesk-preview 2021-05-19 02:56:46 +04:30
Aria Moradi
14a2cbc793 [SKIP CI] fix typo 2021-05-19 02:52:28 +04:30
Aria Moradi
fd385017df [SKIP CI] fix typo 2021-05-19 02:50:22 +04:30
Aria Moradi
9b05954cf2 [SKIP CI] fix typo 2021-05-19 02:49:10 +04:30
Aria Moradi
6aaf636069 [SKIP CI] update for new scripts 2021-05-19 02:47:48 +04:30
Aria Moradi
d30e89e5ec update workflows to include both 32-bit and 64-bit windows bundles 2021-05-19 02:42:14 +04:30
Aria Moradi
7acc745478 Merge the two windows bundlers 2021-05-19 02:31:56 +04:30
Aria Moradi
5a9a2d816e 32-bit variant of bundler 2021-05-19 02:26:29 +04:30
Aria Moradi
105f11ed02 Merge branch 'master' of github.com:Suwayomi/Tachidesk 2021-05-19 00:28:56 +04:30
Aria Moradi
3021437a05 new preview system! 2021-05-19 00:28:14 +04:30
Aria Moradi
439602fc03 [SKIP CI] no more preview 2021-05-18 23:42:43 +04:30
Aria Moradi
34e13b9589 [SKIP CI] improve wording... 2021-05-18 23:28:59 +04:30
Aria Moradi
2aab4ae918 [SKIP CI] asking for help! 2021-05-18 23:27:14 +04:30
Aria Moradi
7ef67671a4 print tachidesk info on startup 2021-05-18 22:36:41 +04:30
Syer10
e8df84416c Smarter Chapters and cleanup (#87)
* Smarter Chapters and cleanup

* Fix check
2021-05-18 22:22:15 +04:30
Aria Moradi
be930bb68b update to the new scheme 2021-05-18 22:03:18 +04:30
Aria Moradi
db52948865 update windows instructions 2021-05-18 21:42:30 +04:30
Aria Moradi
d2a72526f6 bump to v0.3.6 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
35 changed files with 311 additions and 178 deletions

3
.gitattributes vendored
View File

@@ -24,4 +24,5 @@
*.woff binary *.woff binary
*.pyc binary *.pyc binary
*.swp binary *.swp binary
*.pdf binary *.pdf binary
*.exe binary

View File

@@ -1,18 +1,16 @@
#!/bin/bash #!/bin/bash
rm -rf preview/*.jar preview/*.zip
cp master/server/build/Tachidesk-*.jar preview cp master/server/build/Tachidesk-*.jar preview
cp master/server/build/Tachidesk-*.zip preview
cd preview cd preview
new_jar_build=$(ls *.jar| tail -1) new_jar_build=$(ls Tachidesk-*.jar)
echo "last jar build file name: $new_jar_build" echo "last jar build file name: $new_jar_build"
cp -f $new_jar_build Tachidesk-latest.jar latest=$(echo $new_jar_build | sed -e's/Tachidesk-\|.jar//g')
rm -rf latest_pointer/*
cp $new_jar_build latest_pointer
cp ../master/server/build/Tachidesk-*.zip latest_pointer
latest=$(ls *.jar | tail -n1 | sed -e's/Tachidesk-\|.jar//g')
echo "{ \"latest\": \"$latest\" }" > index.json echo "{ \"latest\": \"$latest\" }" > index.json
git config --global user.email "github-actions[bot]@users.noreply.github.com" git config --global user.email "github-actions[bot]@users.noreply.github.com"

View File

@@ -57,12 +57,12 @@ jobs:
**/react/node_modules **/react/node_modules
key: ${{ runner.os }}-${{ hashFiles('**/react/yarn.lock') }} key: ${{ runner.os }}-${{ hashFiles('**/react/yarn.lock') }}
- name: Build and copy webUI, Build Jar and launch4j - name: Build and copy webUI, Build Jar
uses: eskatos/gradle-command-action@v1 uses: eskatos/gradle-command-action@v1
with: with:
build-root-directory: master build-root-directory: master
wrapper-directory: master wrapper-directory: master
arguments: :webUI:copyBuild :server:windowsPackage --stacktrace arguments: :webUI:copyBuild :server:shadowJar --stacktrace
wrapper-cache-enabled: true wrapper-cache-enabled: true
dependencies-cache-enabled: true dependencies-cache-enabled: true
configuration-cache-enabled: true configuration-cache-enabled: true

View File

@@ -69,16 +69,19 @@ jobs:
dependencies-cache-enabled: true dependencies-cache-enabled: true
configuration-cache-enabled: true configuration-cache-enabled: true
- name: make windows package - name: make windows packages
run: | run: |
cd master/scripts cd master/scripts
./windows-bundler.sh ./windows32-bundler.sh
./windows64-bundler.sh
- name: Checkout preview branch - name: Checkout preview branch
uses: actions/checkout@v2 uses: actions/checkout@v2
with: with:
ref: preview repository: 'Suwayomi/Tachidesk-preview'
ref: main
path: preview path: preview
token: ${{ secrets.DEPLOY_PREVIEW_TOKEN }}
- name: Deploy preview - name: Deploy preview
run: | run: |

View File

@@ -68,10 +68,11 @@ jobs:
dependencies-cache-enabled: true dependencies-cache-enabled: true
configuration-cache-enabled: true configuration-cache-enabled: true
- name: make windows package - name: make windows packages
run: | run: |
cd master/scripts cd master/scripts
./windows-bundler.sh ./windows32-bundler.sh
./windows64-bundler.sh
- name: Upload Release - name: Upload Release
uses: xresloader/upload-to-github-release@master uses: xresloader/upload-to-github-release@master

5
.gitignore vendored
View File

@@ -8,4 +8,7 @@ build
server/src/main/resources/react server/src/main/resources/react
server/tmp/ server/tmp/
server/tachiserver-data/ server/tachiserver-data/
# OpenJDK downlaods
OpenJDK*

View File

@@ -87,7 +87,6 @@ function Dedupe($path)
} }
Dedupe "AndroidCompat/src/main/java" Dedupe "AndroidCompat/src/main/java"
Dedupe "server/src/main/java"
Dedupe "server/src/main/kotlin" Dedupe "server/src/main/kotlin"
Write-Output "Copying Android.jar to library folder..." Write-Output "Copying Android.jar to library folder..."

View File

@@ -20,7 +20,7 @@ fi
# foolproof against running from AndroidCompat dir instead of running from project root # foolproof against running from AndroidCompat dir instead of running from project root
if [ "$(basename $(pwd))" = "AndroidCompat" ]; then if [ "$(basename "$(pwd)")" = "AndroidCompat" ]; then
cd .. cd ..
fi fi
@@ -59,7 +59,7 @@ zip --delete android.jar javax/*
echo "Removing java..." echo "Removing java..."
zip --delete android.jar java/* zip --delete android.jar java/*
echo "Removing overriden classes..." echo "Removing overridden classes..."
zip --delete android.jar android/app/Application.class zip --delete android.jar android/app/Application.class
zip --delete android.jar android/app/Service.class zip --delete android.jar android/app/Service.class
zip --delete android.jar android/net/Uri.class zip --delete android.jar android/net/Uri.class
@@ -68,12 +68,12 @@ zip --delete android.jar android/os/Environment.class
zip --delete android.jar android/text/format/Formatter.class zip --delete android.jar android/text/format/Formatter.class
zip --delete android.jar android/text/Html.class zip --delete android.jar android/text/Html.class
# Dedup overriden Android classes # Dedup overridden Android classes
ABS_JAR="$(realpath android.jar)" ABS_JAR="$(realpath android.jar)"
function dedup() { function dedup() {
pushd "$1" pushd "$1"
CLASSES="$(find * -type f)" CLASSES="$(find ./* -type f)"
echo "$CLASSES" | while read class echo "$CLASSES" | while read -r class
do do
NAME="${class%.*}" NAME="${class%.*}"
echo "Processing class: $NAME" echo "Processing class: $NAME"
@@ -82,13 +82,10 @@ function dedup() {
popd popd
} }
pushd .. popd
dedup AndroidCompat/src/main/java dedup AndroidCompat/src/main/java
dedup server/src/main/java
dedup server/src/main/kotlin dedup server/src/main/kotlin
popd
popd
echo "Copying Android.jar to library folder..." echo "Copying Android.jar to library folder..."
mv tmp/android.jar AndroidCompat/lib mv tmp/android.jar AndroidCompat/lib

View File

@@ -16,7 +16,7 @@ This structure is chosen to
- Eaise development of alternative user intefaces for Tachidesk - Eaise development of alternative user intefaces for Tachidesk
## User Interfaces for Tachidesk server ## User Interfaces for Tachidesk server
Currently there are three known interfaces for Tachidesk: Currently, there are three known interfaces for Tachidesk:
1. [webUI](https://github.com/Suwayomi/Tachidesk/tree/master/webUI/react): The react SPA that Tachidesk is traditionally shipped with. 1. [webUI](https://github.com/Suwayomi/Tachidesk/tree/master/webUI/react): The react SPA that Tachidesk is traditionally shipped with.
2. [TachideskJUI](https://github.com/Suwayomi/TachideskJUI): A Jetbrains Compose Native app, re-uses components made for the upcoming Tachiyomi 1.x 2. [TachideskJUI](https://github.com/Suwayomi/TachideskJUI): A Jetbrains Compose Native app, re-uses components made for the upcoming Tachiyomi 1.x
3. [Equinox](https://github.com/Suwayomi/Equinox): A web user interface made with Vue.js, in super early stages of development. 3. [Equinox](https://github.com/Suwayomi/Equinox): A web user interface made with Vue.js, in super early stages of development.
@@ -28,7 +28,7 @@ You need these software packages installed in order to build the project
- Java Development Kit and Java Runtime Environment version 8 or newer(both Oracle JDK and OpenJDK works) - Java Development Kit and Java Runtime Environment version 8 or newer(both Oracle JDK and OpenJDK works)
- Android stubs jar - Android stubs jar
- Manual download: Download [android.jar](https://raw.githubusercontent.com/Suwayomi/Tachidesk/android-jar/android.jar) and put it under `AndroidCompat/lib`. - Manual download: Download [android.jar](https://raw.githubusercontent.com/Suwayomi/Tachidesk/android-jar/android.jar) and put it under `AndroidCompat/lib`.
- Automated download: Run `AndroidCompat/getAndroid.sh`(MacOS/Linux) or `AndroidCompat/getAndroid.ps1`(Windows) from project's root directory to download and rebuild the jar file from Google's repository. - Automated download: Run `AndroidCompat/getAndroid.sh`(MacOS/Linux) or `AndroidCompat/getAndroid.ps1`(Windows) from project's root directory to download and rebuild the jar file from Google's repository.
### webUI ### webUI
- Nodejs LTS or latest - Nodejs LTS or latest
- Yarn - Yarn
@@ -38,15 +38,15 @@ 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<bits>-bundler.sh` (or `./windows<bits>-bundler.ps1` if you are on windows), 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 satisfy [the prerequisites](#prerequisites)
### server ### server
run `./gradlew :server:run --stacktrace` to run the server run `./gradlew :server:run --stacktrace` to run the server
### webUI ### webUI
How to do it is described in `webUI/react/README.md` but for short, How to do it is described in `webUI/react/README.md` but for short,
first cd into `webUI/react` then run `yarn` to install the node modules(do this only once) first cd into `webUI/react` then run `yarn` to install the node modules(do this only once)
then `yarn start` to start the development server, if a new browser window doesn't get opned automatically, then `yarn start` to start the development server, if a new browser window doesn't get opened automatically,
then open `http://127.0.0.1:3000` in a modern browser. This is a `create-react-app` project then open `http://127.0.0.1:3000` in a modern browser. This is a `create-react-app` project
and supports HMR and all the other goodies you'll need. and supports HMR and all the other goodies you'll need.

View File

@@ -1,7 +1,7 @@
| Build | Stable | Preview | Support Server | | Build | Stable | Preview | Support Server |
|-------|----------|---------|---------| |-------|----------|---------|---------|
| ![CI](https://github.com/Suwayomi/Tachidesk/actions/workflows/build_push.yml/badge.svg) | [![stable release](https://img.shields.io/github/release/Suwayomi/Tachidesk.svg?maxAge=3600&label=download)](https://github.com/Suwayomi/Tachidesk/releases) | [![preview](https://img.shields.io/badge/dynamic/json?url=https://github.com/Suwayomi/Tachidesk/raw/preview/index.json&label=download&query=$.latest&color=blue)](https://github.com/Suwayomi/Tachidesk/tree/preview/latest_pointer) | [![Discord](https://img.shields.io/discord/801021177333940224.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/DDZdqZWaHA) | | ![CI](https://github.com/Suwayomi/Tachidesk/actions/workflows/build_push.yml/badge.svg) | [![stable release](https://img.shields.io/github/release/Suwayomi/Tachidesk.svg?maxAge=3600&label=download)](https://github.com/Suwayomi/Tachidesk/releases) | [![preview](https://img.shields.io/badge/dynamic/json?url=https://github.com/Suwayomi/Tachidesk/raw/preview/index.json&label=download&query=$.latest&color=blue)](https://github.com/Suwayomi/Tachidesk/tree/preview/) | [![Discord](https://img.shields.io/discord/801021177333940224.svg?label=discord&labelColor=7289da&color=2c2f33&style=flat)](https://discord.gg/DDZdqZWaHA) |
# Tachidesk # Tachidesk
<img src="https://github.com/Suwayomi/Tachidesk/raw/master/server/src/main/resources/icon/faviconlogo.png" alt="drawing" width="200"/> <img src="https://github.com/Suwayomi/Tachidesk/raw/master/server/src/main/resources/icon/faviconlogo.png" alt="drawing" width="200"/>
@@ -14,6 +14,8 @@ Tachidesk is as multi-platform as you can get. Any platform that runs java and/o
Ability to read and write Tachiyomi compatible backups and syncing is a planned feature. Ability to read and write Tachiyomi compatible backups and syncing is a planned feature.
**Tachidesk needs serious front-end dev help for it's reader and other parts, if you like the app and want to see it become better please don't hesitate to contribute some code!**
## Is this application usable? Should I test it? ## Is this application usable? Should I test it?
Here is a list of current features: Here is a list of current features:
@@ -35,19 +37,15 @@ Download the latest "Stable" jar release from [the releases section](https://git
Double click on the jar file or run `java -jar Tachidesk-vX.Y.Z-rxxx.jar` (or `java -jar Tachidesk-latest.jar` if you have the latest preview) from a Terminal/Command Prompt window to run the app which will open a new browser window automatically. Also the System Tray Icon is your friend if you need to open the browser window again or close Tachidesk. Double click on the jar file or run `java -jar Tachidesk-vX.Y.Z-rxxx.jar` (or `java -jar Tachidesk-latest.jar` if you have the latest preview) from a Terminal/Command Prompt window to run the app which will open a new browser window automatically. Also the System Tray Icon is your friend if you need to open the browser window again or close Tachidesk.
### Windows ### Windows
Download the latest win32 release from [the releases section](https://github.com/Suwayomi/Tachidesk/releases). Download the latest win32 or win64 (depending on your system, usually you want win64) 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-win64.zip` and run `Tachidesk.bat`. 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 Launcher.exe` or `Tachidesk Launcher.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
``` ```
yay -S tachidesk yay -S tachidesk
``` ```
Or the latest preview version
```
yay -S tachidesk-preview
```
### Docker ### Docker
Check [arbuilder's repo](https://github.com/arbuilder/Tachidesk-docker) out for more details and the dockerfile. Check [arbuilder's repo](https://github.com/arbuilder/Tachidesk-docker) out for more details and the dockerfile.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1 @@
start "" jre/bin/javaw -jar Tachidesk.jar

View File

@@ -0,0 +1,5 @@
#include <stdlib.h>
int main() {
system("start jre\\bin\\javaw -jar Tachidesk.jar");
}

View File

@@ -1 +0,0 @@
start "" "jre/bin/javaw -jar Tachidesk.jar"

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`

View File

@@ -0,0 +1,38 @@
# Copyright (C) Contributors to the Suwayomi project
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
Write-Output "Downloading jre..."
$jre="OpenJDK8U-jre_x86-32_windows_hotspot_8u292b10.zip"
if (!(Test-Path $jre)) {
Invoke-WebRequest -Uri "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x86-32_windows_hotspot_8u292b10.zip" -OutFile $jre -UseBasicParsing
}
Write-Output "creating windows bundle"
$jar=$(Get-ChildItem ../server/build/Tachidesk-*.jar)
$release_name=$jar.BaseName + "-win32"
# make release dir
New-Item -ItemType Directory $release_name
Expand-Archive $jre -DestinationPath "./" -ErrorAction SilentlyContinue
# move jre
Move-Item "jdk8u292-b10-jre" "$release_name/jre"
Copy-Item $jar.FullName "$release_name/Tachidesk.jar"
Copy-Item "resources/Tachidesk Launcher-win32.exe" $release_name
Copy-Item "resources/Tachidesk Launcher.bat" $release_name
Copy-Item "resources/Tachidesk Debug Launcher.bat" $release_name
$zip_name="$release_name.zip"
Compress-Archive -CompressionLevel Optimal -DestinationPath $zip_name -Path $release_name -Force -ErrorAction SilentlyContinue
Remove-Item -Force -Recurse $release_name
Move-Item $zip_name "../server/build/" -ErrorAction SilentlyContinue

41
scripts/windows32-bundler.sh Executable file
View File

@@ -0,0 +1,41 @@
#!/bin/bash
# Copyright (C) Contributors to the Suwayomi project
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
echo "Downloading jre..."
jre="OpenJDK8U-jre_x86-32_windows_hotspot_8u292b10.zip"
if [ ! -f $jre ]; then
curl -L "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x86-32_windows_hotspot_8u292b10.zip" -o $jre
fi
echo "creating windows bundle"
jar=$(ls ../server/build/Tachidesk-*.jar)
jar_name=$(echo $jar | cut -d'/' -f4)
release_name=$(echo $jar_name | cut -d'.' -f4 --complement)-win32
# make release dir
mkdir $release_name
unzip $jre
# move jre
mv jdk8u292-b10-jre $release_name/jre
cp $jar $release_name/Tachidesk.jar
cp "resources/Tachidesk Launcher-win32.exe" "$release_name/Tachidesk Launcher.exe"
cp "resources/Tachidesk Launcher.bat" $release_name
cp "resources/Tachidesk Debug Launcher.bat" $release_name
zip_name=$release_name.zip
zip -9 -r $zip_name $release_name
rm -rf $release_name
mv $zip_name ../server/build/

View File

@@ -0,0 +1,38 @@
# Copyright (C) Contributors to the Suwayomi project
#
# This Source Code Form is subject to the terms of the Mozilla Public
# 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/.
Write-Output "Downloading jre..."
$jre="OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip"
if (!(Test-Path $jre)) {
Invoke-WebRequest -Uri "https://github.com/AdoptOpenJDK/openjdk8-binaries/releases/download/jdk8u292-b10/OpenJDK8U-jre_x64_windows_hotspot_8u292b10.zip" -OutFile $jre -UseBasicParsing
}
Write-Output "creating windows bundle"
$jar=$(Get-ChildItem ../server/build/Tachidesk-*.jar)
$release_name=$jar.BaseName + "-win64"
# make release dir
New-Item -ItemType Directory $release_name
Expand-Archive $jre -DestinationPath "./" -ErrorAction SilentlyContinue
# move jre
Move-Item "jdk8u292-b10-jre" "$release_name/jre"
Copy-Item $jar.FullName "$release_name/Tachidesk.jar"
Copy-Item "resources/Tachidesk Launcher-win64.exe" $release_name
Copy-Item "resources/Tachidesk Launcher.bat" $release_name
Copy-Item "resources/Tachidesk Debug Launcher.bat" $release_name
$zip_name="$release_name.zip"
Compress-Archive -CompressionLevel Optimal -DestinationPath $zip_name -Path $release_name -Force -ErrorAction SilentlyContinue
Remove-Item -Force -Recurse $release_name
Move-Item $zip_name "../server/build/" -ErrorAction SilentlyContinue

View File

@@ -9,7 +9,9 @@
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"
@@ -27,10 +29,13 @@ mv jdk8u292-b10-jre $release_name/jre
cp $jar $release_name/Tachidesk.jar cp $jar $release_name/Tachidesk.jar
cp resources/Tachidesk.bat $release_name cp "resources/Tachidesk Launcher-win64.exe" "$release_name/Tachidesk Launcher.exe"
cp resources/Tachidesk-debug.bat $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/

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.5" val tachideskVersion = "v0.3.7"
// 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"))
} }
} }

View File

@@ -27,96 +27,105 @@ import org.jetbrains.exposed.sql.update
object Chapter { object Chapter {
/** get chapter list when showing a manga */ /** get chapter list when showing a manga */
suspend fun getChapterList(mangaId: Int, onlineFetch: Boolean): List<ChapterDataClass> { suspend fun getChapterList(mangaId: Int, onlineFetch: Boolean?): List<ChapterDataClass> {
return if (!onlineFetch) { return if (onlineFetch == true) {
getSourceChapters(mangaId)
} else {
transaction { transaction {
ChapterTable.select { ChapterTable.manga eq mangaId }.orderBy(ChapterTable.chapterIndex to DESC) ChapterTable.select { ChapterTable.manga eq mangaId }.orderBy(ChapterTable.chapterIndex to DESC)
.map { .map {
ChapterTable.toDataClass(it) ChapterTable.toDataClass(it)
} }
}.ifEmpty {
// If it was explicitly set to offline dont grab chapters
if (onlineFetch == null) {
getSourceChapters(mangaId)
} else emptyList()
} }
} else { }
}
val mangaDetails = getManga(mangaId) private suspend fun getSourceChapters(mangaId: Int): List<ChapterDataClass> {
val source = getHttpSource(mangaDetails.sourceId.toLong()) val mangaDetails = getManga(mangaId)
val chapterList = source.fetchChapterList( val source = getHttpSource(mangaDetails.sourceId.toLong())
SManga.create().apply { val chapterList = source.fetchChapterList(
title = mangaDetails.title SManga.create().apply {
url = mangaDetails.url title = mangaDetails.title
} url = mangaDetails.url
).awaitSingle() }
).awaitSingle()
val chapterCount = chapterList.count() val chapterCount = chapterList.count()
transaction { transaction {
chapterList.reversed().forEachIndexed { index, fetchedChapter -> chapterList.reversed().forEachIndexed { index, fetchedChapter ->
val chapterEntry = ChapterTable.select { ChapterTable.url eq fetchedChapter.url }.firstOrNull() val chapterEntry = ChapterTable.select { ChapterTable.url eq fetchedChapter.url }.firstOrNull()
if (chapterEntry == null) { if (chapterEntry == null) {
ChapterTable.insert { ChapterTable.insert {
it[url] = fetchedChapter.url it[url] = fetchedChapter.url
it[name] = fetchedChapter.name it[name] = fetchedChapter.name
it[date_upload] = fetchedChapter.date_upload it[date_upload] = fetchedChapter.date_upload
it[chapter_number] = fetchedChapter.chapter_number it[chapter_number] = fetchedChapter.chapter_number
it[scanlator] = fetchedChapter.scanlator it[scanlator] = fetchedChapter.scanlator
it[chapterIndex] = index + 1 it[chapterIndex] = index + 1
it[manga] = mangaId it[manga] = mangaId
} }
} else { } else {
ChapterTable.update({ ChapterTable.url eq fetchedChapter.url }) { ChapterTable.update({ ChapterTable.url eq fetchedChapter.url }) {
it[name] = fetchedChapter.name it[name] = fetchedChapter.name
it[date_upload] = fetchedChapter.date_upload it[date_upload] = fetchedChapter.date_upload
it[chapter_number] = fetchedChapter.chapter_number it[chapter_number] = fetchedChapter.chapter_number
it[scanlator] = fetchedChapter.scanlator it[scanlator] = fetchedChapter.scanlator
it[chapterIndex] = index + 1 it[chapterIndex] = index + 1
it[manga] = mangaId it[manga] = mangaId
}
} }
} }
} }
}
// clear any orphaned chapters that are in the db but not in `chapterList` // clear any orphaned chapters that are in the db but not in `chapterList`
val dbChapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() } val dbChapterCount = transaction { ChapterTable.select { ChapterTable.manga eq mangaId }.count() }
if (dbChapterCount > chapterCount) { // we got some clean up due if (dbChapterCount > chapterCount) { // we got some clean up due
val dbChapterList = transaction { ChapterTable.select { ChapterTable.manga eq mangaId } } val dbChapterList = transaction { ChapterTable.select { ChapterTable.manga eq mangaId } }
dbChapterList.forEach { dbChapterList.forEach {
if (it[ChapterTable.chapterIndex] >= chapterList.size || if (it[ChapterTable.chapterIndex] >= chapterList.size ||
chapterList[it[ChapterTable.chapterIndex] - 1].url != it[ChapterTable.url] chapterList[it[ChapterTable.chapterIndex] - 1].url != it[ChapterTable.url]
) { ) {
transaction { transaction {
PageTable.deleteWhere { PageTable.chapter eq it[ChapterTable.id] } PageTable.deleteWhere { PageTable.chapter eq it[ChapterTable.id] }
ChapterTable.deleteWhere { ChapterTable.id eq it[ChapterTable.id] } ChapterTable.deleteWhere { ChapterTable.id eq it[ChapterTable.id] }
}
} }
} }
} }
}
val dbChapterMap = transaction { val dbChapterMap = transaction {
ChapterTable.select { ChapterTable.manga eq mangaId } ChapterTable.select { ChapterTable.manga eq mangaId }
.associateBy({ it[ChapterTable.url] }, { it }) .associateBy({ it[ChapterTable.url] }, { it })
} }
return chapterList.mapIndexed { index, it -> return chapterList.mapIndexed { index, it ->
val dbChapter = dbChapterMap.getValue(it.url) val dbChapter = dbChapterMap.getValue(it.url)
ChapterDataClass( ChapterDataClass(
it.url, it.url,
it.name, it.name,
it.date_upload, it.date_upload,
it.chapter_number, it.chapter_number,
it.scanlator, it.scanlator,
mangaId, mangaId,
dbChapter[ChapterTable.isRead], dbChapter[ChapterTable.isRead],
dbChapter[ChapterTable.isBookmarked], dbChapter[ChapterTable.isBookmarked],
dbChapter[ChapterTable.lastPageRead], dbChapter[ChapterTable.lastPageRead],
chapterCount - index, chapterCount - index,
) chapterList.size
} )
} }
} }
@@ -125,9 +134,9 @@ object Chapter {
val chapterEntry = transaction { val chapterEntry = transaction {
ChapterTable.select { ChapterTable.select {
(ChapterTable.chapterIndex eq chapterIndex) and (ChapterTable.manga eq mangaId) (ChapterTable.chapterIndex eq chapterIndex) and (ChapterTable.manga eq mangaId)
}.firstOrNull()!! }.first()
} }
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
val source = getHttpSource(mangaEntry[MangaTable.sourceReference]) val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
val pageList = source.fetchPageList( val pageList = source.fetchPageList(

View File

@@ -159,7 +159,7 @@ object Extension {
it[this.classFQName] = className it[this.classFQName] = className
} }
val extensionId = ExtensionTable.select { ExtensionTable.pkgName eq pkgName }.firstOrNull()!![ExtensionTable.id].value val extensionId = ExtensionTable.select { ExtensionTable.pkgName eq pkgName }.first()[ExtensionTable.id].value
sources.forEach { httpSource -> sources.forEach { httpSource ->
SourceTable.insert { SourceTable.insert {
@@ -195,7 +195,7 @@ object Extension {
fun uninstallExtension(pkgName: String) { fun uninstallExtension(pkgName: String) {
logger.debug("Uninstalling $pkgName") logger.debug("Uninstalling $pkgName")
val extensionRecord = transaction { ExtensionTable.select { ExtensionTable.pkgName eq pkgName }.firstOrNull()!! } val extensionRecord = transaction { ExtensionTable.select { ExtensionTable.pkgName eq pkgName }.first() }
val fileNameWithoutType = extensionRecord[ExtensionTable.apkName].substringBefore(".apk") val fileNameWithoutType = extensionRecord[ExtensionTable.apkName].substringBefore(".apk")
val jarPath = "${applicationDirs.extensionsRoot}/$fileNameWithoutType.jar" val jarPath = "${applicationDirs.extensionsRoot}/$fileNameWithoutType.jar"
transaction { transaction {
@@ -234,7 +234,7 @@ object Extension {
} }
suspend fun getExtensionIcon(apkName: String): Pair<InputStream, String> { suspend fun getExtensionIcon(apkName: String): Pair<InputStream, String> {
val iconUrl = transaction { ExtensionTable.select { ExtensionTable.apkName eq apkName }.firstOrNull()!! }[ExtensionTable.iconUrl] val iconUrl = transaction { ExtensionTable.select { ExtensionTable.apkName eq apkName }.first() }[ExtensionTable.iconUrl]
val saveDir = "${applicationDirs.extensionsRoot}/icon" val saveDir = "${applicationDirs.extensionsRoot}/icon"

View File

@@ -37,7 +37,7 @@ object Manga {
} }
suspend fun getManga(mangaId: Int, onlineFetch: Boolean = false): MangaDataClass { suspend fun getManga(mangaId: Int, onlineFetch: Boolean = false): MangaDataClass {
var mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } var mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
return if (mangaEntry[MangaTable.initialized] && !onlineFetch) { return if (mangaEntry[MangaTable.initialized] && !onlineFetch) {
MangaDataClass( MangaDataClass(
@@ -78,14 +78,14 @@ object Manga {
it[MangaTable.description] = truncate(fetchedManga.description, 4096) it[MangaTable.description] = truncate(fetchedManga.description, 4096)
it[MangaTable.genre] = fetchedManga.genre it[MangaTable.genre] = fetchedManga.genre
it[MangaTable.status] = fetchedManga.status it[MangaTable.status] = fetchedManga.status
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty()) if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url.orEmpty().isNotEmpty())
it[MangaTable.thumbnail_url] = fetchedManga.thumbnail_url it[MangaTable.thumbnail_url] = fetchedManga.thumbnail_url
} }
} }
clearMangaThumbnail(mangaId) clearMangaThumbnail(mangaId)
mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
MangaDataClass( MangaDataClass(
mangaId, mangaId,
@@ -117,7 +117,7 @@ object Manga {
return getCachedImageResponse(saveDir, fileName) { return getCachedImageResponse(saveDir, fileName) {
getManga(mangaId) // make sure is initialized getManga(mangaId) // make sure is initialized
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
val sourceId = mangaEntry[MangaTable.sourceReference] val sourceId = mangaEntry[MangaTable.sourceReference]
val source = getHttpSource(sourceId) val source = getHttpSource(sourceId)
@@ -130,7 +130,7 @@ object Manga {
} }
} }
suspend fun clearMangaThumbnail(mangaId: Int) { private fun clearMangaThumbnail(mangaId: Int) {
val saveDir = applicationDirs.thumbnailsRoot val saveDir = applicationDirs.thumbnailsRoot
val fileName = mangaId.toString() val fileName = mangaId.toString()

View File

@@ -40,7 +40,7 @@ object MangaList {
val mangasPage = this val mangasPage = this
val mangaList = transaction { val mangaList = transaction {
return@transaction mangasPage.mangas.map { manga -> return@transaction mangasPage.mangas.map { manga ->
var mangaEntry = MangaTable.select { MangaTable.url eq manga.url }.firstOrNull() val mangaEntry = MangaTable.select { MangaTable.url eq manga.url }.firstOrNull()
if (mangaEntry == null) { // create manga entry if (mangaEntry == null) { // create manga entry
val mangaId = MangaTable.insertAndGetId { val mangaId = MangaTable.insertAndGetId {
it[url] = manga.url it[url] = manga.url

View File

@@ -40,16 +40,16 @@ object Page {
} }
suspend fun getPageImage(mangaId: Int, chapterIndex: Int, index: Int): Pair<InputStream, String> { suspend fun getPageImage(mangaId: Int, chapterIndex: Int, index: Int): Pair<InputStream, String> {
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
val source = getHttpSource(mangaEntry[MangaTable.sourceReference]) val source = getHttpSource(mangaEntry[MangaTable.sourceReference])
val chapterEntry = transaction { val chapterEntry = transaction {
ChapterTable.select { ChapterTable.select {
(ChapterTable.chapterIndex eq chapterIndex) and (ChapterTable.manga eq mangaId) (ChapterTable.chapterIndex eq chapterIndex) and (ChapterTable.manga eq mangaId)
}.firstOrNull()!! }.first()
} }
val chapterId = chapterEntry[ChapterTable.id].value val chapterId = chapterEntry[ChapterTable.id].value
val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq index) }.firstOrNull()!! } val pageEntry = transaction { PageTable.select { (PageTable.chapter eq chapterId) and (PageTable.index eq index) }.first() }
val tachiPage = Page( val tachiPage = Page(
pageEntry[PageTable.index], pageEntry[PageTable.index],
@@ -78,11 +78,11 @@ object Page {
// TODO: rewrite this to match tachiyomi // TODO: rewrite this to match tachiyomi
private val applicationDirs by DI.global.instance<ApplicationDirs>() private val applicationDirs by DI.global.instance<ApplicationDirs>()
fun getChapterDir(mangaId: Int, chapterId: Int): String { fun getChapterDir(mangaId: Int, chapterId: Int): String {
val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.firstOrNull()!! } val mangaEntry = transaction { MangaTable.select { MangaTable.id eq mangaId }.first() }
val sourceId = mangaEntry[MangaTable.sourceReference] val sourceId = mangaEntry[MangaTable.sourceReference]
val source = getHttpSource(sourceId) val source = getHttpSource(sourceId)
val sourceEntry = transaction { SourceTable.select { SourceTable.id eq sourceId }.firstOrNull()!! } val sourceEntry = transaction { SourceTable.select { SourceTable.id eq sourceId }.first() }
val chapterEntry = transaction { ChapterTable.select { ChapterTable.id eq chapterId }.firstOrNull()!! } val chapterEntry = transaction { ChapterTable.select { ChapterTable.id eq chapterId }.first() }
val chapterDir = when { val chapterDir = when {
chapterEntry[ChapterTable.scanlator] != null -> "${chapterEntry[ChapterTable.scanlator]}_${chapterEntry[ChapterTable.name]}" chapterEntry[ChapterTable.scanlator] != null -> "${chapterEntry[ChapterTable.scanlator]}_${chapterEntry[ChapterTable.name]}"

View File

@@ -198,7 +198,7 @@ object LegacyBackupImport : LegacyBackupBase() {
it[description] = fetchedManga.description it[description] = fetchedManga.description
it[genre] = fetchedManga.genre it[genre] = fetchedManga.genre
it[status] = fetchedManga.status it[status] = fetchedManga.status
if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url!!.isNotEmpty()) if (fetchedManga.thumbnail_url != null && fetchedManga.thumbnail_url.orEmpty().isNotEmpty())
it[MangaTable.thumbnail_url] = fetchedManga.thumbnail_url it[MangaTable.thumbnail_url] = fetchedManga.thumbnail_url
} }
} }

View File

@@ -10,7 +10,6 @@ package ir.armor.tachidesk.impl.util
import okhttp3.Response import okhttp3.Response
import okio.buffer import okio.buffer
import okio.sink import okio.sink
import java.io.BufferedInputStream
import java.io.File import java.io.File
import java.io.FileInputStream import java.io.FileInputStream
import java.io.InputStream import java.io.InputStream
@@ -19,12 +18,12 @@ import java.nio.file.Paths
object CachedImageResponse { object CachedImageResponse {
private fun pathToInputStream(path: String): InputStream { private fun pathToInputStream(path: String): InputStream {
return BufferedInputStream(FileInputStream(path)) return FileInputStream(path).buffered()
} }
private fun findFileNameStartingWith(directoryPath: String, fileName: String): String? { private fun findFileNameStartingWith(directoryPath: String, fileName: String): String? {
val target = "$fileName." val target = "$fileName."
File(directoryPath).listFiles().forEach { file -> File(directoryPath).listFiles().orEmpty().forEach { file ->
if (file.name.startsWith(target)) if (file.name.startsWith(target))
return "$directoryPath/${file.name}" return "$directoryPath/${file.name}"
} }
@@ -57,16 +56,13 @@ object CachedImageResponse {
} }
} }
} }
return Pair( return pathToInputStream(fullPath) to contentType
pathToInputStream(fullPath),
contentType
)
} else { } else {
throw Exception("request error! ${response.code}") throw Exception("request error! ${response.code}")
} }
} }
suspend fun clearCachedImage(saveDir: String, fileName: String) { fun clearCachedImage(saveDir: String, fileName: String) {
val cachedFile = findFileNameStartingWith(saveDir, fileName) val cachedFile = findFileNameStartingWith(saveDir, fileName)
cachedFile?.also { cachedFile?.also {
File(it).delete() File(it).delete()

View File

@@ -32,12 +32,12 @@ object GetHttpSource {
} }
val sourceRecord = transaction { val sourceRecord = transaction {
SourceTable.select { SourceTable.id eq sourceId }.firstOrNull()!! SourceTable.select { SourceTable.id eq sourceId }.first()
} }
val extensionId = sourceRecord[SourceTable.extension] val extensionId = sourceRecord[SourceTable.extension]
val extensionRecord = transaction { val extensionRecord = transaction {
ExtensionTable.select { ExtensionTable.id eq extensionId }.firstOrNull()!! ExtensionTable.select { ExtensionTable.id eq extensionId }.first()
} }
val apkName = extensionRecord[ExtensionTable.apkName] val apkName = extensionRecord[ExtensionTable.apkName]

View File

@@ -11,6 +11,7 @@ import kotlinx.coroutines.suspendCancellableCoroutine
import okhttp3.Call import okhttp3.Call
import okhttp3.Callback import okhttp3.Callback
import okhttp3.Response import okhttp3.Response
import okhttp3.internal.closeQuietly
import java.io.IOException import java.io.IOException
import kotlin.coroutines.resume import kotlin.coroutines.resume
import kotlin.coroutines.resumeWithException import kotlin.coroutines.resumeWithException
@@ -26,7 +27,9 @@ suspend fun Call.await(): Response {
return return
} }
continuation.resume(response) continuation.resume(response) {
response.body?.closeQuietly()
}
} }
override fun onFailure(call: Call, e: IOException) { override fun onFailure(call: Call, e: IOException) {

View File

@@ -71,12 +71,14 @@ object PackageTools {
if (handler.hasException()) { if (handler.hasException()) {
val errorFile: Path = File(applicationDirs.extensionsRoot).toPath().resolve("$fileNameWithoutType-error.txt") val errorFile: Path = File(applicationDirs.extensionsRoot).toPath().resolve("$fileNameWithoutType-error.txt")
logger.error( logger.error(
"Detail Error Information in File $errorFile\n" + """
"Please report this file to one of following link if possible (any one).\n" + Detail Error Information in File $errorFile
" https://sourceforge.net/p/dex2jar/tickets/\n" + Please report this file to one of following link if possible (any one).
" https://bitbucket.org/pxb1988/dex2jar/issues\n" + https://sourceforge.net/p/dex2jar/tickets/
" https://github.com/pxb1988/dex2jar/issues\n" + https://bitbucket.org/pxb1988/dex2jar/issues
" dex2jar@googlegroups.com" https://github.com/pxb1988/dex2jar/issues
dex2jar@googlegroups.com
""".trimIndent()
) )
handler.dump(errorFile, emptyArray<String>()) handler.dump(errorFile, emptyArray<String>())
} }
@@ -98,18 +100,21 @@ object PackageTools {
applicationInfo.metaData = Bundle().apply { applicationInfo.metaData = Bundle().apply {
val appTag = doc.getElementsByTagName("application").item(0) val appTag = doc.getElementsByTagName("application").item(0)
appTag?.childNodes?.toList()?.filter { appTag?.childNodes?.toList()
it.nodeType == Node.ELEMENT_NODE .orEmpty()
}?.map { .asSequence()
it as Element .filter {
}?.filter { it.nodeType == Node.ELEMENT_NODE
it.tagName == "meta-data" }.map {
}?.map { it as Element
putString( }.filter {
it.attributes.getNamedItem("android:name").nodeValue, it.tagName == "meta-data"
it.attributes.getNamedItem("android:value").nodeValue }.forEach {
) putString(
} it.attributes.getNamedItem("android:name").nodeValue,
it.attributes.getNamedItem("android:value").nodeValue
)
}
} }
signatures = ( signatures = (

View File

@@ -25,7 +25,7 @@ data class ChapterDataClass(
val lastPageRead: Int, val lastPageRead: Int,
/** this chapter's index, starts with 1 */ /** this chapter's index, starts with 1 */
val index: Int? = null, val index: Int,
/** total chapter count, used to calculate if there's a next and prev chapter */ /** total chapter count, used to calculate if there's a next and prev chapter */
val chapterCount: Int? = null, val chapterCount: Int? = null,

View File

@@ -96,7 +96,10 @@ object JavalinSetup {
logger.error("NullPointerException while handling the request", e) logger.error("NullPointerException while handling the request", e)
ctx.status(404) ctx.status(404)
} }
app.exception(NoSuchElementException::class.java) { e, ctx ->
logger.error("NoSuchElementException while handling the request", e)
ctx.status(404)
}
app.exception(IOException::class.java) { e, ctx -> app.exception(IOException::class.java) { e, ctx ->
logger.error("IOException while handling the request", e) logger.error("IOException while handling the request", e)
ctx.status(500) ctx.status(500)
@@ -257,7 +260,7 @@ object JavalinSetup {
app.get("/api/v1/manga/:mangaId/chapters") { ctx -> app.get("/api/v1/manga/:mangaId/chapters") { ctx ->
val mangaId = ctx.pathParam("mangaId").toInt() val mangaId = ctx.pathParam("mangaId").toInt()
val onlineFetch = ctx.queryParam("onlineFetch", "false").toBoolean() val onlineFetch = ctx.queryParam("onlineFetch")?.toBoolean()
ctx.json(future { getChapterList(mangaId, onlineFetch) }) ctx.json(future { getChapterList(mangaId, onlineFetch) })
} }

View File

@@ -41,6 +41,8 @@ val systemTray by lazy { systemTray() }
val androidCompat by lazy { AndroidCompat() } val androidCompat by lazy { AndroidCompat() }
fun applicationSetup() { fun applicationSetup() {
logger.info("Running Tachidesk ${BuildConfig.version} revision ${BuildConfig.revision}")
// Application dirs // Application dirs
val applicationDirs = ApplicationDirs() val applicationDirs = ApplicationDirs()
DI.global.addImport( DI.global.addImport(