78
frontend/src/css/epubReader.css
Normal file
78
frontend/src/css/epubReader.css
Normal file
@@ -0,0 +1,78 @@
|
||||
.epub-reader {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.epub-reader .container {
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
height: calc(100% - 64px);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.epub-reader .arrow.pre {
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.epub-reader .readerArea {
|
||||
background-color: var(--background) !important;
|
||||
}
|
||||
|
||||
.epub-reader .titleArea {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.epub-reader .tocButtonBar {
|
||||
background: var(--divider);
|
||||
}
|
||||
|
||||
.epub-reader .tocButton {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.epub-reader .tocButton.tocButtonExpanded {
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.epub-reader .tocAreaButton.active {
|
||||
color: var(--blue);
|
||||
border-color: var(--dark-blue);
|
||||
}
|
||||
|
||||
.epub-reader .tocArea {
|
||||
background-color: var(--background);
|
||||
}
|
||||
|
||||
.epub-reader .readerArea .arrow {
|
||||
color: var(--text);
|
||||
}
|
||||
|
||||
.epub-reader .readerArea .arrow:hover {
|
||||
color: var(--hover);
|
||||
}
|
||||
|
||||
.epub-reader .size {
|
||||
display: flex;
|
||||
gap: 5px;
|
||||
align-items: center;
|
||||
z-index: 111;
|
||||
right: 25px;
|
||||
outline: none;
|
||||
position: absolute;
|
||||
top: 78px;
|
||||
}
|
||||
|
||||
.epub-reader .size span {
|
||||
color: var(--textSecondary);
|
||||
}
|
||||
|
||||
.epub-reader .size button {
|
||||
background: none;
|
||||
outline: none;
|
||||
border: none;
|
||||
width: 25px;
|
||||
height: 25px;
|
||||
color: var(--textPrimary);
|
||||
padding: 0;
|
||||
}
|
||||
@@ -15,6 +15,7 @@
|
||||
@import "./dashboard.css";
|
||||
@import "./login.css";
|
||||
@import "./mobile.css";
|
||||
@import "./epubReader.css";
|
||||
|
||||
/* For testing only
|
||||
:focus {
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user