mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 18:54:09 -04:00
Store MathJax in the db
This commit is contained in:
parent
7501a3b0fd
commit
edb11dbd28
@ -13,6 +13,8 @@ def upgrade_schema(idb, old_version, new_version):
|
|||||||
idb.createObjectStore('books', {'keyPath':'key'})
|
idb.createObjectStore('books', {'keyPath':'key'})
|
||||||
if not idb.objectStoreNames.contains('files'):
|
if not idb.objectStoreNames.contains('files'):
|
||||||
idb.createObjectStore('files')
|
idb.createObjectStore('files')
|
||||||
|
if not idb.objectStoreNames.contains('mathjax'):
|
||||||
|
idb.createObjectStore('mathjax')
|
||||||
if not idb.objectStoreNames.contains('objects'):
|
if not idb.objectStoreNames.contains('objects'):
|
||||||
idb.createObjectStore('objects', {'keyPath':'key'})
|
idb.createObjectStore('objects', {'keyPath':'key'})
|
||||||
|
|
||||||
@ -27,7 +29,7 @@ def get_error_details(event):
|
|||||||
desc = desc.errorCode
|
desc = desc.errorCode
|
||||||
|
|
||||||
DB_NAME = 'calibre-books-db-testing' # TODO: Remove test suffix and change version back to 1
|
DB_NAME = 'calibre-books-db-testing' # TODO: Remove test suffix and change version back to 1
|
||||||
DB_VERSION = 1
|
DB_VERSION = 2
|
||||||
|
|
||||||
class DB:
|
class DB:
|
||||||
|
|
||||||
@ -96,6 +98,11 @@ class DB:
|
|||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_mathjax_info(self, proceed):
|
||||||
|
self.do_op(['objects'], 'mathjax-info', _('Failed to read from the objects database'), def(result):
|
||||||
|
proceed(result or {'key':'mathjax-info'})
|
||||||
|
)
|
||||||
|
|
||||||
def save_manifest(self, book, manifest, proceed):
|
def save_manifest(self, book, manifest, proceed):
|
||||||
book.manifest = manifest
|
book.manifest = manifest
|
||||||
book.metadata = manifest.metadata
|
book.metadata = manifest.metadata
|
||||||
@ -106,7 +113,7 @@ class DB:
|
|||||||
self.do_op(['books'], book, _('Failed to write to the books database'), proceed, op='put')
|
self.do_op(['books'], book, _('Failed to write to the books database'), proceed, op='put')
|
||||||
|
|
||||||
def store_file(self, book, name, xhr, proceed, is_cover):
|
def store_file(self, book, name, xhr, proceed, is_cover):
|
||||||
store_as_text = xhr.responseType is 'text'
|
store_as_text = xhr.responseType is 'text' or not xhr.responseType
|
||||||
fname = file_store_name(book, name)
|
fname = file_store_name(book, name)
|
||||||
needs_encoding = not store_as_text and not self.supports_blobs
|
needs_encoding = not store_as_text and not self.supports_blobs
|
||||||
book.stored_files[fname] = {'encoded':needs_encoding, 'mimetype':book.manifest.files[name].mimetype, 'store_as_text':store_as_text}
|
book.stored_files[fname] = {'encoded':needs_encoding, 'mimetype':book.manifest.files[name].mimetype, 'store_as_text':store_as_text}
|
||||||
@ -148,10 +155,22 @@ class DB:
|
|||||||
req.onerror = def(event):
|
req.onerror = def(event):
|
||||||
proceed(_('Failed to store book data ({0}) with error: {1}').format(name, get_error_details(event)))
|
proceed(_('Failed to store book data ({0}) with error: {1}').format(name, get_error_details(event)))
|
||||||
|
|
||||||
|
def store_mathjax_file(self, name, xhr, proceed):
|
||||||
|
data = xhr.response
|
||||||
|
if not self.supports_blobs:
|
||||||
|
data = base64encode(Uint8Array(data))
|
||||||
|
req = self.idb.transaction(['mathjax'], 'readwrite').objectStore('mathjax').put(data, name)
|
||||||
|
req.onsuccess = def(event): proceed()
|
||||||
|
req.onerror = def(event):
|
||||||
|
proceed(_('Failed to store mathjax file ({0}) with error: {1}').format(name, get_error_details(event)))
|
||||||
|
|
||||||
def finish_book(self, book, proceed):
|
def finish_book(self, book, proceed):
|
||||||
book.is_complete = True
|
book.is_complete = True
|
||||||
self.do_op(['books'], book, _('Failed to write to the books database'), proceed, op='put')
|
self.do_op(['books'], book, _('Failed to write to the books database'), proceed, op='put')
|
||||||
|
|
||||||
|
def finish_mathjax(self, mathjax_info, proceed):
|
||||||
|
self.do_op(['objects'], mathjax_info, _('Failed to write to the objects database'), proceed, op='put')
|
||||||
|
|
||||||
def update_last_read_time(self, book):
|
def update_last_read_time(self, book):
|
||||||
book.last_read = Date()
|
book.last_read = Date()
|
||||||
self.do_op(['books'], book, _('Failed to write to the books database'), op='put')
|
self.do_op(['books'], book, _('Failed to write to the books database'), op='put')
|
||||||
|
@ -141,7 +141,7 @@ class ReadUI:
|
|||||||
return
|
return
|
||||||
if end_type is not 'load':
|
if end_type is not 'load':
|
||||||
return self.show_error(_('Failed to load book manifest'),
|
return self.show_error(_('Failed to load book manifest'),
|
||||||
_('Could not open {title} as book manifest failed to load, click "Show Details" for more information.').format(title=self.current_metadata.title),
|
_('Could not open {title} as the book manifest failed to load, click "Show Details" for more information.').format(title=self.current_metadata.title),
|
||||||
xhr.error_html)
|
xhr.error_html)
|
||||||
try:
|
try:
|
||||||
manifest = JSON.parse(xhr.responseText)
|
manifest = JSON.parse(xhr.responseText)
|
||||||
@ -201,6 +201,11 @@ class ReadUI:
|
|||||||
pbar.setAttribute('value', x + '')
|
pbar.setAttribute('value', x + '')
|
||||||
progress.lastChild.textContent = _('Downloaded {0}, {1} left').format(human_readable(x), human_readable(total - x))
|
progress.lastChild.textContent = _('Downloaded {0}, {1} left').format(human_readable(x), human_readable(total - x))
|
||||||
|
|
||||||
|
def show_failure():
|
||||||
|
det = ['<h4>{}</h4><div>{}</div><hr>'.format(fname, err_html) for fname, err_html in failed_files].join('')
|
||||||
|
self.show_error(_('Could not download book'), _(
|
||||||
|
'Failed to download some book data, click "Show details" for more information'), det)
|
||||||
|
|
||||||
def on_stored(err):
|
def on_stored(err):
|
||||||
files_left.discard(this)
|
files_left.discard(this)
|
||||||
if err:
|
if err:
|
||||||
@ -208,10 +213,7 @@ class ReadUI:
|
|||||||
if len(files_left):
|
if len(files_left):
|
||||||
return
|
return
|
||||||
if failed_files.length:
|
if failed_files.length:
|
||||||
det = ['<h4>{}</h4><div>{}</div><hr>'.format(fname, err_html) for fname, err_html in failed_files].join('')
|
return show_failure()
|
||||||
self.show_error(_('Could not download book'), _(
|
|
||||||
'Failed to download some book data, click "Show details" for more information'), det)
|
|
||||||
return
|
|
||||||
self.db.finish_book(book, self.display_book.bind(self, book))
|
self.db.finish_book(book, self.display_book.bind(self, book))
|
||||||
|
|
||||||
def on_complete(end_type, xhr, ev):
|
def on_complete(end_type, xhr, ev):
|
||||||
@ -226,6 +228,8 @@ class ReadUI:
|
|||||||
else:
|
else:
|
||||||
failed_files.append([this, xhr.error_html])
|
failed_files.append([this, xhr.error_html])
|
||||||
files_left.discard(this)
|
files_left.discard(this)
|
||||||
|
if not len(files_left):
|
||||||
|
show_failure()
|
||||||
|
|
||||||
def on_progress(loaded, ftotal):
|
def on_progress(loaded, ftotal):
|
||||||
nonlocal total, cover_total_updated, raster_cover_size
|
nonlocal total, cover_total_updated, raster_cover_size
|
||||||
@ -252,6 +256,112 @@ class ReadUI:
|
|||||||
if fname is not raster_cover_name:
|
if fname is not raster_cover_name:
|
||||||
start_download(fname, base_path + encodeURIComponent(fname))
|
start_download(fname, base_path + encodeURIComponent(fname))
|
||||||
|
|
||||||
|
def ensure_maths(self, proceed):
|
||||||
|
self.db.get_mathjax_info(def(mathjax_info):
|
||||||
|
if mathjax_info.version is MATHJAX_VERSION:
|
||||||
|
return proceed()
|
||||||
|
print('Upgrading MathJax, previous version:', mathjax_info.version)
|
||||||
|
self.get_mathjax_manifest(mathjax_info, proceed)
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_mathjax_manifest(self, mathjax_info, proceed):
|
||||||
|
ajax('mathjax', def(end_type, xhr, event):
|
||||||
|
if end_type is 'abort':
|
||||||
|
return
|
||||||
|
if end_type is not 'load':
|
||||||
|
return self.show_error(_('Failed to load MathJax manifest'),
|
||||||
|
_('Could not open {title} as the MathJax manifest failed to load, click "Show Details" for more information.').format(title=self.current_metadata.title),
|
||||||
|
xhr.error_html)
|
||||||
|
try:
|
||||||
|
manifest = JSON.parse(xhr.responseText)
|
||||||
|
except Exception:
|
||||||
|
return self.show_error(_('Failed to load MathJax manifest'),
|
||||||
|
_('The MathJax manifest is not valid'), traceback.format_exc())
|
||||||
|
if manifest.etag is not MATHJAX_VERSION:
|
||||||
|
print('calibre upgraded: MATHJAX_VERSION={} manifest.etag={}'.format(MATHJAX_VERSION, manifest.etag))
|
||||||
|
return self.show_error(_('calibre upgraded!'), _(
|
||||||
|
'A newer version of calibre is available, please click the reload button in your browser.'))
|
||||||
|
mathjax_info.version = manifest.etag
|
||||||
|
mathjax_info.files = manifest.files
|
||||||
|
self.download_mathjax(mathjax_info, proceed)
|
||||||
|
).send()
|
||||||
|
|
||||||
|
def download_mathjax(self, mathjax_info, proceed):
|
||||||
|
files = mathjax_info.files
|
||||||
|
total = 0
|
||||||
|
progress_track = {}
|
||||||
|
files_left = set()
|
||||||
|
failed_files = []
|
||||||
|
for key in files:
|
||||||
|
total += files[key]
|
||||||
|
progress_track[key] = 0
|
||||||
|
files_left.add(key)
|
||||||
|
progress = document.getElementById(self.progress_id)
|
||||||
|
progress.firstChild.textContent = _(
|
||||||
|
'Downloading MathJax to render mathematics in this book...')
|
||||||
|
pbar = progress.firstChild.nextSibling
|
||||||
|
pbar.setAttribute('max', total + '')
|
||||||
|
for xhr in self.downloads_in_progress:
|
||||||
|
xhr.abort()
|
||||||
|
self.downloads_in_progress = []
|
||||||
|
|
||||||
|
def update_progress():
|
||||||
|
x = 0
|
||||||
|
for name in progress_track:
|
||||||
|
x += progress_track[name]
|
||||||
|
pbar.setAttribute('value', x + '')
|
||||||
|
progress.lastChild.textContent = _('Downloaded {0}, {1} left').format(human_readable(x), human_readable(total - x))
|
||||||
|
|
||||||
|
def on_progress(loaded, ftotal):
|
||||||
|
progress_track[this] = loaded
|
||||||
|
update_progress()
|
||||||
|
|
||||||
|
def show_failure():
|
||||||
|
det = ['<h4>{}</h4><div>{}</div><hr>'.format(fname, err_html) for fname, err_html in failed_files].join('')
|
||||||
|
self.show_error(_('Could not download MathJax'), _(
|
||||||
|
'Failed to download some MathJax data, click "Show details" for more information'), det)
|
||||||
|
|
||||||
|
def on_complete(end_type, xhr, ev):
|
||||||
|
self.downloads_in_progress.remove(xhr)
|
||||||
|
progress_track[this] = files[this]
|
||||||
|
update_progress()
|
||||||
|
if end_type is 'abort':
|
||||||
|
files_left.discard(this)
|
||||||
|
return
|
||||||
|
if end_type is 'load':
|
||||||
|
self.db.store_mathjax_file(this, xhr, on_stored.bind(this))
|
||||||
|
else:
|
||||||
|
failed_files.append([this, xhr.error_html])
|
||||||
|
files_left.discard(this)
|
||||||
|
if not len(files_left):
|
||||||
|
show_failure()
|
||||||
|
|
||||||
|
def on_stored(err):
|
||||||
|
files_left.discard(this)
|
||||||
|
if err:
|
||||||
|
failed_files.append([this, err])
|
||||||
|
if len(files_left):
|
||||||
|
return
|
||||||
|
if failed_files.length:
|
||||||
|
return show_failure()
|
||||||
|
self.db.finish_mathjax(mathjax_info, proceed)
|
||||||
|
|
||||||
|
def start_download(name):
|
||||||
|
path = 'mathjax/' + name
|
||||||
|
xhr = ajax(path, on_complete.bind(name), on_progress=on_progress.bind(name), progress_totals_needed=False)
|
||||||
|
xhr.responseType = 'blob' if self.db.supports_blobs else 'arraybuffer'
|
||||||
|
xhr.send()
|
||||||
|
self.downloads_in_progress.push(xhr)
|
||||||
|
|
||||||
|
for fname in files_left:
|
||||||
|
start_download(fname)
|
||||||
|
|
||||||
def display_book(self, book):
|
def display_book(self, book):
|
||||||
|
if book.manifest.has_maths:
|
||||||
|
self.ensure_maths(self.display_book_stage2.bind(self, book))
|
||||||
|
else:
|
||||||
|
self.display_book_stage2(book)
|
||||||
|
|
||||||
|
def display_book_stage2(self, book):
|
||||||
self.show_stack(self.display_id)
|
self.show_stack(self.display_id)
|
||||||
self.view.display_book(book)
|
self.view.display_book(book)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user