mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
E-book viewer: Speed up initialisation of WebEngine
Prevent the viewer JavaScript from being loaded multiple times on the various iframes. Also only create the iframe used for the footnote popups on demand.
This commit is contained in:
parent
9a3a8bd271
commit
b8e128271d
@ -6,8 +6,8 @@ from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from book_list.theme import get_color, get_color_as_rgba
|
||||
from dom import add_extra_css, build_rule, clear, ensure_id, svgicon
|
||||
from iframe_comm import IframeClient, IframeWrapper
|
||||
from dom import add_extra_css, build_rule, clear, svgicon
|
||||
from iframe_comm import IframeClient, create_wrapped_iframe
|
||||
from modals import create_custom_dialog
|
||||
from utils import html_escape
|
||||
from widgets import create_button
|
||||
@ -348,17 +348,19 @@ def add_editor(editor):
|
||||
|
||||
class Editor:
|
||||
|
||||
def __init__(self, iframe):
|
||||
def __init__(self, iframe_kw):
|
||||
handlers = {
|
||||
'ready': self.on_iframe_ready,
|
||||
'html': self.on_html_received,
|
||||
'update_state': self.update_state,
|
||||
}
|
||||
self.iframe_wrapper = IframeWrapper(handlers, iframe, 'book_list.comments_editor', _('Loading comments editor...'))
|
||||
self.id = ensure_id(iframe)
|
||||
iframe, self.iframe_wrapper = create_wrapped_iframe(
|
||||
handlers, _('Loading comments editor...'), 'book_list.comments_editor', iframe_kw)
|
||||
self.id = iframe.id
|
||||
self.ready = False
|
||||
self.pending_set_html = None
|
||||
self.get_html_callbacks = v'[]'
|
||||
self.iframe_obj = iframe
|
||||
|
||||
def init(self):
|
||||
self.iframe_wrapper.init()
|
||||
@ -421,8 +423,12 @@ class Editor:
|
||||
|
||||
|
||||
def create_editor():
|
||||
iframe = E.iframe(sandbox='allow-scripts', seamless=True, style='flex-grow: 10; border: solid 1px currentColor', id=self.id)
|
||||
editor = Editor(iframe)
|
||||
iframe_kw = {
|
||||
'sandbox': 'allow-scripts', 'seamless': True, 'style': 'flex-grow: 10; border: solid 1px currentColor'
|
||||
}
|
||||
editor = Editor(iframe_kw)
|
||||
iframe = editor.iframe_obj
|
||||
v'delete editor.iframe_obj'
|
||||
add_editor(editor)
|
||||
return iframe, editor
|
||||
|
||||
|
@ -2,14 +2,14 @@
|
||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
import traceback
|
||||
from aes import GCM
|
||||
from gettext import gettext as _, install
|
||||
from elementmaker import E
|
||||
|
||||
import traceback
|
||||
from book_list.globals import get_translations, main_js
|
||||
from book_list.theme import get_font_family
|
||||
from dom import ensure_id
|
||||
|
||||
from gettext import gettext as _, install
|
||||
|
||||
LOADING_DOC = '''
|
||||
<!DOCTYPE html>
|
||||
@ -58,16 +58,22 @@ class Messenger:
|
||||
|
||||
class IframeWrapper:
|
||||
|
||||
def __init__(self, handlers, iframe, entry_point, bootstrap_text, url):
|
||||
def __init__(self, handlers, iframe, entry_point, bootstrap_text):
|
||||
self.messenger = Messenger()
|
||||
self.iframe_id = ensure_id(iframe, 'content-iframe')
|
||||
self.needs_init = True
|
||||
if ':' in entry_point:
|
||||
self.needs_init = False
|
||||
self.srcdoc_created = True
|
||||
self.constructor_url = entry_point
|
||||
self.entry_point = None
|
||||
else:
|
||||
self.needs_init = True
|
||||
self.srcdoc_created = False
|
||||
self.constructor_url = None
|
||||
self.entry_point = entry_point
|
||||
self.ready = False
|
||||
self.encrypted_communications = False
|
||||
self.srcdoc_created = False
|
||||
self.constructor_url = url
|
||||
self.entry_point = entry_point
|
||||
self.bootstrap_text = bootstrap_text
|
||||
self.bootstrap_text = bootstrap_text or ''
|
||||
self.handlers = {k: handlers[k] for k in handlers}
|
||||
self.on_ready_handler = self.handlers.ready
|
||||
self.handlers.ready = self.on_iframe_ready
|
||||
@ -164,6 +170,15 @@ class IframeWrapper:
|
||||
callback()
|
||||
|
||||
|
||||
def create_wrapped_iframe(handlers, bootstrap_text, entry_point, kw):
|
||||
if ':' in entry_point:
|
||||
kw.src = entry_point
|
||||
kw.sandbox = (kw.sandbox or '') + ' allow-same-origin'
|
||||
iframe = E.iframe(**kw)
|
||||
ans = IframeWrapper(handlers, iframe, entry_point, bootstrap_text)
|
||||
return iframe, ans
|
||||
|
||||
|
||||
class IframeClient:
|
||||
|
||||
def __init__(self, handlers):
|
||||
|
@ -6,7 +6,7 @@ from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from dom import add_extra_css, build_rule, clear, svgicon
|
||||
from iframe_comm import IframeWrapper
|
||||
from iframe_comm import create_wrapped_iframe
|
||||
from read_book.globals import runtime, ui_operations
|
||||
from read_book.resources import load_resources
|
||||
|
||||
@ -42,29 +42,35 @@ class ContentPopupOverlay:
|
||||
self.loaded_resources = {}
|
||||
c = self.container
|
||||
c.classList.add(CLASS_NAME)
|
||||
sandbox = 'allow-scripts'
|
||||
if runtime.is_standalone_viewer:
|
||||
sandbox += ' allow-same-origin'
|
||||
iframe = E.iframe(seamless=True, sandbox=sandbox, style='width: 100%; max-height: 70vh')
|
||||
|
||||
c.appendChild(E.div(
|
||||
E.div(),
|
||||
iframe
|
||||
))
|
||||
c.appendChild(E.div(E.div()))
|
||||
c.addEventListener('click', self.hide)
|
||||
c.firstChild.addEventListener('click', def(ev):
|
||||
ev.stopPropagation(), ev.preventDefault()
|
||||
)
|
||||
self.pending_load = None
|
||||
|
||||
def reset(self):
|
||||
if self.iframe_wrapper:
|
||||
self.iframe_wrapper.reset()
|
||||
|
||||
def create_iframe(self):
|
||||
handlers = {
|
||||
'ready': self.on_iframe_ready,
|
||||
'error': self.view.on_iframe_error,
|
||||
'content_loaded': self.on_content_loaded,
|
||||
}
|
||||
entry_point = None if runtime.is_standalone_viewer else 'read_book.footnotes'
|
||||
self.iframe_wrapper = IframeWrapper(
|
||||
handlers, iframe, entry_point, _('Loading data, please wait...'),
|
||||
f'{runtime.FAKE_PROTOCOL}://{runtime.SANDBOX_HOST}/book/__popup__')
|
||||
self.pending_load = None
|
||||
iframe_kw = {
|
||||
'seamless': True, 'sandbox': 'allow-scripts', 'style': 'width: 100%; max-height: 70vh'
|
||||
}
|
||||
if runtime.is_standalone_viewer:
|
||||
entry_point = f'{runtime.FAKE_PROTOCOL}://{runtime.SANDBOX_HOST}/book/__popup__'
|
||||
else:
|
||||
entry_point = 'read_book.footnotes'
|
||||
iframe, self.iframe_wrapper = create_wrapped_iframe(
|
||||
handlers, _('Loading data, please wait...'), entry_point, iframe_kw
|
||||
)
|
||||
c = self.container
|
||||
c.firstChild.appendChild(iframe)
|
||||
|
||||
@property
|
||||
def container(self):
|
||||
@ -117,6 +123,8 @@ class ContentPopupOverlay:
|
||||
load_resources(self.view.book, name, self.loaded_resources, cb)
|
||||
|
||||
def show_footnote(self, data):
|
||||
if not self.iframe_wrapper:
|
||||
self.create_iframe()
|
||||
self.current_footnote_data = data
|
||||
width = 100 // data.cols_per_screen
|
||||
c = self.container.firstChild
|
||||
|
@ -11,7 +11,7 @@ from book_list.theme import cached_color_to_rgba, get_color, set_ui_colors
|
||||
from book_list.ui import query_as_href
|
||||
from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id
|
||||
from gettext import gettext as _
|
||||
from iframe_comm import IframeWrapper
|
||||
from iframe_comm import create_wrapped_iframe
|
||||
from modals import error_dialog, warning_dialog
|
||||
from read_book.annotations import AnnotationsManager
|
||||
from read_book.bookmarks import create_new_bookmark
|
||||
@ -229,38 +229,6 @@ class View:
|
||||
set_left_margin_handler(left_margin)
|
||||
right_margin = side_margin_elem(self, sd, 'right')
|
||||
set_right_margin_handler(right_margin)
|
||||
iframe_id = unique_id('read-book-iframe')
|
||||
sandbox = 'allow-popups allow-scripts allow-popups-to-escape-sandbox'
|
||||
if runtime.is_standalone_viewer:
|
||||
sandbox += ' allow-same-origin'
|
||||
container.appendChild(
|
||||
E.div(style='max-height: 100vh; width: 100vw; height: 100vh; overflow: hidden; display: flex; align-items: stretch', # container for horizontally aligned panels
|
||||
oncontextmenu=def (ev):
|
||||
if not default_context_menu_should_be_allowed(ev):
|
||||
ev.preventDefault()
|
||||
,
|
||||
|
||||
E.div(style='max-height: 100vh; display: flex; flex-direction: column; align-items: stretch; flex-grow:2', # container for iframe and any other panels in the same column
|
||||
E.div(style='max-height: 100vh; flex-grow: 2; display:flex; align-items: stretch', # container for iframe and its overlay
|
||||
left_margin,
|
||||
E.div(style='flex-grow:2; display:flex; align-items:stretch; flex-direction: column', # container for top and bottom margins
|
||||
margin_elem(sd, 'margin_top', 'book-top-margin', self.top_margin_clicked, self.margin_context_menu.bind(None, 'top')),
|
||||
E.iframe(id=iframe_id, seamless=True, sandbox=sandbox, style='flex-grow: 2', allowfullscreen='true'),
|
||||
margin_elem(sd, 'margin_bottom', 'book-bottom-margin', self.bottom_margin_clicked, self.margin_context_menu.bind(None, 'bottom')),
|
||||
),
|
||||
right_margin,
|
||||
self.book_scrollbar.create(),
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-selection-bar-overlay'), # selection bar overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-read-aloud-overlay'), # read aloud overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-hints-overlay'), # hints overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; pointer-events:none; display:none', id='book-search-overlay'), # search overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='book-content-popup-overlay'), # content popup overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; overflow: auto; display:none', id='book-overlay'), # main overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='controls-help-overlay'), # controls help overlay
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
handlers = {
|
||||
'autoscroll_state_changed': def(data):
|
||||
self.autoscroll_active = v'!!data.running'
|
||||
@ -304,15 +272,51 @@ class View:
|
||||
ui_operations.view_image(data.calibre_src)
|
||||
,
|
||||
}
|
||||
entry_point = None if runtime.is_standalone_viewer else 'read_book.iframe'
|
||||
|
||||
iframe_id = unique_id('read-book-iframe')
|
||||
if runtime.is_standalone_viewer:
|
||||
entry_point = f'{runtime.FAKE_PROTOCOL}://{runtime.SANDBOX_HOST}/book/__index__'
|
||||
else:
|
||||
entry_point = 'read_book.iframe'
|
||||
iframe_kw = {
|
||||
'id': iframe_id, 'seamless': True,
|
||||
'sandbox': 'allow-popups allow-scripts allow-popups-to-escape-sandbox',
|
||||
'style': 'flex-grow: 2', 'allowfullscreen': 'true',
|
||||
}
|
||||
iframe, self.iframe_wrapper = create_wrapped_iframe(handlers, _('Bootstrapping book reader...'), entry_point, iframe_kw)
|
||||
container.appendChild(
|
||||
E.div(style='max-height: 100vh; width: 100vw; height: 100vh; overflow: hidden; display: flex; align-items: stretch', # container for horizontally aligned panels
|
||||
oncontextmenu=def (ev):
|
||||
if not default_context_menu_should_be_allowed(ev):
|
||||
ev.preventDefault()
|
||||
,
|
||||
|
||||
E.div(style='max-height: 100vh; display: flex; flex-direction: column; align-items: stretch; flex-grow:2', # container for iframe and any other panels in the same column
|
||||
E.div(style='max-height: 100vh; flex-grow: 2; display:flex; align-items: stretch', # container for iframe and its overlay
|
||||
left_margin,
|
||||
E.div(style='flex-grow:2; display:flex; align-items:stretch; flex-direction: column', # container for top and bottom margins
|
||||
margin_elem(sd, 'margin_top', 'book-top-margin', self.top_margin_clicked, self.margin_context_menu.bind(None, 'top')),
|
||||
iframe,
|
||||
margin_elem(sd, 'margin_bottom', 'book-bottom-margin', self.bottom_margin_clicked, self.margin_context_menu.bind(None, 'bottom')),
|
||||
),
|
||||
right_margin,
|
||||
self.book_scrollbar.create(),
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-selection-bar-overlay'), # selection bar overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-read-aloud-overlay'), # read aloud overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none;', id='book-hints-overlay'), # hints overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; pointer-events:none; display:none', id='book-search-overlay'), # search overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='book-content-popup-overlay'), # content popup overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; overflow: auto; display:none', id='book-overlay'), # main overlay
|
||||
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='controls-help-overlay'), # controls help overlay
|
||||
)
|
||||
),
|
||||
),
|
||||
)
|
||||
self.current_color_scheme = resolve_color_scheme()
|
||||
if runtime.is_standalone_viewer:
|
||||
document.documentElement.addEventListener('keydown', self.handle_keypress, {'passive': False})
|
||||
set_ui_colors(self.current_color_scheme.is_dark_theme)
|
||||
is_dark_theme(self.current_color_scheme.is_dark_theme)
|
||||
self.iframe_wrapper = IframeWrapper(
|
||||
handlers, document.getElementById(iframe_id), entry_point, _('Bootstrapping book reader...'),
|
||||
f'{runtime.FAKE_PROTOCOL}://{runtime.SANDBOX_HOST}/book/__index__')
|
||||
self.search_overlay = SearchOverlay(self)
|
||||
self.content_popup_overlay = ContentPopupOverlay(self)
|
||||
self.overlay = Overlay(self)
|
||||
@ -914,7 +918,7 @@ class View:
|
||||
self.book_load_started = True
|
||||
if not is_current_book:
|
||||
self.iframe_wrapper.reset()
|
||||
self.content_popup_overlay.iframe_wrapper.reset()
|
||||
self.content_popup_overlay.reset()
|
||||
self.loaded_resources = {}
|
||||
self.content_popup_overlay.loaded_resources = {}
|
||||
self.timers.start_book(book)
|
||||
|
Loading…
x
Reference in New Issue
Block a user