mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Load the db early during initialization
This commit is contained in:
parent
b99e261260
commit
09717b15c4
@ -21,3 +21,15 @@ def get_current_query(newval):
|
|||||||
if newval:
|
if newval:
|
||||||
get_current_query.ans = newval
|
get_current_query.ans = newval
|
||||||
return get_current_query.ans
|
return get_current_query.ans
|
||||||
|
|
||||||
|
|
||||||
|
def get_db(db):
|
||||||
|
if db:
|
||||||
|
get_db.db = db
|
||||||
|
return get_db.db
|
||||||
|
|
||||||
|
|
||||||
|
def get_translations(val):
|
||||||
|
if val:
|
||||||
|
get_translations.ans = val
|
||||||
|
return get_translations.ans
|
||||||
|
@ -14,8 +14,10 @@ from utils import parse_url_params
|
|||||||
|
|
||||||
from book_list.constants import book_list_container_id, read_book_container_id
|
from book_list.constants import book_list_container_id, read_book_container_id
|
||||||
from book_list.theme import get_color
|
from book_list.theme import get_color
|
||||||
from book_list.router import update_window_title, set_default_mode_handler, apply_url
|
from book_list.router import update_window_title, set_default_mode_handler, apply_url, set_mode_handler
|
||||||
|
from book_list.globals import get_db, set_session_data
|
||||||
from book_list.ui import apply_url_state as book_list_mode_handler
|
from book_list.ui import apply_url_state as book_list_mode_handler
|
||||||
|
from read_book.ui import ReadUI
|
||||||
|
|
||||||
# Register the various panels
|
# Register the various panels
|
||||||
import book_list.home # noqa: unused-import
|
import book_list.home # noqa: unused-import
|
||||||
@ -39,13 +41,17 @@ def onerror(msg, script_url, line_number, column_number, error_object):
|
|||||||
except:
|
except:
|
||||||
console.log('There was an error in the unhandled exception handler')
|
console.log('There was an error in the unhandled exception handler')
|
||||||
|
|
||||||
|
read_ui = None
|
||||||
|
|
||||||
def init_ui():
|
def init_ui():
|
||||||
|
nonlocal read_ui
|
||||||
install_event_filters()
|
install_event_filters()
|
||||||
set_default_mode_handler(book_list_mode_handler)
|
set_default_mode_handler(book_list_mode_handler)
|
||||||
window.onerror = onerror
|
window.onerror = onerror
|
||||||
translations = get_translations()
|
translations = get_translations()
|
||||||
if translations:
|
if translations:
|
||||||
install(translations)
|
install(translations)
|
||||||
|
get_translations(translations)
|
||||||
remove_initial_progress_bar()
|
remove_initial_progress_bar()
|
||||||
document.head.appendChild(E.style(get_widget_css()))
|
document.head.appendChild(E.style(get_widget_css()))
|
||||||
set_css(document.body, background_color=get_color('window-background'), color=get_color('window-foreground'))
|
set_css(document.body, background_color=get_color('window-background'), color=get_color('window-foreground'))
|
||||||
@ -54,6 +60,9 @@ def init_ui():
|
|||||||
document.body.lastChild.appendChild(E.div(id=read_book_container_id, style='display: none'))
|
document.body.lastChild.appendChild(E.div(id=read_book_container_id, style='display: none'))
|
||||||
create_modal_container()
|
create_modal_container()
|
||||||
update_window_title()
|
update_window_title()
|
||||||
|
read_ui = ReadUI()
|
||||||
|
get_db(read_ui.db)
|
||||||
|
set_mode_handler('read_book', read_ui.apply_url_state.bind(read_ui))
|
||||||
apply_url()
|
apply_url()
|
||||||
|
|
||||||
def on_data_loaded(end_type, xhr, ev):
|
def on_data_loaded(end_type, xhr, ev):
|
||||||
@ -61,6 +70,9 @@ def on_data_loaded(end_type, xhr, ev):
|
|||||||
if end_type is 'load':
|
if end_type is 'load':
|
||||||
data = JSON.parse(xhr.responseText)
|
data = JSON.parse(xhr.responseText)
|
||||||
update_interface_data(data)
|
update_interface_data(data)
|
||||||
|
interface_data = get_interface_data()
|
||||||
|
sd = UserSessionData(interface_data.username, interface_data.user_session_data)
|
||||||
|
set_session_data(sd)
|
||||||
if data.translations:
|
if data.translations:
|
||||||
get_translations(data.translations)
|
get_translations(data.translations)
|
||||||
init_ui()
|
init_ui()
|
||||||
@ -94,4 +106,7 @@ def main():
|
|||||||
if get_interface_data().is_default:
|
if get_interface_data().is_default:
|
||||||
load_interface_data()
|
load_interface_data()
|
||||||
else:
|
else:
|
||||||
|
interface_data = get_interface_data()
|
||||||
|
sd = UserSessionData(interface_data.username, interface_data.user_session_data)
|
||||||
|
set_session_data(sd)
|
||||||
init_ui()
|
init_ui()
|
||||||
|
@ -8,6 +8,7 @@ from utils import parse_url_params
|
|||||||
|
|
||||||
mode_handlers = {}
|
mode_handlers = {}
|
||||||
default_mode_handler = None
|
default_mode_handler = None
|
||||||
|
read_book_mode = 'read_book'
|
||||||
|
|
||||||
|
|
||||||
def set_mode_handler(mode, handler):
|
def set_mode_handler(mode, handler):
|
||||||
@ -24,8 +25,13 @@ def update_window_title(subtitle, title='calibre', sep=' :: '):
|
|||||||
document.title = title + extra
|
document.title = title + extra
|
||||||
|
|
||||||
|
|
||||||
|
def is_reading_book():
|
||||||
|
cq = get_current_query
|
||||||
|
return cq and cq.mode is read_book_mode
|
||||||
|
|
||||||
|
|
||||||
def apply_mode(mode):
|
def apply_mode(mode):
|
||||||
divid = read_book_container_id if (mode or get_current_query().mode) is 'read_book' else book_list_container_id
|
divid = read_book_container_id if is_reading_book() else book_list_container_id
|
||||||
for div in document.getElementById(divid).parentNode.childNodes:
|
for div in document.getElementById(divid).parentNode.childNodes:
|
||||||
div.style.display = 'block' if div.id is divid else 'none'
|
div.style.display = 'block' if div.id is divid else 'none'
|
||||||
|
|
||||||
@ -37,3 +43,10 @@ def apply_url():
|
|||||||
apply_mode()
|
apply_mode()
|
||||||
handler = mode_handlers[data.mode] or default_mode_handler
|
handler = mode_handlers[data.mode] or default_mode_handler
|
||||||
handler(data)
|
handler(data)
|
||||||
|
|
||||||
|
|
||||||
|
def push_state(query, replace=False, mode='book_list'):
|
||||||
|
query = {k:query[k] for k in query}
|
||||||
|
if mode is not 'book_list':
|
||||||
|
query.mode = mode
|
||||||
|
# TODO: Implement this (see push_state in boos.pyj)
|
||||||
|
@ -1,9 +1,12 @@
|
|||||||
# vim:fileencoding=utf-8
|
# vim:fileencoding=utf-8
|
||||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||||
from __python__ import hash_literals
|
from __python__ import hash_literals, bound_methods
|
||||||
|
|
||||||
from gettext import gettext as _
|
from gettext import gettext as _
|
||||||
from encodings import base64encode, base64decode
|
from encodings import base64encode, base64decode
|
||||||
|
from modals import error_dialog
|
||||||
|
|
||||||
|
from book_list.router import is_reading_book
|
||||||
|
|
||||||
def upgrade_schema(idb, old_version, new_version):
|
def upgrade_schema(idb, old_version, new_version):
|
||||||
print('upgrade_schema:', old_version, new_version)
|
print('upgrade_schema:', old_version, new_version)
|
||||||
@ -31,13 +34,59 @@ DB_VERSION = 2
|
|||||||
|
|
||||||
class DB:
|
class DB:
|
||||||
|
|
||||||
def __init__(self, idb, ui, supports_blobs):
|
def __init__(self, callback, show_read_book_error):
|
||||||
self.interface_data = ui.interface_data
|
self.initialized = False
|
||||||
|
self.initialize_error_msg = None
|
||||||
|
self.callback = callback
|
||||||
|
self.show_read_book_error = show_read_book_error
|
||||||
|
self.initialize_stage1()
|
||||||
|
|
||||||
|
def show_error(self, title, msg, det_msg):
|
||||||
|
if is_reading_book():
|
||||||
|
self.show_read_book_error(title, msg, det_msg)
|
||||||
|
else:
|
||||||
|
error_dialog(title, msg, det_msg)
|
||||||
|
|
||||||
|
def initialize_stage1(self):
|
||||||
|
if not window.indexedDB:
|
||||||
|
self.initialize_error_msg = _('Your browser does not support IndexedDB. Cannot read books. Consider using a modern browser, such as Firefox, Chrome or Edge.')
|
||||||
|
self.initialized = True
|
||||||
|
self.callback()
|
||||||
|
return
|
||||||
|
|
||||||
|
request = window.indexedDB.open(DB_NAME, DB_VERSION)
|
||||||
|
|
||||||
|
request.onupgradeneeded = def(event):
|
||||||
|
upgrade_schema(event.target.result, event.oldVersion, event.newVersion)
|
||||||
|
|
||||||
|
request.onblocked = def(event):
|
||||||
|
self.initialize_error_msg = _('Please close all other browser tabs with calibre open')
|
||||||
|
self.initialized = True
|
||||||
|
self.callback()
|
||||||
|
|
||||||
|
request.onerror = def(event):
|
||||||
|
self.initialize_error_msg = _('You must allow calibre to use IndexedDB storage in your browser to read books')
|
||||||
|
self.initialized = True
|
||||||
|
self.callback()
|
||||||
|
|
||||||
|
request.onsuccess = def(event):
|
||||||
|
blob = Blob(['test'], {'type':"text/plain"})
|
||||||
|
idb = event.target.result
|
||||||
|
try:
|
||||||
|
req = idb.transaction(['files'], 'readwrite').objectStore('files').put(blob, ':-test-blob-:')
|
||||||
|
except Exception:
|
||||||
|
self.initialize_stage2(idb, False)
|
||||||
|
req.onsuccess = def(event):
|
||||||
|
self.initialize_stage2(idb, True)
|
||||||
|
req.onerror = def(event):
|
||||||
|
self.initialize_stage2(idb, False)
|
||||||
|
|
||||||
|
def initialize_stage2(self, idb, supports_blobs):
|
||||||
self.idb = idb
|
self.idb = idb
|
||||||
self.supports_blobs = supports_blobs
|
self.supports_blobs = supports_blobs
|
||||||
|
self.initialized = True
|
||||||
if not supports_blobs:
|
if not supports_blobs:
|
||||||
print('IndexedDB does not support Blob storage, using base64 encoding instead')
|
print('WARNING: browser does not support blob storage, calibre falling back to base64 encoding')
|
||||||
self.show_error = ui.show_error.bind(ui)
|
|
||||||
|
|
||||||
idb.onerror = def(event):
|
idb.onerror = def(event):
|
||||||
self.display_error(None, event)
|
self.display_error(None, event)
|
||||||
@ -48,8 +97,9 @@ class DB:
|
|||||||
|
|
||||||
idb.onversionchange = def(event):
|
idb.onversionchange = def(event):
|
||||||
idb.close()
|
idb.close()
|
||||||
ui.show_error(_('Database upgraded!'), _(
|
self.show_error(_('Database upgraded!'), _(
|
||||||
'A newer version of calibre is available, please click the reload button in your browser.'))
|
'A newer version of calibre is available, please click the reload button in your browser.'))
|
||||||
|
self.callback()
|
||||||
|
|
||||||
def display_error(self, msg, event):
|
def display_error(self, msg, event):
|
||||||
if event.already_displayed_by_calibre:
|
if event.already_displayed_by_calibre:
|
||||||
@ -225,31 +275,8 @@ class DB:
|
|||||||
books.delete(book.key)
|
books.delete(book.key)
|
||||||
next_step()
|
next_step()
|
||||||
|
|
||||||
def create_db(ui, interface_data):
|
|
||||||
if not window.indexedDB:
|
|
||||||
return ui.db_initialized(_('Your browser does not support IndexedDB. Cannot read books. Consider using a modern browser, such as Firefox, Chrome or Edge.'))
|
|
||||||
|
|
||||||
request = window.indexedDB.open(DB_NAME, DB_VERSION)
|
def get_db(callback, show_read_book_error):
|
||||||
|
if not get_db.ans:
|
||||||
request.onupgradeneeded = def(event):
|
get_db.ans = DB(callback)
|
||||||
upgrade_schema(event.target.result, event.oldVersion, event.newVersion)
|
return get_db.ans
|
||||||
|
|
||||||
request.onblocked = def(event):
|
|
||||||
alert(_('Please close all other tabs with a calibre book open'))
|
|
||||||
|
|
||||||
request.onerror = def(event):
|
|
||||||
ui.db_initialized(_('You must allow calibre to use IndexedDB storage in your browser to read books'))
|
|
||||||
|
|
||||||
request.onsuccess = def(event):
|
|
||||||
blob = Blob(['test'], {'type':"text/plain"})
|
|
||||||
idb = event.target.result
|
|
||||||
try:
|
|
||||||
req = idb.transaction(['files'], 'readwrite').objectStore('files').put(blob, ':-test-blob-:')
|
|
||||||
except Exception:
|
|
||||||
print('WARNING: browser does not support blob storage, calibre falling back to base64 encoding')
|
|
||||||
return ui.db_initialized(DB(idb, ui, False))
|
|
||||||
req.onsuccess = def(event):
|
|
||||||
ui.db_initialized(DB(idb, ui, True))
|
|
||||||
req.onerror = def(event):
|
|
||||||
print('WARNING: browser does not support blob storage, calibre falling back to base64 encoding')
|
|
||||||
ui.db_initialized(DB(idb, ui, False))
|
|
||||||
|
@ -10,8 +10,9 @@ from gettext import gettext as _
|
|||||||
from modals import error_dialog
|
from modals import error_dialog
|
||||||
from utils import human_readable, debounce
|
from utils import human_readable, debounce
|
||||||
|
|
||||||
|
from book_list.constants import read_book_container_id
|
||||||
|
from read_book.db import get_db
|
||||||
from book_list.router import update_window_title
|
from book_list.router import update_window_title
|
||||||
from read_book.db import create_db
|
|
||||||
from read_book.view import View
|
from read_book.view import View
|
||||||
|
|
||||||
RENDER_VERSION = __RENDER_VERSION__
|
RENDER_VERSION = __RENDER_VERSION__
|
||||||
@ -19,19 +20,17 @@ MATHJAX_VERSION = "__MATHJAX_VERSION__"
|
|||||||
|
|
||||||
class ReadUI:
|
class ReadUI:
|
||||||
|
|
||||||
def __init__(self, interface_data, container):
|
def __init__(self):
|
||||||
self.interface_data = interface_data
|
|
||||||
self.db = None
|
|
||||||
self.current_metadata = {'title': _('Unknown book')}
|
self.current_metadata = {'title': _('Unknown book')}
|
||||||
self.current_book_id = None
|
self.current_book_id = None
|
||||||
self.manifest_xhr = None
|
self.manifest_xhr = None
|
||||||
create_db(self, interface_data)
|
|
||||||
self.pending_load = None
|
self.pending_load = None
|
||||||
self.downloads_in_progress = []
|
self.downloads_in_progress = []
|
||||||
self.progress_id = 'book-load-progress'
|
self.progress_id = 'book-load-progress'
|
||||||
self.display_id = 'book-iframe-container'
|
self.display_id = 'book-iframe-container'
|
||||||
self.error_id = 'book-global-error-container'
|
self.error_id = 'book-global-error-container'
|
||||||
self.stacked_widgets = [self.progress_id, self.display_id, self.error_id]
|
self.stacked_widgets = [self.progress_id, self.display_id, self.error_id]
|
||||||
|
container = document.getElementById(read_book_container_id)
|
||||||
|
|
||||||
container.appendChild(E.div(
|
container.appendChild(E.div(
|
||||||
id=self.progress_id, style='display:none; text-align: center',
|
id=self.progress_id, style='display:none; text-align: center',
|
||||||
@ -51,6 +50,7 @@ class ReadUI:
|
|||||||
))
|
))
|
||||||
self.view = View(container.lastChild, self)
|
self.view = View(container.lastChild, self)
|
||||||
window.addEventListener('resize', debounce(self.on_resize.bind(self), 250))
|
window.addEventListener('resize', debounce(self.on_resize.bind(self), 250))
|
||||||
|
self.db = get_db(self.db_initialized.bind(self), self.show_error.bind(self))
|
||||||
|
|
||||||
def on_resize(self):
|
def on_resize(self):
|
||||||
self.view.on_resize()
|
self.view.on_resize()
|
||||||
@ -99,7 +99,7 @@ class ReadUI:
|
|||||||
|
|
||||||
def load_book(self, book_id, fmt, metadata, force_reload):
|
def load_book(self, book_id, fmt, metadata, force_reload):
|
||||||
self.base_url_data = {'book_id':book_id, 'fmt':fmt}
|
self.base_url_data = {'book_id':book_id, 'fmt':fmt}
|
||||||
if self.db is None:
|
if not self.db.initialized:
|
||||||
self.pending_load = [book_id, fmt, metadata, force_reload]
|
self.pending_load = [book_id, fmt, metadata, force_reload]
|
||||||
return
|
return
|
||||||
self.start_load(book_id, fmt, metadata, force_reload)
|
self.start_load(book_id, fmt, metadata, force_reload)
|
||||||
@ -126,11 +126,13 @@ class ReadUI:
|
|||||||
ans.bookpos = bookpos
|
ans.bookpos = bookpos
|
||||||
return ans
|
return ans
|
||||||
|
|
||||||
def db_initialized(self, db):
|
def db_initialized(self):
|
||||||
self.db = db
|
|
||||||
if self.pending_load is not None:
|
if self.pending_load is not None:
|
||||||
pl, self.pending_load = self.pending_load, None
|
pl, self.pending_load = self.pending_load, None
|
||||||
self.start_load(*pl)
|
if self.db.initialize_error_msg:
|
||||||
|
self.show_error(_('Failed to initialize IndexedDB'), self.db.initialize_error_msg)
|
||||||
|
else:
|
||||||
|
self.start_load(*pl)
|
||||||
|
|
||||||
def start_load(self, book_id, fmt, metadata, force_reload):
|
def start_load(self, book_id, fmt, metadata, force_reload):
|
||||||
self.current_book_id = book_id
|
self.current_book_id = book_id
|
||||||
@ -402,3 +404,6 @@ class ReadUI:
|
|||||||
def display_book_stage2(self, 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)
|
||||||
|
|
||||||
|
def apply_url_state(self, current_query):
|
||||||
|
pass
|
||||||
|
@ -8,7 +8,8 @@ from gettext import gettext as _
|
|||||||
from utils import html_escape
|
from utils import html_escape
|
||||||
|
|
||||||
from modals import error_dialog, warning_dialog
|
from modals import error_dialog, warning_dialog
|
||||||
from book_list.globals import get_session_data, get_boss, main_js
|
from book_list.globals import get_session_data, main_js, get_translations
|
||||||
|
from book_list.router import push_state, read_book_mode
|
||||||
from read_book.globals import messenger, iframe_id, current_book, set_current_spine_item
|
from read_book.globals import messenger, iframe_id, current_book, set_current_spine_item
|
||||||
from read_book.resources import load_resources
|
from read_book.resources import load_resources
|
||||||
from read_book.overlay import Overlay
|
from read_book.overlay import Overlay
|
||||||
@ -228,7 +229,7 @@ class View:
|
|||||||
|
|
||||||
def on_iframe_ready(self, data):
|
def on_iframe_ready(self, data):
|
||||||
messenger.reset()
|
messenger.reset()
|
||||||
self.send_message('initialize', secret=messenger.secret, translations=self.ui.interface_data.translations)
|
self.send_message('initialize', secret=messenger.secret, translations=get_translations())
|
||||||
self.iframe_ready = True
|
self.iframe_ready = True
|
||||||
if self.pending_load:
|
if self.pending_load:
|
||||||
data = self.pending_load
|
data = self.pending_load
|
||||||
@ -354,7 +355,7 @@ class View:
|
|||||||
|
|
||||||
def on_update_cfi(self, data):
|
def on_update_cfi(self, data):
|
||||||
self.currently_showing.bookpos = data.cfi
|
self.currently_showing.bookpos = data.cfi
|
||||||
get_boss().push_state(replace=data.replace_history)
|
push_state(self.url_data, replace=data.replace_history, mode=read_book_mode)
|
||||||
unkey = username_key(self.ui.interface_data.username)
|
unkey = username_key(self.ui.interface_data.username)
|
||||||
if not self.book.last_read_position:
|
if not self.book.last_read_position:
|
||||||
self.book.last_read_position = {}
|
self.book.last_read_position = {}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user