mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 10:44:09 -04:00
Implement progress bar while loading library data
This commit is contained in:
parent
ba95bf86b9
commit
d2ba80ec41
@ -2,9 +2,24 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<title>calibre</title>
|
<title>calibre</title>
|
||||||
<meta http-equiv="content-type" content="text/html; charset=utf-8"/>
|
<meta charset="utf-8"/>
|
||||||
<script type="text/javascript" src="js/main.js"></script>
|
<script>window.interface_data_url = 'ajax/interface-data';</script>
|
||||||
|
<script type="text/javascript" src="static/main.js"></script>
|
||||||
|
<link rel="stylesheet" href="static/reset.css"></link>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<div id="page_load_progress">
|
||||||
|
<progress>
|
||||||
|
</progress>
|
||||||
|
<div>Loading library, please wait…<div>
|
||||||
|
<style type="text/css">
|
||||||
|
#page_load_progress {
|
||||||
|
position:relative;
|
||||||
|
top: 50px;
|
||||||
|
margin-left: auto; margin-right: auto;
|
||||||
|
text-align: center;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
74
resources/content-server/reset.css
Normal file
74
resources/content-server/reset.css
Normal file
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Reset CSS to suppress cross-browser differences
|
||||||
|
*/
|
||||||
|
|
||||||
|
html, body, div, span, object, iframe,
|
||||||
|
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
|
||||||
|
abbr, address, cite, code,
|
||||||
|
del, dfn, em, img, ins, kbd, q, samp,
|
||||||
|
small, strong, sub, sup, var,
|
||||||
|
b, i,
|
||||||
|
dl, dt, dd, ol, ul, li,
|
||||||
|
fieldset, form, label, legend,
|
||||||
|
table, caption, tbody, tfoot, thead, tr, th, td,
|
||||||
|
article, aside, canvas, details, figcaption, figure,
|
||||||
|
footer, header, hgroup, menu, nav, section, summary,
|
||||||
|
time, mark, audio, video {
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
border:0;
|
||||||
|
outline:0;
|
||||||
|
font-size:100%;
|
||||||
|
vertical-align:baseline;
|
||||||
|
background:transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
line-height:1;
|
||||||
|
font-family: sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
article,aside,details,figcaption,figure,
|
||||||
|
footer,header,hgroup,menu,nav,section {
|
||||||
|
display:block;
|
||||||
|
}
|
||||||
|
|
||||||
|
nav ul {
|
||||||
|
list-style:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote, q {
|
||||||
|
quotes:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
blockquote:before, blockquote:after,
|
||||||
|
q:before, q:after {
|
||||||
|
content:'';
|
||||||
|
content:none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
margin:0;
|
||||||
|
padding:0;
|
||||||
|
font-size:100%;
|
||||||
|
vertical-align:baseline;
|
||||||
|
background:transparent;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse:collapse;
|
||||||
|
border-spacing:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
display:block;
|
||||||
|
height:1px;
|
||||||
|
border:0;
|
||||||
|
border-top:1px solid currentColor;
|
||||||
|
margin:1em 0;
|
||||||
|
padding:0;
|
||||||
|
}
|
||||||
|
|
||||||
|
input, select {
|
||||||
|
vertical-align:middle;
|
||||||
|
}
|
@ -580,7 +580,6 @@ def interface_data(ctx, rd, library_id):
|
|||||||
num = int(rd.query.get('num', 75))
|
num = int(rd.query.get('num', 75))
|
||||||
except Exception:
|
except Exception:
|
||||||
raise HTTPNotFound('Invalid number of books: %r' % rd.query.get('num'))
|
raise HTTPNotFound('Invalid number of books: %r' % rd.query.get('num'))
|
||||||
last_modified = None
|
|
||||||
db = get_db(ctx, library_id)
|
db = get_db(ctx, library_id)
|
||||||
with db.safe_read_lock:
|
with db.safe_read_lock:
|
||||||
ans['search_result'] = _search(ctx, rd, db, '', num, 0, ','.join(sorts), ','.join(orders))
|
ans['search_result'] = _search(ctx, rd, db, '', num, 0, ','.join(sorts), ','.join(orders))
|
||||||
@ -588,10 +587,7 @@ def interface_data(ctx, rd, library_id):
|
|||||||
# ans['categories'] = ctx.get_categories(rd, db)
|
# ans['categories'] = ctx.get_categories(rd, db)
|
||||||
mdata = ans['metadata'] = {}
|
mdata = ans['metadata'] = {}
|
||||||
for book_id in ans['search_result']['book_ids']:
|
for book_id in ans['search_result']['book_ids']:
|
||||||
data, lm = book_to_json(ctx, rd, db, book_id)
|
data, last_modified = book_to_json(ctx, rd, db, book_id)
|
||||||
last_modified = lm if last_modified is None else max(lm, last_modified)
|
|
||||||
mdata[book_id] = data
|
mdata[book_id] = data
|
||||||
|
|
||||||
if last_modified is not None:
|
|
||||||
rd.outheaders['Last-Modified'] = http_date(timestampfromdt(last_modified))
|
|
||||||
return ans
|
return ans
|
||||||
|
@ -4,21 +4,9 @@
|
|||||||
|
|
||||||
from __future__ import (unicode_literals, division, absolute_import,
|
from __future__ import (unicode_literals, division, absolute_import,
|
||||||
print_function)
|
print_function)
|
||||||
import errno
|
|
||||||
|
|
||||||
from calibre import sanitize_file_name2
|
|
||||||
from calibre.srv.errors import HTTPNotFound
|
|
||||||
from calibre.srv.routes import endpoint
|
from calibre.srv.routes import endpoint
|
||||||
|
|
||||||
@endpoint('', auth_required=False)
|
@endpoint('', auth_required=False)
|
||||||
def index(ctx, rd):
|
def index(ctx, rd):
|
||||||
return lopen(P('content-server/index.html'), 'rb')
|
return lopen(P('content-server/index.html'), 'rb')
|
||||||
|
|
||||||
@endpoint('/js/{which}', auth_required=False)
|
|
||||||
def js(ctx, rd, which):
|
|
||||||
try:
|
|
||||||
return lopen(P('content-server/' + sanitize_file_name2(which)), 'rb')
|
|
||||||
except EnvironmentError as e:
|
|
||||||
if e.errno == errno.ENOENT:
|
|
||||||
raise HTTPNotFound('No js with name: %r' % which)
|
|
||||||
raise
|
|
||||||
|
@ -1,14 +1,36 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
def ajax(path, on_complete, on_progress=None, bypass_cache=True):
|
def ajax(path, on_complete, on_progress=None, bypass_cache=True, method='GET'):
|
||||||
xhr = XMLHttpRequest()
|
xhr = XMLHttpRequest()
|
||||||
if bypass_cache:
|
if bypass_cache:
|
||||||
path += ('&' if '?' in path else '?') + Date().getTime()
|
path += ('&' if '?' in path else '?') + Date().getTime()
|
||||||
|
|
||||||
|
def progress_callback(ev):
|
||||||
|
if ev.lengthComputable:
|
||||||
|
on_progress(ev.loaded, ev.total, xhr)
|
||||||
|
elif ev.loaded:
|
||||||
|
ul = xhr.getResponseHeader('Calibre-Uncompressed-Length')
|
||||||
|
if ul:
|
||||||
|
try:
|
||||||
|
ul = int(ul)
|
||||||
|
except Exception:
|
||||||
|
return
|
||||||
|
on_progress(ev.loaded, ul)
|
||||||
|
|
||||||
|
def complete_callback(end_type, ev):
|
||||||
|
if end_type != 'load':
|
||||||
|
on_complete(end_type, xhr, ev)
|
||||||
|
return
|
||||||
|
if not (200 <= xhr.status < 300):
|
||||||
|
end_type = 'error'
|
||||||
|
on_complete(end_type, xhr, ev)
|
||||||
|
|
||||||
if on_progress:
|
if on_progress:
|
||||||
xhr.addEventListener('progress', on_progress)
|
xhr.addEventListener('progress', progress_callback)
|
||||||
xhr.addEventListener('abort', def(ev): on_complete('abort', this, xhr);)
|
xhr.addEventListener('abort', def(ev): complete_callback('abort', xhr, ev);)
|
||||||
xhr.addEventListener('error', def(ev): on_complete('error', this, xhr);)
|
xhr.addEventListener('error', def(ev): complete_callback('error', xhr, ev);)
|
||||||
xhr.addEventListener('load', def(ev): on_complete('load', this, xhr);)
|
xhr.addEventListener('load', def(ev): complete_callback('load', xhr, ev);)
|
||||||
|
xhr.open(method, path)
|
||||||
return xhr
|
return xhr
|
||||||
|
|
||||||
|
@ -1,13 +1,28 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2015, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
|
|
||||||
|
from ajax import ajax
|
||||||
from elementmaker import E
|
from elementmaker import E
|
||||||
|
from gettext import gettext as _
|
||||||
|
|
||||||
def create_page_load_progress_bar():
|
def on_library_loaded(end_type, xhr, ev):
|
||||||
E.progress(id='library_load_bar')
|
p = document.getElementById('page_load_progress')
|
||||||
|
p.parentNode.removeChild(p)
|
||||||
|
if end_type == 'load':
|
||||||
|
data = xhr.response
|
||||||
|
data
|
||||||
|
else:
|
||||||
|
document.body.appendChild(E.p(style="color:red", _(
|
||||||
|
'Failed to download library data, with status:') + str.format(' [{}] {}', xhr.status, xhr.statusText)
|
||||||
|
))
|
||||||
|
|
||||||
|
def on_library_load_progress(loaded, total):
|
||||||
|
p = document.querySelector('#page_load_progress > progress')
|
||||||
|
p.max = total
|
||||||
|
p.value = loaded
|
||||||
|
|
||||||
def on_document_loaded():
|
def on_document_loaded():
|
||||||
alert(11111111)
|
ajax(window.interface_data_url, on_library_loaded, on_library_load_progress).send()
|
||||||
|
|
||||||
# We wait for all page elements to load, since this is a single page app
|
# We wait for all page elements to load, since this is a single page app
|
||||||
# with a largely empty starting document, we can use this to preload any resources
|
# with a largely empty starting document, we can use this to preload any resources
|
||||||
|
Loading…
x
Reference in New Issue
Block a user