Skip to content

Commit

Permalink
feat(book): Theme support for ebook reader
Browse files Browse the repository at this point in the history
  • Loading branch information
ragusa87 authored and SergioMendolia committed Aug 11, 2024
1 parent 9632229 commit 1a7172f
Show file tree
Hide file tree
Showing 9 changed files with 80 additions and 30 deletions.
13 changes: 4 additions & 9 deletions assets/ReadEbook.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
:url="props.file"
:showToc="true"
:getRendition="getRendition"
backgroundColor="#000"
:backgroundColor="props.bgColor"
@update:location="locationChange"
:location="getInitialLocation()"
/>
</div>
</template>

<script setup>
const props = defineProps({'file': String})
const props = defineProps({'file': String, 'css': String, 'bgColor': String})
import { VueReader } from 'vue-book-reader'
const initialCfi = new URLSearchParams(window.location.search).get('cfi');
Expand All @@ -25,14 +25,9 @@ const locationChange = (detail) => {
const getInitialLocation = () => {
return initialCfi ?? null
}
const getRendition = async (rendition) => {
rendition.renderer.setStyles([
`
html {
background: #000;
color: #fff;
}`,
])
rendition.renderer.setStyles([props.css])
}
</script>
7 changes: 5 additions & 2 deletions assets/read-ebook.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ import { createApp } from 'vue'
import ReadEBook from './ReadEbook.vue'

document.addEventListener('DOMContentLoaded', () => {
const file = document.getElementById('mount').getAttribute('data-file')
createApp(ReadEBook, {file: file}).mount('#mount');
const mountId = 'vue-book-reader';
const file = document.getElementById(mountId).getAttribute('data-file')
const css = document.getElementById(mountId).getAttribute('data-css')
const bgColor = document.getElementById(mountId).getAttribute('data-background-color')
createApp(ReadEBook, {file: file, css: css, bgColor: bgColor}).mount(`#${mountId}`);
});
8 changes: 8 additions & 0 deletions assets/styles/global.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@
@import "~bootstrap/scss/bootstrap";
@import "~bootstrap-icons/font/bootstrap-icons.css";

body.bg-darker{
background-color: #000;
color: #fff;
}

#vue-book-reader{
width: 100%;
}

/*
* Sidebar
Expand Down
14 changes: 12 additions & 2 deletions src/Controller/BookController.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Entity\User;
use App\Repository\BookRepository;
use App\Service\BookFileSystemManager;
use App\Service\ThemeSelector;
use Doctrine\ORM\EntityManagerInterface;
use Knp\Component\Pager\PaginatorInterface;
use Symfony\Component\Form\Extension\Core\Type\FileType;
Expand Down Expand Up @@ -85,8 +86,15 @@ public function index(Book $book, string $slug, BookRepository $bookRepository,
}

#[Route('/{book}/{slug}/read', name: 'app_book_read')]
public function read(Request $request, Book $book, string $slug, BookFileSystemManager $fileSystemManager, PaginatorInterface $paginator, EntityManagerInterface $manager): Response
{
public function read(
Request $request,
Book $book,
string $slug,
BookFileSystemManager $fileSystemManager,
PaginatorInterface $paginator,
ThemeSelector $themeSelector,
EntityManagerInterface $manager
): Response {
set_time_limit(120);
if ($slug !== $book->getSlug()) {
return $this->redirectToRoute('app_book', [
Expand All @@ -107,6 +115,8 @@ public function read(Request $request, Book $book, string $slug, BookFileSystemM
return $this->render('book/reader-files-epub.html.twig', [
'book' => $book,
'file' => $fileSystemManager->getBookPublicPath($book),
'body_class' => $themeSelector->isDark() ? 'bg-darker' : '',
'isDark' => $themeSelector->isDark(),
]);
case 'pdf':
case 'cbr':
Expand Down
30 changes: 30 additions & 0 deletions src/Service/ThemeSelector.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

namespace App\Service;

use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;

class ThemeSelector
{
public function __construct(
private Security $security,
) {
}

public function isDark(): bool
{
return $this->getTheme() === 'dark';
}

public function getTheme(): ?string
{
$user = $this->security->getUser();

if ($user instanceof User) {
return $user->getTheme();
}

return null;
}
}
12 changes: 5 additions & 7 deletions src/Twig/Runtime/ThemeExtensionRuntime.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,21 @@

namespace App\Twig\Runtime;

use App\Entity\User;
use Symfony\Bundle\SecurityBundle\Security;
use App\Service\ThemeSelector;
use Twig\Extension\RuntimeExtensionInterface;

class ThemeExtensionRuntime implements RuntimeExtensionInterface
{
public function __construct(private Security $security)
public function __construct(private ThemeSelector $themeSelector)
{
// Inject dependencies if needed
}

public function themedTemplate(string $value): string|array
{
$user = $this->security->getUser();
$theme = $this->themeSelector->getTheme();

if ($user instanceof User) {
return ['themes/'.$user->getTheme().'/'.$value, $value];
if ($theme !== null) {
return ['themes/'.$theme.'/'.$value, $value];
}

return $value;
Expand Down
2 changes: 1 addition & 1 deletion templates/bare.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{{ encore_entry_link_tags('app') }}
{% endblock %}
</head>
<body>
<body {{ (body_class is defined and body_class ? 'class="' ~ (body_class|e('html_attr'))~'"' : '')|raw }}>
{% block content %}{% endblock %}

{% block javascripts %}
Expand Down
22 changes: 14 additions & 8 deletions templates/book/reader-files-epub.html.twig
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
{% extends themedTemplate('bare.html.twig') %}
{% set isDark = isDark|default(false) %}

{% block title %}{{ book.authors|first }} {% if book.serie is not null %}> {{ book.serie }} #{{ book.serieIndex }} {% endif %}> {{ book.title }}{% endblock %}
{% block javascripts %}
Expand All @@ -7,18 +8,23 @@
{% endblock %}

{% block stylesheets %}
{{ parent() }}
{{ encore_entry_link_tags('read-ebook') }}
<style>
body
{
background-color: #000;
color: #fff;
}
</style>
{% endblock %}

{% block content %}
<div id="mount" data-file="{{ file }}" style="width: 100%">
<div id="vue-book-reader" data-file="{{ file }}" data-css="{{ block('readercss')|e('html_attr') }}" data-background-color="{{ isDark ? '#000' : '#fff' }}">
<a href="{{ file }}">Loading book</a>
</div>
{% endblock %}

{% block readercss %}
{# This css is injected to the vue-book-reader component, in a shadow root, so it's not possible to use --vars. #}
html {
background: {{ isDark ? '#000' : '#fff' }};
color: {{ isDark ? '#fff' : '#000' }};
}
a {
color: #24599d;
}
{% endblock %}
2 changes: 1 addition & 1 deletion templates/themes/dark/bare.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
{{ encore_entry_link_tags('app') }}
{% endblock %}
</head>
<body>
<body {{ (body_class is defined and body_class ? 'class="' ~ (body_class|e('html_attr'))~'"' : '')|raw }}>
{% block content %}{% endblock %}

{% block javascripts %}
Expand Down

0 comments on commit 1a7172f

Please sign in to comment.