diff --git a/resources/content-server/index.html b/resources/content-server/index.html index 93c1afedee..ae000a82db 100644 --- a/resources/content-server/index.html +++ b/resources/content-server/index.html @@ -2,9 +2,24 @@ calibre - - + + + + +
+ + +
Loading library, please wait…
+ +
diff --git a/resources/content-server/reset.css b/resources/content-server/reset.css new file mode 100644 index 0000000000..fb58a32847 --- /dev/null +++ b/resources/content-server/reset.css @@ -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; +} diff --git a/src/calibre/srv/ajax.py b/src/calibre/srv/ajax.py index 48db766edf..638765b5b5 100644 --- a/src/calibre/srv/ajax.py +++ b/src/calibre/srv/ajax.py @@ -580,7 +580,6 @@ def interface_data(ctx, rd, library_id): num = int(rd.query.get('num', 75)) except Exception: raise HTTPNotFound('Invalid number of books: %r' % rd.query.get('num')) - last_modified = None db = get_db(ctx, library_id) with db.safe_read_lock: 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) mdata = ans['metadata'] = {} for book_id in ans['search_result']['book_ids']: - data, lm = book_to_json(ctx, rd, db, book_id) - last_modified = lm if last_modified is None else max(lm, last_modified) + data, last_modified = book_to_json(ctx, rd, db, book_id) mdata[book_id] = data - if last_modified is not None: - rd.outheaders['Last-Modified'] = http_date(timestampfromdt(last_modified)) return ans diff --git a/src/calibre/srv/code.py b/src/calibre/srv/code.py index df7aadfe4c..2af99df41f 100644 --- a/src/calibre/srv/code.py +++ b/src/calibre/srv/code.py @@ -4,21 +4,9 @@ from __future__ import (unicode_literals, division, absolute_import, print_function) -import errno -from calibre import sanitize_file_name2 -from calibre.srv.errors import HTTPNotFound from calibre.srv.routes import endpoint @endpoint('', auth_required=False) def index(ctx, rd): 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 diff --git a/src/pyj/ajax.pyj b/src/pyj/ajax.pyj index c9610e98b3..16f054c9da 100644 --- a/src/pyj/ajax.pyj +++ b/src/pyj/ajax.pyj @@ -1,14 +1,36 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2015, Kovid Goyal -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() if bypass_cache: 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: - xhr.addEventListener('progress', on_progress) - xhr.addEventListener('abort', def(ev): on_complete('abort', this, xhr);) - xhr.addEventListener('error', def(ev): on_complete('error', this, xhr);) - xhr.addEventListener('load', def(ev): on_complete('load', this, xhr);) + xhr.addEventListener('progress', progress_callback) + xhr.addEventListener('abort', def(ev): complete_callback('abort', xhr, ev);) + xhr.addEventListener('error', def(ev): complete_callback('error', xhr, ev);) + xhr.addEventListener('load', def(ev): complete_callback('load', xhr, ev);) + xhr.open(method, path) return xhr diff --git a/src/pyj/srv.pyj b/src/pyj/srv.pyj index b5063d64bd..e64be635f4 100644 --- a/src/pyj/srv.pyj +++ b/src/pyj/srv.pyj @@ -1,13 +1,28 @@ # vim:fileencoding=utf-8 # License: GPL v3 Copyright: 2015, Kovid Goyal +from ajax import ajax from elementmaker import E +from gettext import gettext as _ -def create_page_load_progress_bar(): - E.progress(id='library_load_bar') +def on_library_loaded(end_type, xhr, ev): + 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(): - 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 # with a largely empty starting document, we can use this to preload any resources