feat: Added epub preview. Resolves #3375 (#3376)

This commit is contained in:
Dmitriy
2024-08-17 20:07:55 +03:00
committed by GitHub
parent a53aac1c30
commit 99a6382b32
5 changed files with 424 additions and 19 deletions

View File

@@ -6,7 +6,7 @@
@mousemove="toggleNavigation"
@touchstart="toggleNavigation"
>
<header-bar v-if="isPdf || showNav">
<header-bar v-if="isPdf || isEpub || showNav">
<action icon="close" :label="$t('buttons.close')" @action="close()" />
<title>{{ name }}</title>
<action
@@ -57,7 +57,37 @@
</div>
<template v-else>
<div class="preview">
<ExtendedImage v-if="fileStore.req?.type == 'image'" :src="raw" />
<div v-if="isEpub" class="epub-reader">
<vue-reader
:location="location"
:url="raw"
:get-rendition="getRendition"
:epubInitOptions="{
requestCredentials: true,
}"
:epubOptions="{
allowPopups: true,
allowScriptedContent: true,
}"
@update:location="locationChange"
/>
<div class="size">
<button
@click="changeSize(Math.max(100, size - 10))"
class="reader-button"
>
<i class="material-icons">remove</i>
</button>
<button
@click="changeSize(Math.min(150, size + 10))"
class="reader-button"
>
<i class="material-icons">add</i>
</button>
<span>{{ size }}%</span>
</div>
</div>
<ExtendedImage v-else-if="fileStore.req?.type == 'image'" :src="raw" />
<audio
v-else-if="fileStore.req?.type == 'audio'"
ref="player"
@@ -129,20 +159,69 @@
</template>
<script setup lang="ts">
import { useStorage } from "@vueuse/core";
import { useAuthStore } from "@/stores/auth";
import { useFileStore } from "@/stores/file";
import { useLayoutStore } from "@/stores/layout";
import { files as api } from "@/api";
import { createURL } from "@/api/utils";
import { resizePreview } from "@/utils/constants";
import url from "@/utils/url";
import throttle from "lodash/throttle";
import HeaderBar from "@/components/header/HeaderBar.vue";
import Action from "@/components/header/Action.vue";
import ExtendedImage from "@/components/files/ExtendedImage.vue";
import VideoPlayer from "@/components/files/VideoPlayer.vue";
import { VueReader } from "vue-reader";
import { computed, inject, onBeforeUnmount, onMounted, ref, watch } from "vue";
import { useRoute, useRouter } from "vue-router";
import VideoPlayer from "@/components/files/VideoPlayer.vue";
import type { Rendition } from "epubjs";
import { getTheme } from "@/utils/theme";
const location = useStorage("book-progress", 0, undefined, {
serializer: {
read: (v) => JSON.parse(v),
write: (v) => JSON.stringify(v),
},
});
const size = useStorage("book-size", 120, undefined, {
serializer: {
read: (v) => JSON.parse(v),
write: (v) => JSON.stringify(v),
},
});
const locationChange = (epubcifi: number) => {
location.value = epubcifi;
};
let rendition: Rendition | null = null;
const changeSize = (val: number) => {
size.value = val;
rendition?.themes.fontSize(`${val}%`);
};
const getRendition = (_rendition: Rendition) => {
rendition = _rendition;
switch (getTheme()) {
case "dark": {
rendition.themes.override("color", "rgba(255, 255, 255, 0.6)");
break;
}
case "light": {
rendition.themes.override("color", "rgb(111, 111, 111)");
break;
}
}
rendition.themes.registerRules("h2Transparent", {
"h1,h2,h3,h4": {
"background-color": "transparent !important",
},
});
rendition?.themes.fontSize(`${size.value}%`);
rendition.themes.select("h2Transparent");
rendition.themes.override("background-color", "transparent", true);
};
const mediaTypes: ResourceType[] = ["image", "video", "audio", "blob"];
@@ -182,10 +261,17 @@ const raw = computed(() => {
return api.getPreviewURL(fileStore.req, "big");
}
if (isEpub.value) {
return createURL("api/raw" + fileStore.req?.path, {}, false);
}
return downloadUrl.value;
});
const isPdf = computed(() => fileStore.req?.extension.toLowerCase() == ".pdf");
const isEpub = computed(
() => fileStore.req?.extension.toLowerCase() == ".epub"
);
const isResizeEnabled = computed(() => resizePreview);