Wire up the footnote popup

This commit is contained in:
Kovid Goyal 2017-10-16 11:58:31 +05:30
parent cad17a5785
commit 9ed99e752f
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 98 additions and 9 deletions

View File

@ -7,6 +7,7 @@ from gettext import gettext as _
from dom import add_extra_css, build_rule, clear, svgicon
from read_book.comm import IframeWrapper
from read_book.resources import load_resources
CLASS_NAME = 'book-content-popup-container'
TOP_LEVEL_DISPLAY = 'flex'
@ -37,9 +38,10 @@ class ContentPopupOverlay:
def __init__(self, view):
self.view = view
self.loaded_resources = {}
c = self.container
c.classList.add(CLASS_NAME)
iframe = E.iframe(seamless=True, sandbox='allow-scripts')
iframe = E.iframe(seamless=True, sandbox='allow-scripts', style='width: 100%; max-height: 70vh')
c.appendChild(E.div(
E.div(),
@ -51,6 +53,8 @@ class ContentPopupOverlay:
)
handlers = {
'ready': self.on_iframe_ready,
'error': self.view.on_iframe_error,
'content_loaded': self.on_content_loaded,
}
self.iframe_wrapper = IframeWrapper(handlers, iframe, 'popup', _('Loading data, please wait...'))
self.pending_load = None
@ -98,6 +102,12 @@ class ContentPopupOverlay:
bc.lastChild.addEventListener('click', self.hide)
header.appendChild(bc)
def load_doc(self, name, done_callback):
def cb(resource_data):
self.loaded_resources = resource_data
done_callback(resource_data)
load_resources(self.view.ui.db, self.view.book, name, self.loaded_resources, cb)
def show_footnote(self, data):
self.current_footnote_data = data
width = 100 // data.cols_per_screen
@ -105,3 +115,27 @@ class ContentPopupOverlay:
c.style.width = f'{width}vw'
header = c.firstChild
self.create_footnote_header(header)
self.load_doc(data.name, self.show_footnote_item)
self.iframe.style.height = '12ex'
self.iframe_wrapper.send_message('clear', text=_('Loading note, please wait...'))
def show_footnote_item(self, resource_data):
self.pending_load = resource_data, self.show_footnote_item_stage2
if self.iframe_wrapper.ready:
self.do_pending_load()
else:
self.iframe_wrapper.init()
def do_pending_load(self):
if self.pending_load:
data, func = self.pending_load
self.pending_load = None
func(data)
def show_footnote_item_stage2(self, resource_data):
self.iframe_wrapper.send_unencrypted_message('display',
resource_data=resource_data, book=self.view.book, name=self.current_footnote_data.name,
frag=self.current_footnote_data.frag)
def on_content_loaded(self, data):
self.iframe.style.height = f'{data.height}px'

View File

@ -2,6 +2,10 @@
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
from __python__ import bound_methods, hash_literals
from dom import clear
from read_book.comm import IframeClient
from read_book.resources import finalize_resources, unserialize_html
def elem_roles(elem):
return {k.toLowerCase(): True for k in (elem.getAttribute('role') or '').split(' ')}
@ -68,3 +72,48 @@ def is_footnote_link(a, dest_name, dest_frag, src_name, link_to_map):
is_footnote_link.inline_displays = {'inline': True, 'inline-block': True}
is_footnote_link.vert_aligns = {'sub': True, 'super': True, 'top': True, 'bottom': True}
class PopupIframeBoss:
def __init__(self):
handlers = {
'initialize': self.initialize,
'clear': self.on_clear,
'display': self.display,
}
self.comm = IframeClient(handlers)
self.blob_url_map = {}
self.name = None
self.frag = None
def initialize(self, data):
window.onerror = self.onerror
def onerror(self, msg, script_url, line_number, column_number, error_object):
if error_object is None:
# This happens for cross-domain errors (probably javascript injected
# into the browser via extensions/ userscripts and the like). It also
# happens all the time when using Chrome on Safari
console.log(f'Unhandled error from external javascript, ignoring: {msg} {script_url} {line_number}')
else:
console.log(error_object)
def display(self, data):
self.book = data.book
self.name = data.name
self.frag = data.frag
for name in self.blob_url_map:
window.URL.revokeObjectURL(self.blob_url_map[name])
root_data, self.mathjax, self.blob_url_map = finalize_resources(self.book, data.name, data.resource_data)
self.resource_urls = unserialize_html(root_data, self.content_loaded)
def on_clear(self, data):
clear(document.head)
clear(document.body)
document.body.textContent = data.text
self.name = None
self.frag = None
def content_loaded(self):
self.comm.send_message('content_loaded', height=document.documentElement.scrollHeight + 25)

View File

@ -12,7 +12,7 @@ from read_book.flow_mode import (
flow_to_scroll_fraction, handle_gesture as flow_handle_gesture,
layout as flow_layout, scroll_by_page as flow_scroll_by_page
)
from read_book.footnotes import is_footnote_link
from read_book.footnotes import is_footnote_link, PopupIframeBoss
from read_book.globals import (
current_book, current_layout_mode, current_spine_item, set_boss,
set_current_spine_item, set_layout_mode
@ -104,7 +104,7 @@ class IframeBoss:
if error_object is None:
# This happens for cross-domain errors (probably javascript injected
# into the browser via extensions/ userscripts and the like). It also
# happens all the time when using Chrom on Safari, so ignore this
# happens all the time when using Chrome on Safari, so ignore this
# type of error
console.log(f'Unhandled error from external javascript, ignoring: {msg} {script_url} {line_number}')
return
@ -387,5 +387,5 @@ def init():
script = document.getElementById('bootstrap')
script.parentNode.removeChild(script) # free up some memory
IframeBoss()
# elif window.iframe_type is 'popup':
# PopupIframeBoss()
elif window.iframe_type is 'popup':
PopupIframeBoss()

View File

@ -326,9 +326,10 @@ class View:
if not is_current_book:
self.iframe_wrapper.reset()
self.content_popup_overlay.iframe_wrapper.reset()
self.loaded_resources = {}
self.content_popup_overlay.loaded_resources = {}
self.book = current_book.book = book
self.ui.db.update_last_read_time(book)
self.loaded_resources = {}
pos = {'replace_history':True}
unkey = username_key(get_interface_data().username)
name = book.manifest.spine[0]
@ -374,7 +375,13 @@ class View:
if idx > -1:
self.currently_showing.bookpos = 'epubcfi(/{})'.format(2 * (idx +1))
self.set_margins()
load_resources(self.ui.db, self.book, name, self.loaded_resources, self.show_spine_item)
self.load_doc(name, self.show_spine_item)
def load_doc(self, name, done_callback):
def cb(resource_data):
self.loaded_resources = resource_data
done_callback(resource_data)
load_resources(self.ui.db, self.book, name, self.loaded_resources, cb)
def goto_doc_boundary(self, start):
name = self.book.manifest.spine[0 if start else self.book.manifest.spine.length - 1]
@ -467,7 +474,6 @@ class View:
update_visible_toc_nodes(data.visible_anchors)
def show_spine_item(self, resource_data):
self.loaded_resources = resource_data
self.pending_load = resource_data
if self.iframe_wrapper.ready:
self.do_pending_load()