New reader based on reveal.js. works well on mobile and desktop and gives a better expierance all around.

This commit is contained in:
ajurna
2020-05-20 10:26:45 +01:00
parent 2debda7abc
commit be32796bea
43 changed files with 16776 additions and 72 deletions

View File

@@ -131,13 +131,9 @@ class ComicBook(models.Model):
out.prev_index = page - 1
out.prev_path = out.cur_path
if self.is_last_page(page):
out.next_path, out.next_index = self.nav_get_next_comic(user)
if out.next_index == -1:
out.q_next_to_directory = True
else:
out.next_index = page + 1
out.next_path = out.cur_path
out.next_path, out.next_index = self.nav_get_next_comic(user)
if out.next_index == -1:
out.q_next_to_directory = True
return out
def nav_get_prev_comic(self, user):

View File

@@ -20,6 +20,9 @@
<link href="{% static "css/base.css" %}" rel="stylesheet">
<link href="{% static "font-awesome/css/all.css" %}" rel="stylesheet">
{# <link href="{% static "reveal.js/css/reveal.css" %}" rel="stylesheet">#}
{# <link href="{% static "reveal.js/css/theme/white.css" %}" rel="stylesheet">#}
</head>
@@ -51,9 +54,9 @@
<!-- /.container -->
<footer class="footer">
<div class="container centered">
<center><a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons Licence" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/InteractiveResource" property="dct:title" rel="dct:type">CBReader</span> by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Ajurna</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://github.com/ajurna/cbreader" rel="dct:source">https://github.com/ajurna/cbreader</a>.</center>
<footer class="footer mt-auto py-3">
<div class="container text-center">
<a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/"><img alt="Creative Commons Licence" style="border-width:0" src="https://i.creativecommons.org/l/by-sa/4.0/88x31.png" /></a><br /><span xmlns:dct="http://purl.org/dc/terms/" href="http://purl.org/dc/dcmitype/InteractiveResource" property="dct:title" rel="dct:type">CBReader</span> by <span xmlns:cc="http://creativecommons.org/ns#" property="cc:attributionName">Ajurna</span> is licensed under a <a rel="license" href="http://creativecommons.org/licenses/by-sa/4.0/">Creative Commons Attribution-ShareAlike 4.0 International License</a>.<br />Based on a work at <a xmlns:dct="http://purl.org/dc/terms/" href="https://github.com/ajurna/cbreader" rel="dct:source">https://github.com/ajurna/cbreader</a>.
</div>
</footer>
@@ -63,6 +66,9 @@
{% bootstrap_javascript jquery='full' %}
<script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.21/b-1.6.2/b-colvis-1.6.2/r-2.2.4/datatables.min.js"></script>
<script type="text/javascript" src="{% static "js/js.cookie.js" %}"></script>
<script type="text/javascript" src="{% static "reveal.js/js/reveal.js" %}"></script>
<script type="text/javascript" src="{% static "js/hammer.min.js" %}"></script>
{% block script %}
{% endblock %}
</body>

View File

@@ -2,47 +2,99 @@
{% block title %}{{ title }}{% endblock %}
{% block content %}
<div class="container comic_box justify-content-center">
<div class="row justify-content-center">
{% if nav.q_next_to_directory %}
<a href="/comic/{{ nav.next_path }}/">
{% else %}
<a href="/comic/read/{{ nav.next_path }}/{{ nav.next_index }}/">
{% endif %}
<img src="/comic/read/{{ nav.cur_path }}/{{ nav.cur_index }}/img" class="img-fluid">
</a>
</div>
<div class="row justify-content-center mt-1 mb-1">
<div class="btn-group" role="group" aria-label="Navigation">
{% if nav.q_prev_to_directory %}
{% if nav.prev_path %}
<a href="/comic/{{ nav.prev_path }}/" class="btn btn-secondary">Prev</a>
{% else %}
<a href="/comic/" class="btn btn-secondary">Prev</a>
{% endif %}
{% else %}
<a href="/comic/read/{{ nav.prev_path }}/{{ nav.prev_index }}/" class="btn btn-secondary">Prev</a>
{% endif %}
<div class="btn-group" role="group">
<button id="page_list" type="button" class="btn btn-secondary dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ orig_file_name }}
</button>
<div class="dropdown-menu" aria-labelledby="page_list">
{% for file in book.pages %}
<a class="dropdown-item" href="/comic/read/{{ nav.cur_path }}/{{ file.index }}/">{{ file.page_file_name }}</a>
{% endfor %}
</div>
</div>
{% if nav.q_next_to_directory %}
{% if nav.next_path %}
<a href="/comic/{{ nav.next_path }}/" class="btn btn-secondary">Next</a>
{% else %}
<a href="/comic/" class="btn btn-secondary">Next</a>
{% endif %}
{% else %}
<a href="/comic/read/{{ nav.next_path }}/{{ nav.next_index }}/" class="btn btn-secondary">Next</a>
{% endif %}
</div>
</div>
</div>
<div class="reveal" id="comic_box">
<div class="slides">
{% for page in pages %}
<section><img data-src="{% url "get_image" nav.cur_path page.index %}" class=" w-100" onclick="Reveal.next()"></section>
{% endfor %}
</div>
</div>
{% endblock %}
{% block script %}
<script>
Reveal.initialize({
controls: false,
hash: true,
width: "100%",
height: "100%",
margin: 0,
minScale: 1,
maxScale: 1,
disableLayout: true,
keyboard: false,
touch: false,
transition: 'slide',
});
Reveal.setState({indexh: {{ status.last_read_page }} });
Reveal.addEventListener( 'slidechanged', function( event ) {
// event.previousSlide, event.currentSlide, event.indexh, event.indexv
document.getElementsByClassName('present')[0].scrollIntoView({behavior: 'smooth'})
$.ajax({url: "/comic/set_page/{{nav.cur_path}}/" + event.indexh + "/"})
} );
$(document).keydown(function(e) {
switch(e.which) {
case 37: // left
if (Reveal.isFirstSlide()){
window.location = "{% url "read_comic" nav.prev_path %}"
} else {
Reveal.prev();
}
break;
case 38: // up
window.scrollTo({
top: window.scrollY-window.innerHeight*.7,
left: 0,
behavior: 'smooth'
});
break;
case 39: // right
if (Reveal.isLastSlide()){
window.location = "{% url "read_comic" nav.next_path %}"
} else {
Reveal.next()
}
break;
case 40: // down
window.scrollTo({
top: window.scrollY+window.innerHeight*.7,
left: 0,
behavior: 'smooth'
});
break;
default: return; // exit this handler for other keys
}
e.preventDefault(); // prevent the default action (scroll / move caret)
});
var hammertime = new Hammer(document.getElementById('comic_box'), {});
hammertime.on('swipeleft', function (ev) {
if (Reveal.isLastSlide()){
window.location = "{% url "read_comic" nav.next_path %}"
} else {
Reveal.next()
}
})
hammertime.on('swiperight', function (ev) {
if (Reveal.isFirstSlide()){
window.location = "{% url "read_comic" nav.prev_path %}"
} else {
Reveal.prev();
}
})
hammertime.on('tap', function (ev) {
if (Reveal.isLastSlide()){
window.location = "{% url "read_comic" nav.next_path %}"
} else {
Reveal.next()
}
})
</script>
{% endblock %}

View File

@@ -1,4 +1,5 @@
from django.conf.urls import url
from django.urls import path
from . import feeds, views
@@ -9,7 +10,8 @@ urlpatterns = [
url(r"^settings/users/(?P<user_id>[0-9]+)/$", views.user_config_page, name="user_details"),
url(r"^settings/users/add/$", views.user_add_page, name="add_users"),
url(r"^account/$", views.account_page, name="account"),
url(r"^read/(?P<comic_selector>[\w-]+)/(?P<page>[0-9]+)/$", views.read_comic, name="read_comic"),
url(r"^read/(?P<comic_selector>[\w-]+)/$", views.read_comic, name="read_comic"),
url(r"^set_page/(?P<comic_selector>[\w-]+)/(?P<page>[0-9]+)/$", views.set_read_page, name="set_read_page"),
url(r"^read/(?P<comic_selector>[\w-]+)/(?P<page>[0-9]+)/img$", views.get_image, name="get_image"),
url(r"^list_json/$", views.comic_list_json, name="comic_list_json1"),
url(r"^list_json/(?P<directory_selector>[\w-]+)/$", views.comic_list_json, name="comic_list_json2"),

View File

@@ -112,7 +112,7 @@ class DirFile:
if created:
status.save()
self.selector = urlsafe_base64_encode(comic.selector.bytes)
self.location = "/comic/read/{0}/{1}/".format(self.selector, status.last_read_page)
self.location = "/comic/read/{0}/".format(self.selector)
self.label = generate_label(comic, status)
self.type = "book"

View File

@@ -140,9 +140,7 @@ def recent_comics_json(request):
"name": book.file_name,
"date": book.date_added.strftime("%d/%m/%y-%H:%M"),
"label": generate_label(book, status),
"url": "/comic/read/{0}/{1}/".format(
urlsafe_base64_encode(book.selector.bytes), status.last_read_page
),
"url": "/comic/read/{0}/".format(urlsafe_base64_encode(book.selector.bytes)),
}
)
return HttpResponse(json.dumps(response_data), content_type="application/json")
@@ -293,13 +291,31 @@ def settings_page(request):
@login_required
def read_comic(request, comic_selector, page):
def read_comic(request, comic_selector):
selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
book = get_object_or_404(ComicBook, selector=selector)
pages = ComicPage.objects.filter(Comic=book)
status, _ = ComicStatus.objects.get_or_create(comic=book, user=request.user)
title = "CBWebReader - " + book.file_name
context = {
"book": book,
"pages": pages,
# "orig_file_name": book.page_name(page),
"nav": book.nav(0, request.user),
"status": status,
"breadcrumbs": generate_breadcrumbs_from_path(book.directory, book),
"menu": Menu(request.user),
"title": title,
}
return render(request, "comic/read_comic.html", context)
@login_required
def set_read_page(request, comic_selector, page):
page = int(page)
selector = uuid.UUID(bytes=urlsafe_base64_decode(comic_selector))
book = get_object_or_404(ComicBook, selector=selector)
breadcrumbs = generate_breadcrumbs_from_path(book.directory, book)
status, _ = ComicStatus.objects.get_or_create(comic=book, user=request.user)
status.unread = False
status.last_read_page = page
@@ -308,16 +324,7 @@ def read_comic(request, comic_selector, page):
else:
status.finished = False
status.save()
title = "CBWebReader - " + book.file_name + " - Page: " + str(page)
context = {
"book": book,
"orig_file_name": book.page_name(page),
"nav": book.nav(page, request.user),
"breadcrumbs": breadcrumbs,
"menu": Menu(request.user),
"title": title,
}
return render(request, "comic/read_comic.html", context)
return HttpResponse(status=200)
@login_required