mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Work on reafactoring read_book module to make it useable in standalone viewer
This commit is contained in:
parent
953734320b
commit
9b3d5d486b
@ -17,7 +17,9 @@ from io import BytesIO
|
||||
from threading import Thread, local
|
||||
|
||||
from calibre import force_unicode
|
||||
from calibre.constants import __appname__, __version__, cache_dir
|
||||
from calibre.constants import (
|
||||
FAKE_HOST, FAKE_PROTOCOL, __appname__, __version__, cache_dir
|
||||
)
|
||||
from calibre.utils.filenames import atomic_rename
|
||||
from calibre.utils.terminal import ANSIStream
|
||||
from duktape import Context, JSError, to_python
|
||||
@ -226,7 +228,10 @@ def compile_viewer():
|
||||
rapydscript_dir = os.path.join(base, 'src', 'pyj')
|
||||
fname = os.path.join(rapydscript_dir, 'viewer-main.pyj')
|
||||
with lopen(fname, 'rb') as f:
|
||||
js = compile_fast(f.read(), fname, js_version=6).replace('__SPECIAL_TITLE__', special_title, 1)
|
||||
js = compile_fast(f.read(), fname, js_version=6).replace(
|
||||
'__SPECIAL_TITLE__', special_title, 1).replace(
|
||||
'__FAKE_PROTOCOL__', FAKE_PROTOCOL, 1).replace(
|
||||
'__FAKE_HOST__', FAKE_HOST, 1)
|
||||
base = os.path.join(base, 'resources')
|
||||
atomic_write(base, 'viewer.js', js)
|
||||
|
||||
|
@ -81,13 +81,16 @@ class IframeWrapper:
|
||||
|
||||
def create_srcdoc(self):
|
||||
r = /__([A-Z][A-Z_0-9]*[A-Z0-9])__/g
|
||||
data = {
|
||||
'BS': self.bootstrap_text,
|
||||
'SCRIPT': iframe_js(),
|
||||
'FONT': get_font_family(),
|
||||
'ENTRY_POINT': self.entry_point,
|
||||
}
|
||||
self.iframe.srcdoc = LOADING_DOC.replace(r, def(match, field): return data[field];)
|
||||
if self.entry_point:
|
||||
data = {
|
||||
'BS': self.bootstrap_text,
|
||||
'SCRIPT': iframe_js(),
|
||||
'FONT': get_font_family(),
|
||||
'ENTRY_POINT': self.entry_point,
|
||||
}
|
||||
self.iframe.srcdoc = LOADING_DOC.replace(r, def(match, field): return data[field];)
|
||||
else:
|
||||
self.iframe.srcdoc = '<div>\xa0</div>'
|
||||
self.srcdoc_created = True
|
||||
|
||||
def init(self):
|
||||
|
@ -60,3 +60,16 @@ register_callback(def():
|
||||
scheme = default_color_schemes[key]
|
||||
scheme.name = gt(scheme.name)
|
||||
)
|
||||
|
||||
runtime = {
|
||||
'is_standalone_viewer': False
|
||||
}
|
||||
|
||||
|
||||
ui_operations = {
|
||||
'get_file': None,
|
||||
'get_mathjax_files': None,
|
||||
'update_url_state': None,
|
||||
'update_last_read_time': None,
|
||||
'show_error': None,
|
||||
}
|
||||
|
@ -6,6 +6,7 @@ from elementmaker import E
|
||||
from encodings import base64decode, utf8_decode
|
||||
|
||||
from dom import clear
|
||||
from read_book.globals import ui_operations
|
||||
|
||||
JSON_XHTML_MIMETYPE = 'application/calibre+xhtml+json'
|
||||
|
||||
@ -19,7 +20,7 @@ def decode_url(x):
|
||||
def create_link_pat(book):
|
||||
return RegExp(book.manifest.link_uid + r'\|([^|]+)\|', 'g')
|
||||
|
||||
def load_resources(db, book, root_name, previous_resources, proceed):
|
||||
def load_resources(book, root_name, previous_resources, proceed):
|
||||
ans = Object.create(None)
|
||||
pending_resources = v'[root_name]'
|
||||
link_pat = create_link_pat(book)
|
||||
@ -29,7 +30,7 @@ def load_resources(db, book, root_name, previous_resources, proceed):
|
||||
for k in previous_resources:
|
||||
v'delete previous_resources[k]'
|
||||
if book.manifest.files[root_name].has_maths:
|
||||
return load_mathjax(db, book, ans, proceed)
|
||||
return load_mathjax(book, ans, proceed)
|
||||
return proceed(ans)
|
||||
name = pending_resources.shift()
|
||||
if ans[name]:
|
||||
@ -39,7 +40,7 @@ def load_resources(db, book, root_name, previous_resources, proceed):
|
||||
if jstype(data[0]) is 'string':
|
||||
find_virtualized_resources(data[0])
|
||||
return setTimeout(do_one, 0)
|
||||
db.get_file(book, name, got_one)
|
||||
ui_operations.get_file(book, name, got_one)
|
||||
|
||||
def got_one(data, name, mimetype):
|
||||
if False and name is book.manifest.title_page_name:
|
||||
@ -68,9 +69,9 @@ def load_resources(db, book, root_name, previous_resources, proceed):
|
||||
|
||||
mathjax_data = None
|
||||
|
||||
def load_mathjax(db, book, resource_data, proceed):
|
||||
def load_mathjax(book, resource_data, proceed):
|
||||
if mathjax_data is None:
|
||||
db.get_mathjax_files(def(data):
|
||||
ui_operations.get_mathjax_files(def(data):
|
||||
nonlocal mathjax_data
|
||||
mathjax_data = data
|
||||
resource_data['..mathjax-files..'] = data
|
||||
|
@ -1,13 +1,15 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import hash_literals, bound_methods
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from book_list.theme import get_color
|
||||
from complete import create_search_bar
|
||||
from dom import add_extra_css, build_rule, svgicon
|
||||
from keycodes import get_key
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
from book_list.theme import get_color
|
||||
from read_book.globals import ui_operations
|
||||
from read_book.resources import text_from_serialized_html
|
||||
|
||||
CLASS_NAME = 'book-search-container'
|
||||
@ -84,7 +86,7 @@ def find_in_serialized_html(data, text):
|
||||
return haystack.toLowerCase().indexOf(text) > -1
|
||||
|
||||
|
||||
def find_in_spine(names, book, db, text, proceed):
|
||||
def find_in_spine(names, book, text, proceed):
|
||||
text = text.toLowerCase()
|
||||
|
||||
def got_one(data, name, mimetype):
|
||||
@ -96,7 +98,7 @@ def find_in_spine(names, book, db, text, proceed):
|
||||
def do_one():
|
||||
name = names.shift()
|
||||
if name:
|
||||
db.get_file(book, name, got_one)
|
||||
ui_operations.get_file(book, name, got_one)
|
||||
else:
|
||||
proceed(None)
|
||||
|
||||
|
@ -9,14 +9,13 @@ from gettext import gettext as _
|
||||
|
||||
from ajax import ajax
|
||||
from book_list.constants import read_book_container_id
|
||||
from book_list.library_data import (
|
||||
current_library_id, library_data
|
||||
)
|
||||
from book_list.library_data import current_library_id, library_data
|
||||
from book_list.router import home, push_state, read_book_mode, update_window_title
|
||||
from book_list.ui import show_panel
|
||||
from book_list.router import update_window_title, home
|
||||
from dom import clear
|
||||
from modals import create_simple_dialog_markup, error_dialog
|
||||
from read_book.db import get_db
|
||||
from read_book.globals import ui_operations
|
||||
from read_book.view import View
|
||||
from utils import debounce, human_readable
|
||||
from widgets import create_button
|
||||
@ -53,9 +52,14 @@ class ReadUI:
|
||||
container.appendChild(E.div(
|
||||
id=self.display_id, style='display:none',
|
||||
))
|
||||
self.view = View(container.lastChild, self)
|
||||
self.view = View(container.lastChild)
|
||||
window.addEventListener('resize', debounce(self.on_resize.bind(self), 250))
|
||||
self.db = get_db(self.db_initialized.bind(self), self.show_error.bind(self))
|
||||
ui_operations.get_file = self.db.get_file
|
||||
ui_operations.get_mathjax_files = self.db.get_mathjax_files
|
||||
ui_operations.update_url_state = self.update_url_state.bind(self)
|
||||
ui_operations.update_last_read_time = self.db.update_last_read_time
|
||||
ui_operations.show_error = self.show_error.bind(self)
|
||||
|
||||
def on_resize(self):
|
||||
self.view.on_resize()
|
||||
@ -448,3 +452,6 @@ class ReadUI:
|
||||
self.view.goto_bookpos(current_query.bookpos)
|
||||
else:
|
||||
self.load_book(current_query.library_id, int(current_query.book_id), current_query.fmt, library_data.metadata[current_query.book_id])
|
||||
|
||||
def update_url_state(self, replace):
|
||||
push_state(self.url_data, replace=replace, mode=read_book_mode)
|
||||
|
@ -9,13 +9,14 @@ import read_book.iframe # noqa
|
||||
from ajax import ajax_send
|
||||
from book_list.book_details import CLASS_NAME as BD_CLASS_NAME, render_metadata
|
||||
from book_list.globals import get_session_data
|
||||
from book_list.router import push_state, read_book_mode
|
||||
from book_list.theme import get_color
|
||||
from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id
|
||||
from iframe_comm import IframeWrapper
|
||||
from modals import error_dialog, warning_dialog
|
||||
from read_book.content_popup import ContentPopupOverlay
|
||||
from read_book.globals import current_book, set_current_spine_item
|
||||
from read_book.globals import (
|
||||
current_book, runtime, set_current_spine_item, ui_operations
|
||||
)
|
||||
from read_book.goto import get_next_section
|
||||
from read_book.overlay import Overlay
|
||||
from read_book.prefs.colors import resolve_color_scheme
|
||||
@ -115,8 +116,7 @@ def margin_elem(sd, which, id, onclick):
|
||||
|
||||
class View:
|
||||
|
||||
def __init__(self, container, ui):
|
||||
self.ui = ui
|
||||
def __init__(self, container):
|
||||
self.timers = Timers()
|
||||
self.loaded_resources = {}
|
||||
self.current_progress_frac = self.current_file_progress_frac = 0
|
||||
@ -167,7 +167,8 @@ class View:
|
||||
'print': self.on_print,
|
||||
'human_scroll': self.on_human_scroll,
|
||||
}
|
||||
self.iframe_wrapper = IframeWrapper(handlers, document.getElementById(iframe_id), 'read_book.iframe', _('Bootstrapping book reader...'))
|
||||
entry_point = None if runtime.is_standalone_viewer else 'read_book.iframe'
|
||||
self.iframe_wrapper = IframeWrapper(handlers, document.getElementById(iframe_id), entry_point, _('Bootstrapping book reader...'))
|
||||
self.search_overlay = SearchOverlay(self)
|
||||
self.content_popup_overlay = ContentPopupOverlay(self)
|
||||
self.overlay = Overlay(self)
|
||||
@ -245,7 +246,7 @@ class View:
|
||||
for items in item_groups:
|
||||
for i in items:
|
||||
names.push(spine[i])
|
||||
find_in_spine(names, self.book, self.ui.db, data.text, def(found_in):
|
||||
find_in_spine(names, self.book, data.text, def(found_in):
|
||||
if found_in:
|
||||
self.show_name(found_in, initial_position={'type':'search', 'search_data':data, 'replace_history':True})
|
||||
else:
|
||||
@ -322,7 +323,7 @@ class View:
|
||||
self.show_spine_item_stage2(data)
|
||||
|
||||
def on_iframe_error(self, data):
|
||||
self.ui.show_error((data.title or _('There was an error processing the book')), data.msg, data.details)
|
||||
ui_operations.show_error((data.title or _('There was an error processing the book')), data.msg, data.details)
|
||||
|
||||
def get_color_scheme(self, apply_to_margins):
|
||||
ans = resolve_color_scheme()
|
||||
@ -376,7 +377,8 @@ class View:
|
||||
self.content_popup_overlay.loaded_resources = {}
|
||||
self.timers.start_book(book)
|
||||
self.book = current_book.book = book
|
||||
self.ui.db.update_last_read_time(book)
|
||||
if ui_operations.update_last_read_time:
|
||||
ui_operations.update_last_read_time(book)
|
||||
pos = {'replace_history':True}
|
||||
unkey = username_key(get_interface_data().username)
|
||||
name = book.manifest.spine[0]
|
||||
@ -431,7 +433,7 @@ class View:
|
||||
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)
|
||||
load_resources(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]
|
||||
@ -495,13 +497,14 @@ class View:
|
||||
# See https://bugs.chromium.org/p/chromium/issues/detail?id=404315
|
||||
return
|
||||
self.currently_showing.bookpos = data.cfi
|
||||
push_state(self.ui.url_data, replace=data.replace_history, mode=read_book_mode)
|
||||
ui_operations.update_url_state(data.replace_history)
|
||||
username = get_interface_data().username
|
||||
unkey = username_key(username)
|
||||
if not self.book.last_read_position:
|
||||
self.book.last_read_position = {}
|
||||
self.book.last_read_position[unkey] = data.cfi
|
||||
self.ui.db.update_last_read_time(self.book)
|
||||
if ui_operations.update_last_read_time:
|
||||
ui_operations.update_last_read_time(self.book)
|
||||
lrd = {'device':get_device_uuid(), 'cfi':data.cfi, 'pos_frac':data.progress_frac}
|
||||
self.current_progress_frac = data.progress_frac
|
||||
self.current_file_progress_frac = data.file_progress_frac
|
||||
|
@ -2,4 +2,17 @@
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
print('11111111111111', document.location.href)
|
||||
|
||||
from elementmaker import E
|
||||
from read_book.globals import runtime
|
||||
|
||||
def container_div(id):
|
||||
return E.div(id=id, style='margin: 0; padding: 0; display: none')
|
||||
|
||||
runtime.is_standalone_viewer = True
|
||||
if window is window.top:
|
||||
# main
|
||||
document.body.appendChild(E.iframe(srcdoc="<p>hello"))
|
||||
else:
|
||||
# iframe
|
||||
pass
|
||||
|
0
src/pyj/viewer/__init__.pyj
Normal file
0
src/pyj/viewer/__init__.pyj
Normal file
7
src/pyj/viewer/constants.pyj
Normal file
7
src/pyj/viewer/constants.pyj
Normal file
@ -0,0 +1,7 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2018, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
|
||||
FAKE_PROTOCOL = '__FAKE_PROTOCOL__'
|
||||
FAKE_HOST = '__FAKE_HOST__'
|
Loading…
x
Reference in New Issue
Block a user