From 1a7172f4775b6b94a550984e4e5ec8da0da174fe Mon Sep 17 00:00:00 2001 From: Laurent Constantin Date: Tue, 6 Aug 2024 21:51:45 +0200 Subject: [PATCH] feat(book): Theme support for ebook reader --- assets/ReadEbook.vue | 13 +++------- assets/read-ebook.js | 7 +++-- assets/styles/global.scss | 8 ++++++ src/Controller/BookController.php | 14 ++++++++-- src/Service/ThemeSelector.php | 30 ++++++++++++++++++++++ src/Twig/Runtime/ThemeExtensionRuntime.php | 12 ++++----- templates/bare.html.twig | 2 +- templates/book/reader-files-epub.html.twig | 22 ++++++++++------ templates/themes/dark/bare.html.twig | 2 +- 9 files changed, 80 insertions(+), 30 deletions(-) create mode 100644 src/Service/ThemeSelector.php diff --git a/assets/ReadEbook.vue b/assets/ReadEbook.vue index 0d8b50e0..3fdfc678 100644 --- a/assets/ReadEbook.vue +++ b/assets/ReadEbook.vue @@ -4,7 +4,7 @@ :url="props.file" :showToc="true" :getRendition="getRendition" - backgroundColor="#000" + :backgroundColor="props.bgColor" @update:location="locationChange" :location="getInitialLocation()" /> @@ -12,7 +12,7 @@ diff --git a/assets/read-ebook.js b/assets/read-ebook.js index 9c60569e..10d25f5e 100644 --- a/assets/read-ebook.js +++ b/assets/read-ebook.js @@ -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}`); }); diff --git a/assets/styles/global.scss b/assets/styles/global.scss index ec1350fa..b1f7373d 100644 --- a/assets/styles/global.scss +++ b/assets/styles/global.scss @@ -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 diff --git a/src/Controller/BookController.php b/src/Controller/BookController.php index fc44caf1..fcab7118 100644 --- a/src/Controller/BookController.php +++ b/src/Controller/BookController.php @@ -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; @@ -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', [ @@ -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': diff --git a/src/Service/ThemeSelector.php b/src/Service/ThemeSelector.php new file mode 100644 index 00000000..2de25af8 --- /dev/null +++ b/src/Service/ThemeSelector.php @@ -0,0 +1,30 @@ +getTheme() === 'dark'; + } + + public function getTheme(): ?string + { + $user = $this->security->getUser(); + + if ($user instanceof User) { + return $user->getTheme(); + } + + return null; + } +} diff --git a/src/Twig/Runtime/ThemeExtensionRuntime.php b/src/Twig/Runtime/ThemeExtensionRuntime.php index 4b080354..5efcee75 100644 --- a/src/Twig/Runtime/ThemeExtensionRuntime.php +++ b/src/Twig/Runtime/ThemeExtensionRuntime.php @@ -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; diff --git a/templates/bare.html.twig b/templates/bare.html.twig index 4ce26e9f..7e5fc1f2 100644 --- a/templates/bare.html.twig +++ b/templates/bare.html.twig @@ -12,7 +12,7 @@ {{ encore_entry_link_tags('app') }} {% endblock %} - + {% block content %}{% endblock %} {% block javascripts %} diff --git a/templates/book/reader-files-epub.html.twig b/templates/book/reader-files-epub.html.twig index d10d0ddf..99330c6d 100644 --- a/templates/book/reader-files-epub.html.twig +++ b/templates/book/reader-files-epub.html.twig @@ -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 %} @@ -7,18 +8,23 @@ {% endblock %} {% block stylesheets %} + {{ parent() }} {{ encore_entry_link_tags('read-ebook') }} - {% endblock %} {% block content %} -
+ {% 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 %} diff --git a/templates/themes/dark/bare.html.twig b/templates/themes/dark/bare.html.twig index 6c3887e9..4dfa6ef5 100644 --- a/templates/themes/dark/bare.html.twig +++ b/templates/themes/dark/bare.html.twig @@ -12,7 +12,7 @@ {{ encore_entry_link_tags('app') }} {% endblock %} - + {% block content %}{% endblock %} {% block javascripts %}