Update quarkus to version 3.30.2
* Also adds a bunch of old things I don't remember writing
This commit is contained in:
2
Makefile
2
Makefile
@@ -1,5 +1,5 @@
|
|||||||
executable:
|
executable:
|
||||||
./mvnw package -Pnative -Dquarkus.native.additional-build-args="--initialize-at-run-time=sun.java2d.Disposer" $(EXECUTABLE_ARGS)
|
./mvnw package -Pnative -Dquarkus.native.file-encoding=UTF-8 -Dquarkus.native.additional-build-args="--initialize-at-run-time=sun.java2d.Disposer" $(EXECUTABLE_ARGS)
|
||||||
|
|
||||||
image:
|
image:
|
||||||
docker build -t rhiobet/lalafin$(IMAGE_TAG) . -f src/main/docker/Dockerfile.native
|
docker build -t rhiobet/lalafin$(IMAGE_TAG) . -f src/main/docker/Dockerfile.native
|
||||||
|
|||||||
@@ -18,7 +18,9 @@ stdenv.mkDerivation rec {
|
|||||||
'';
|
'';
|
||||||
|
|
||||||
postFixup = ''
|
postFixup = ''
|
||||||
wrapProgram $out/bin/lalafin --prefix PATH : ${pkgs.imagemagick}/bin
|
wrapProgram $out/bin/lalafin \
|
||||||
|
--prefix PATH : ${pkgs.imagemagick}/bin \
|
||||||
|
--prefix LD_LIBRARY_PATH : ${pkgs.stdenv.cc.cc.lib}/lib
|
||||||
'';
|
'';
|
||||||
|
|
||||||
meta = with lib; {
|
meta = with lib; {
|
||||||
|
|||||||
23
pom.xml
23
pom.xml
@@ -6,17 +6,17 @@
|
|||||||
<artifactId>lalafin</artifactId>
|
<artifactId>lalafin</artifactId>
|
||||||
<version>1.0-SNAPSHOT</version>
|
<version>1.0-SNAPSHOT</version>
|
||||||
<properties>
|
<properties>
|
||||||
<compiler-plugin.version>3.8.1</compiler-plugin.version>
|
<compiler-plugin.version>3.12.1</compiler-plugin.version>
|
||||||
<maven.compiler.parameters>true</maven.compiler.parameters>
|
<maven.compiler.parameters>true</maven.compiler.parameters>
|
||||||
<maven.compiler.source>11</maven.compiler.source>
|
<maven.compiler.source>17</maven.compiler.source>
|
||||||
<maven.compiler.target>11</maven.compiler.target>
|
<maven.compiler.target>17</maven.compiler.target>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
|
||||||
<quarkus-plugin.version>3.4.1</quarkus-plugin.version>
|
<quarkus-plugin.version>3.30.2</quarkus-plugin.version>
|
||||||
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
<quarkus.platform.artifact-id>quarkus-bom</quarkus.platform.artifact-id>
|
||||||
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
|
<quarkus.platform.group-id>io.quarkus</quarkus.platform.group-id>
|
||||||
<quarkus.platform.version>3.4.1</quarkus.platform.version>
|
<quarkus.platform.version>3.30.2</quarkus.platform.version>
|
||||||
<surefire-plugin.version>2.22.1</surefire-plugin.version>
|
<surefire-plugin.version>3.2.3</surefire-plugin.version>
|
||||||
</properties>
|
</properties>
|
||||||
<dependencyManagement>
|
<dependencyManagement>
|
||||||
<dependencies>
|
<dependencies>
|
||||||
@@ -32,19 +32,19 @@
|
|||||||
<dependencies>
|
<dependencies>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-resteasy-reactive</artifactId>
|
<artifactId>quarkus-rest</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-resteasy-reactive-qute</artifactId>
|
<artifactId>quarkus-rest-qute</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-resteasy-reactive-jackson</artifactId>
|
<artifactId>quarkus-rest-jackson</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
<artifactId>quarkus-resteasy-reactive-jaxb</artifactId>
|
<artifactId>quarkus-rest-jaxb</artifactId>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>io.quarkus</groupId>
|
<groupId>io.quarkus</groupId>
|
||||||
@@ -107,7 +107,8 @@
|
|||||||
<profile>
|
<profile>
|
||||||
<id>native</id>
|
<id>native</id>
|
||||||
<properties>
|
<properties>
|
||||||
<quarkus.package.type>native</quarkus.package.type>
|
<quarkus.native.enabled>true</quarkus.native.enabled>
|
||||||
|
<quarkus.package.jar.enabled>false</quarkus.package.jar.enabled>
|
||||||
</properties>
|
</properties>
|
||||||
<build>
|
<build>
|
||||||
<plugins>
|
<plugins>
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
package sh.rhiobet.lalafin.api;
|
package sh.rhiobet.lalafin.api;
|
||||||
|
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
|
import java.net.URLEncoder;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.GET;
|
import jakarta.ws.rs.GET;
|
||||||
@@ -50,12 +52,25 @@ public class FilePublicAPI {
|
|||||||
String decodedFile = URLDecoder.decode(token.file, StandardCharsets.UTF_8);
|
String decodedFile = URLDecoder.decode(token.file, StandardCharsets.UTF_8);
|
||||||
if (request.remoteAddress().host().toString().equals(token.ip)
|
if (request.remoteAddress().host().toString().equals(token.ip)
|
||||||
&& System.currentTimeMillis() < token.timestamp + 172800000) {
|
&& System.currentTimeMillis() < token.timestamp + 172800000) {
|
||||||
FileInfoBase fileInfoBase = fileInfoService.getInfo(decodedFile.split("/"), null);
|
String[] decodedFileSplitted = decodedFile.split("/");
|
||||||
|
FileInfoBase fileInfoBase;
|
||||||
|
if (decodedFileSplitted[decodedFileSplitted.length - 2].endsWith(".zip")) {
|
||||||
|
fileInfoBase = fileInfoService.getInfo(
|
||||||
|
Arrays.copyOf(decodedFileSplitted, decodedFileSplitted.length - 1), null);
|
||||||
|
if (fileInfoBase instanceof FileInfo) {
|
||||||
|
return fileServeService.serveArchiveContent((FileInfo) fileInfoBase,
|
||||||
|
decodedFileSplitted[decodedFileSplitted.length - 1]);
|
||||||
|
} else {
|
||||||
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fileInfoBase = fileInfoService.getInfo(decodedFileSplitted, null);
|
||||||
if (fileInfoBase instanceof FileInfo) {
|
if (fileInfoBase instanceof FileInfo) {
|
||||||
return fileServeService.serveFile((FileInfo) fileInfoBase, range);
|
return fileServeService.serveFile((FileInfo) fileInfoBase, range);
|
||||||
} else {
|
} else {
|
||||||
return Response.status(Response.Status.NOT_FOUND).build();
|
return Response.status(Response.Status.NOT_FOUND).build();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
return Response.status(Response.Status.FORBIDDEN).build();
|
return Response.status(Response.Status.FORBIDDEN).build();
|
||||||
}
|
}
|
||||||
|
|||||||
30
src/main/java/sh/rhiobet/lalafin/api/model/ArchiveInfo.java
Normal file
30
src/main/java/sh/rhiobet/lalafin/api/model/ArchiveInfo.java
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package sh.rhiobet.lalafin.api.model;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||||
|
import io.quarkus.runtime.annotations.RegisterForReflection;
|
||||||
|
|
||||||
|
@RegisterForReflection
|
||||||
|
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||||
|
public class ArchiveInfo extends FileInfo {
|
||||||
|
|
||||||
|
public List<FileInfoBase> content;
|
||||||
|
|
||||||
|
public ArchiveInfo(String filename, String thumbnailUrl, String directUrl, String viewUrl,
|
||||||
|
String publicApiUrl) {
|
||||||
|
super(filename, thumbnailUrl, directUrl, publicApiUrl);
|
||||||
|
this.content = new ArrayList<>();
|
||||||
|
this.viewUrl = viewUrl;
|
||||||
|
this.type = "archive";
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArchiveInfo(String filename, String thumbnailUrl, String directUrl, String viewUrl) {
|
||||||
|
this(filename, thumbnailUrl, directUrl, viewUrl, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArchiveInfo(String filename, String directUrl) {
|
||||||
|
this(filename, "", directUrl, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -84,10 +84,14 @@ public class JellyfinThumbnailGenerator implements ThumbnailGenerator {
|
|||||||
try {
|
try {
|
||||||
Optional<Path> imgPath;
|
Optional<Path> imgPath;
|
||||||
|
|
||||||
Path posterPath = folderPath.resolve("poster.jpg");
|
Path posterPathJpg = folderPath.resolve("poster.jpg");
|
||||||
if (Files.exists(posterPath)) {
|
Path posterPathPng = folderPath.resolve("poster.png");
|
||||||
// Check for series poster
|
if (Files.exists(posterPathJpg)) {
|
||||||
imgPath = Optional.of(posterPath);
|
// Check for series poster (jpg)
|
||||||
|
imgPath = Optional.of(posterPathJpg);
|
||||||
|
} else if (Files.exists(posterPathPng)) {
|
||||||
|
// Check for series poster (png)
|
||||||
|
imgPath = Optional.of(posterPathPng);
|
||||||
} else if (folderPath.getFileName().toString().startsWith("Season ")
|
} else if (folderPath.getFileName().toString().startsWith("Season ")
|
||||||
|| (folderPath.getFileName().toString().equals("Specials"))) {
|
|| (folderPath.getFileName().toString().equals("Specials"))) {
|
||||||
// Season folder
|
// Season folder
|
||||||
@@ -95,10 +99,22 @@ public class JellyfinThumbnailGenerator implements ThumbnailGenerator {
|
|||||||
if (folderName.startsWith("Season ")) {
|
if (folderName.startsWith("Season ")) {
|
||||||
String seasonNumber =
|
String seasonNumber =
|
||||||
String.format("%02d", Integer.parseInt(folderName.substring(7)));
|
String.format("%02d", Integer.parseInt(folderName.substring(7)));
|
||||||
imgPath = Optional
|
Path seasonPathJpg =
|
||||||
.of(folderPath.resolveSibling("season" + seasonNumber + "-poster.jpg"));
|
folderPath.resolveSibling("season" + seasonNumber + "-poster.jpg");
|
||||||
|
if (Files.exists(seasonPathJpg)) {
|
||||||
|
imgPath = Optional.of(seasonPathJpg);
|
||||||
} else {
|
} else {
|
||||||
imgPath = Optional.of(folderPath.resolveSibling("season-specials-poster.jpg"));
|
imgPath = Optional.of(folderPath
|
||||||
|
.resolveSibling("season" + seasonNumber + "-poster.png"));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Path specialsPathJpg = folderPath.resolveSibling("season-specials-poster.jpg");
|
||||||
|
if (Files.exists(specialsPathJpg)) {
|
||||||
|
imgPath = Optional.of(specialsPathJpg);
|
||||||
|
} else {
|
||||||
|
imgPath = Optional
|
||||||
|
.of(folderPath.resolveSibling("season-specials-poster.png"));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
imgPath = Optional.empty();
|
imgPath = Optional.empty();
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import java.nio.file.Path;
|
|||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.core.PathSegment;
|
import jakarta.ws.rs.core.PathSegment;
|
||||||
@@ -16,6 +17,7 @@ import sh.rhiobet.lalafin.LalafinConfiguration;
|
|||||||
import sh.rhiobet.lalafin.api.advent.AdventAccessService;
|
import sh.rhiobet.lalafin.api.advent.AdventAccessService;
|
||||||
import sh.rhiobet.lalafin.api.configuration.FileApiConfiguration;
|
import sh.rhiobet.lalafin.api.configuration.FileApiConfiguration;
|
||||||
import sh.rhiobet.lalafin.api.internal.redis.FileTokenProvider;
|
import sh.rhiobet.lalafin.api.internal.redis.FileTokenProvider;
|
||||||
|
import sh.rhiobet.lalafin.api.model.ArchiveInfo;
|
||||||
import sh.rhiobet.lalafin.api.model.FileInfo;
|
import sh.rhiobet.lalafin.api.model.FileInfo;
|
||||||
import sh.rhiobet.lalafin.api.model.FileInfoBase;
|
import sh.rhiobet.lalafin.api.model.FileInfoBase;
|
||||||
import sh.rhiobet.lalafin.api.model.FolderInfo;
|
import sh.rhiobet.lalafin.api.model.FolderInfo;
|
||||||
@@ -110,7 +112,7 @@ public class FileInfoService {
|
|||||||
}
|
}
|
||||||
StringBuilder playlistContent = new StringBuilder();
|
StringBuilder playlistContent = new StringBuilder();
|
||||||
try {
|
try {
|
||||||
Stream<Path> stream = Files.list(path);
|
Stream<Path> stream = Files.list(path).sorted();
|
||||||
stream.forEach(p -> {
|
stream.forEach(p -> {
|
||||||
String fileName = p.getFileName().toString();
|
String fileName = p.getFileName().toString();
|
||||||
String fileUri = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
|
String fileUri = URLEncoder.encode(fileName, StandardCharsets.UTF_8)
|
||||||
@@ -214,14 +216,41 @@ public class FileInfoService {
|
|||||||
} else {
|
} else {
|
||||||
String requestedFilenameUri = URLEncoder
|
String requestedFilenameUri = URLEncoder
|
||||||
.encode(requestedFilename, StandardCharsets.UTF_8).replace("+", "%20");
|
.encode(requestedFilename, StandardCharsets.UTF_8).replace("+", "%20");
|
||||||
|
if (requestedFilename.endsWith(".zip")) {
|
||||||
|
ArchiveInfo archiveInfo = new ArchiveInfo(requestedFilename, "/file" + requestedUri);
|
||||||
|
if (!requestedThumbUrl.isEmpty()) {
|
||||||
|
archiveInfo.thumbnailUrl = requestedThumbUrl;
|
||||||
|
}
|
||||||
|
archiveInfo.viewUrl = "/view" + requestedUri + "/1";
|
||||||
|
|
||||||
|
Path zipPath = Paths.get(fileApiConfiguration.directory() + "/file/" + requestedPath);
|
||||||
|
try {
|
||||||
|
ZipFile zipFile = new ZipFile(zipPath.toFile());
|
||||||
|
zipFile.stream().filter(e -> !e.isDirectory()).forEach(e -> {
|
||||||
|
String zipEntryName = e.getName();
|
||||||
|
String zipEntryNameUri =
|
||||||
|
URLEncoder.encode(zipEntryName, StandardCharsets.UTF_8).replace("+", "%20");
|
||||||
|
String zipEntryUri = requestedUri + "/" + zipEntryNameUri;
|
||||||
|
FileInfo zipEntryInfo = new FileInfo(zipEntryName, "/file" + zipEntryUri);
|
||||||
|
if (fileTokenProvider != null) {
|
||||||
|
zipEntryInfo.publicApiUrl = "/api/public/file/token/"
|
||||||
|
+ fileTokenProvider.getFileToken(zipEntryUri) + "/" + zipEntryNameUri;
|
||||||
|
}
|
||||||
|
archiveInfo.content.add(zipEntryInfo);
|
||||||
|
});
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
return archiveInfo;
|
||||||
|
} else {
|
||||||
FileInfo fileInfo = new FileInfo(requestedFilename, "/file" + requestedUri);
|
FileInfo fileInfo = new FileInfo(requestedFilename, "/file" + requestedUri);
|
||||||
if (!requestedThumbUrl.isEmpty()) {
|
if (!requestedThumbUrl.isEmpty()) {
|
||||||
fileInfo.thumbnailUrl = requestedThumbUrl;
|
fileInfo.thumbnailUrl = requestedThumbUrl;
|
||||||
}
|
}
|
||||||
if (fileTokenProvider != null) {
|
if (fileTokenProvider != null) {
|
||||||
fileInfo.publicApiUrl =
|
fileInfo.publicApiUrl = "/api/public/file/token/"
|
||||||
"/api/public/file/token/" + fileTokenProvider.getFileToken(requestedUri)
|
+ fileTokenProvider.getFileToken(requestedUri) + "/" + requestedFilenameUri;
|
||||||
+ "/" + requestedFilenameUri;
|
|
||||||
}
|
}
|
||||||
if (requestedFilename.endsWith(".zip")) {
|
if (requestedFilename.endsWith(".zip")) {
|
||||||
fileInfo.viewUrl = "/view" + requestedUri + "/1";
|
fileInfo.viewUrl = "/view" + requestedUri + "/1";
|
||||||
@@ -231,6 +260,7 @@ public class FileInfoService {
|
|||||||
return fileInfo;
|
return fileInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,6 +8,8 @@ import java.nio.channels.FileChannel;
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.nio.file.Paths;
|
import java.nio.file.Paths;
|
||||||
|
import java.util.zip.ZipEntry;
|
||||||
|
import java.util.zip.ZipFile;
|
||||||
import jakarta.enterprise.context.ApplicationScoped;
|
import jakarta.enterprise.context.ApplicationScoped;
|
||||||
import jakarta.inject.Inject;
|
import jakarta.inject.Inject;
|
||||||
import jakarta.ws.rs.core.Response;
|
import jakarta.ws.rs.core.Response;
|
||||||
@@ -100,6 +102,31 @@ public class FileServeService {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Response serveArchiveContent(FileInfo fileInfo, String name) {
|
||||||
|
try {
|
||||||
|
Path path = Paths.get(fileApiConfiguration.directory(),
|
||||||
|
URLDecoder.decode(fileInfo.directUrl, StandardCharsets.UTF_8));
|
||||||
|
ZipFile zipFile = new ZipFile(path.toFile());
|
||||||
|
ZipEntry zipEntry = zipFile.getEntry(name);
|
||||||
|
|
||||||
|
if (zipEntry == null) {
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
|
|
||||||
|
ResponseBuilder response;
|
||||||
|
long fileSize = zipEntry.getSize();
|
||||||
|
|
||||||
|
response = Response.ok(zipFile.getInputStream(zipEntry));
|
||||||
|
response.header("Content-Length", Long.toString(fileSize));
|
||||||
|
|
||||||
|
response.header("Accept-Ranges", "bytes");
|
||||||
|
response.header("Content-Disposition", "inline; filename=\"" + name + "\"");
|
||||||
|
response.header("Content-Type", FileHelper.getMimeType(name));
|
||||||
|
return response.build();
|
||||||
|
} catch (IOException e) {
|
||||||
|
return Response.status(Response.Status.INTERNAL_SERVER_ERROR).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class FileServeInputStream extends InputStream {
|
class FileServeInputStream extends InputStream {
|
||||||
|
|||||||
@@ -5,24 +5,72 @@
|
|||||||
<meta name="mobile-web-app-capable" content="yes" />
|
<meta name="mobile-web-app-capable" content="yes" />
|
||||||
<link rel="stylesheet" href="/style/sakura.css" />
|
<link rel="stylesheet" href="/style/sakura.css" />
|
||||||
<title>{info.filename}</title>
|
<title>{info.filename}</title>
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<table style="table-layout: fixed;">
|
<table style="table-layout: fixed;">
|
||||||
<tr>
|
<tr>
|
||||||
<td style="text-align: left; padding-top: 0; padding-bottom: 0;"><a href="{info.directUrl}/..">back</a></td>
|
<td style="text-align: left; padding-top: 0; padding-bottom: 0;"><a href="{info.directUrl}/..">back</a></td>
|
||||||
<td style="text-align: center; padding-top: 0; padding-bottom: 0;">{currpage}/{totpage}</td>
|
<td id="viewer-page-counter" style="text-align: center; padding-top: 0; padding-bottom: 0;">{currpage}/{totpage}</td>
|
||||||
<td style="text-align: right; padding-top: 0; padding-bottom: 0;">{#if currpage > 1}<a href="{prevuri}"><</a> {/if}{#if currpage < totpage}<a href="{nexturi}">></a>{/if}</td>
|
<td style="text-align: right; padding-top: 0; padding-bottom: 0;"><a id="viewer-page-navigation-left" {#if currpage > 1}href="{prevuri}"{/if}><</a> <a id="viewer-page-navigation-right" {#if currpage < totpage}href="{nexturi}"{/if}>></a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
<hr />
|
<hr />
|
||||||
{#if currpage < totpage}<a href="{nexturi}">{/if}
|
{#if currpage < totpage}<a id="viewer-page-link" href="{nexturi}">{/if}
|
||||||
{#if image??}
|
{#if image??}
|
||||||
<img style="position: absolute; left: 50%; transform: translate(-50%, 0);" src="{image}" />
|
<img id="viewer-page-image" style="position: absolute; left: 50%; transform: translate(-50%, 0);" src="{image}" />
|
||||||
{#else if video??}
|
{#else if video??}
|
||||||
<video src="{video}" controls style="width: 100%"></video>
|
<video src="{video}" controls style="width: 100%"></video>
|
||||||
{/if}
|
{/if}
|
||||||
{#if currpage < totpage}</a>{/if}
|
{#if currpage < totpage}</a>{/if}
|
||||||
<hr />
|
<hr />
|
||||||
|
{#if image??}
|
||||||
|
<script>
|
||||||
|
var pages = [];
|
||||||
|
var preloadedPages = [];
|
||||||
|
$.getJSON('/api/private{info.directUrl}', function(data) {
|
||||||
|
for (const c of data.content) {
|
||||||
|
pages.push(c.publicApiUrl);
|
||||||
|
}
|
||||||
|
for (const page of pages) {
|
||||||
|
preloadedPages.push(new Promise(resolve => {
|
||||||
|
const img = new Image();
|
||||||
|
img.src = page;
|
||||||
|
resolve(img);
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
displayPage({currpage});
|
||||||
|
});
|
||||||
|
function displayPage(pageNumber) {
|
||||||
|
var imgtag = document.getElementById("viewer-page-image");
|
||||||
|
var atag = document.getElementById("viewer-page-link");
|
||||||
|
atag.setAttribute("href", "#");
|
||||||
|
|
||||||
|
var leftatag = document.getElementById("viewer-page-navigation-left");
|
||||||
|
leftatag.setAttribute('href', '#');
|
||||||
|
if (pageNumber > 1) {
|
||||||
|
leftatag.setAttribute('onClick', 'displayPage(' + (pageNumber-1) + ')');
|
||||||
|
}
|
||||||
|
|
||||||
|
var rightatag = document.getElementById("viewer-page-navigation-right");
|
||||||
|
if (pageNumber < pages.length) {
|
||||||
|
rightatag.setAttribute('href', '#');
|
||||||
|
rightatag.setAttribute('onClick', 'displayPage(' + (pageNumber+1) + ')');
|
||||||
|
atag.setAttribute('onClick', 'displayPage(' + (pageNumber+1) + ')');
|
||||||
|
}
|
||||||
|
if (typeof preloadedPages !== "undefined" && preloadedPages.length > 0) {
|
||||||
|
preloadedPages[pageNumber-1].then(img => {
|
||||||
|
img.setAttribute('id', imgtag.id)
|
||||||
|
img.setAttribute('style', imgtag.style.cssText);
|
||||||
|
atag.innerHTML = '';
|
||||||
|
atag.appendChild(img);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var middlespantag = document.getElementById("viewer-page-counter");
|
||||||
|
middlespantag.innerHTML = pageNumber + "/" + pages.length;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{/if}
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user