mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-08 02:34:06 -04:00
Implement header bar for footnote popup
This commit is contained in:
parent
c2f050ed2a
commit
f4a6f0117d
94
src/pyj/read_book/content_popup.pyj
Normal file
94
src/pyj/read_book/content_popup.pyj
Normal file
@ -0,0 +1,94 @@
|
||||
# vim:fileencoding=utf-8
|
||||
# License: GPL v3 Copyright: 2017, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
|
||||
from dom import add_extra_css, build_rule, clear, svgicon
|
||||
|
||||
CLASS_NAME = 'book-content-popup-container'
|
||||
TOP_LEVEL_DISPLAY = 'flex'
|
||||
|
||||
add_extra_css(def():
|
||||
sel = '.' + CLASS_NAME
|
||||
style = ''
|
||||
style += build_rule(sel, justify_content='center', align_items='center', height='100%')
|
||||
|
||||
sel += ' > div'
|
||||
style += build_rule(sel, border_radius='8px', border='solid currentColor 2px', margin='1rem', padding='0.5rem', box_shadow='2px 2px 4px currentColor')
|
||||
|
||||
sel += ' > div'
|
||||
style += build_rule(sel, padding_bottom='1ex', margin_bottom='1ex', border_bottom='solid currentColor 2px', display='flex', justify_content='space-between', align_items='center')
|
||||
|
||||
sel += ' > div' # button container
|
||||
style += build_rule(sel, display='flex', justify_content='space-between', align_items='center')
|
||||
|
||||
sel += ' > a' # buttons
|
||||
style += build_rule(sel, margin_left='1ex', cursor='pointer', display='inline-block')
|
||||
style += build_rule(sel + ':hover', transform='scale(1.5)')
|
||||
style += build_rule(sel + ':active', transform='scale(2)')
|
||||
return style
|
||||
)
|
||||
|
||||
|
||||
class ContentPopupOverlay:
|
||||
|
||||
def __init__(self, view):
|
||||
self.view = view
|
||||
c = self.container
|
||||
c.classList.add(CLASS_NAME)
|
||||
|
||||
c.appendChild(E.div(
|
||||
E.div(),
|
||||
E.iframe(seamless=True, sandbox='allow-scripts')
|
||||
))
|
||||
c.addEventListener('click', self.hide)
|
||||
c.firstChild.addEventListener('click', def(ev):
|
||||
ev.stopPropagation(), ev.preventDefault()
|
||||
)
|
||||
|
||||
@property
|
||||
def container(self):
|
||||
return document.getElementById('book-content-popup-overlay')
|
||||
|
||||
@property
|
||||
def is_visible(self):
|
||||
return self.container.style.display is not 'none'
|
||||
|
||||
def hide(self):
|
||||
self.container.style.display = 'none'
|
||||
|
||||
def show(self):
|
||||
c = self.container
|
||||
c.style.display = TOP_LEVEL_DISPLAY
|
||||
|
||||
def apply_color_scheme(self, bg, fg):
|
||||
c = self.container.firstChild
|
||||
c.style.backgroundColor = bg
|
||||
c.style.color = fg
|
||||
|
||||
def create_footnote_header(self, header):
|
||||
clear(header)
|
||||
header.appendChild(
|
||||
E.h3(self.current_footnote_data.title or _('Footnote')),
|
||||
)
|
||||
bc = E.div(
|
||||
E.a(svgicon('arrow-right'), title=_('Go to this footnote in the main view'), href='javascript:void(0)'),
|
||||
E.a(svgicon('close'), title=_('Close the footnotes window'), href='javascript:void(0)')
|
||||
)
|
||||
bc.firstChild.addEventListener('click', def():
|
||||
self.hide()
|
||||
self.view.goto_named_destination(self.current_footnote_data.name, self.current_footnote_data.frag)
|
||||
)
|
||||
bc.lastChild.addEventListener('click', self.hide)
|
||||
header.appendChild(bc)
|
||||
|
||||
def show_footnote(self, data):
|
||||
self.current_footnote_data = data
|
||||
width = 100 // data.cols_per_screen
|
||||
c = self.container.firstChild
|
||||
c.style.width = f'{width}vw'
|
||||
header = c.firstChild
|
||||
self.create_footnote_header(header)
|
||||
# iframe = c.lastChild
|
@ -19,11 +19,12 @@ from read_book.globals import (
|
||||
)
|
||||
from read_book.mathjax import apply_mathjax
|
||||
from read_book.paged_mode import (
|
||||
anchor_funcs as paged_anchor_funcs, handle_gesture as paged_handle_gesture,
|
||||
jump_to_cfi as paged_jump_to_cfi, layout as paged_layout,
|
||||
onkeydown as paged_onkeydown, onwheel as paged_onwheel, progress_frac,
|
||||
reset_paged_mode_globals, scroll_by_page as paged_scroll_by_page, scroll_to_elem,
|
||||
scroll_to_fraction as paged_scroll_to_fraction, snap_to_selection
|
||||
anchor_funcs as paged_anchor_funcs, calc_columns_per_screen,
|
||||
handle_gesture as paged_handle_gesture, jump_to_cfi as paged_jump_to_cfi,
|
||||
layout as paged_layout, onkeydown as paged_onkeydown, onwheel as paged_onwheel,
|
||||
progress_frac, reset_paged_mode_globals, scroll_by_page as paged_scroll_by_page,
|
||||
scroll_to_elem, scroll_to_fraction as paged_scroll_to_fraction,
|
||||
snap_to_selection
|
||||
)
|
||||
from read_book.resources import finalize_resources, unserialize_html
|
||||
from read_book.settings import apply_settings, opts
|
||||
@ -391,7 +392,8 @@ class IframeBoss:
|
||||
traceback.print_exc()
|
||||
is_popup = False
|
||||
if is_popup:
|
||||
pass
|
||||
self.send_message('show_footnote', name=name, frag=frag, title=evt.currentTarget.textContent, cols_per_screen=calc_columns_per_screen())
|
||||
return
|
||||
if name is current_spine_item().name:
|
||||
self.replace_history_on_next_cfi_update = False
|
||||
self.scroll_to_anchor(frag)
|
||||
|
@ -114,10 +114,7 @@ def fit_images():
|
||||
set_elem_data(img, 'height-limited', True)
|
||||
|
||||
|
||||
def layout(is_single_page):
|
||||
nonlocal _in_paged_mode, col_width, col_and_gap, screen_height, gap, screen_width, is_full_screen_layout, cols_per_screen
|
||||
body_style = window.getComputedStyle(document.body)
|
||||
first_layout = not _in_paged_mode
|
||||
def calc_columns_per_screen():
|
||||
cps = opts.columns_per_screen or {}
|
||||
cps = cps.landscape if scroll_viewport.width() > scroll_viewport.height() else cps.portrait
|
||||
try:
|
||||
@ -127,6 +124,14 @@ def layout(is_single_page):
|
||||
if not cps:
|
||||
cps = int(Math.floor(scroll_viewport.width() / 500.0))
|
||||
cps = max(1, min(cps or 1, 20))
|
||||
return cps
|
||||
|
||||
|
||||
def layout(is_single_page):
|
||||
nonlocal _in_paged_mode, col_width, col_and_gap, screen_height, gap, screen_width, is_full_screen_layout, cols_per_screen
|
||||
body_style = window.getComputedStyle(document.body)
|
||||
first_layout = not _in_paged_mode
|
||||
cps = calc_columns_per_screen()
|
||||
if first_layout:
|
||||
handle_rtl_body(body_style)
|
||||
# Check if the current document is a full screen layout like
|
||||
|
@ -2,27 +2,29 @@
|
||||
# License: GPL v3 Copyright: 2016, Kovid Goyal <kovid at kovidgoyal.net>
|
||||
from __python__ import bound_methods, hash_literals
|
||||
|
||||
from ajax import ajax_send
|
||||
from dom import set_css, add_extra_css, build_rule, svgicon
|
||||
from elementmaker import E
|
||||
from gettext import gettext as _
|
||||
from utils import html_escape
|
||||
from session import get_interface_data, get_device_uuid
|
||||
|
||||
from modals import error_dialog, warning_dialog
|
||||
from book_list.globals import get_session_data, main_js, get_translations
|
||||
from ajax import ajax_send
|
||||
from book_list.globals import get_session_data, get_translations, main_js
|
||||
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.resources import load_resources
|
||||
from book_list.theme import get_color, get_font_family
|
||||
from dom import add_extra_css, build_rule, set_css, svgicon
|
||||
from modals import error_dialog, warning_dialog
|
||||
from read_book.content_popup import ContentPopupOverlay
|
||||
from read_book.globals import (
|
||||
current_book, iframe_id, messenger, set_current_spine_item
|
||||
)
|
||||
from read_book.goto import get_next_section
|
||||
from read_book.overlay import Overlay
|
||||
from read_book.search import SearchOverlay, find_in_spine
|
||||
from read_book.prefs.colors import resolve_color_scheme
|
||||
from read_book.prefs.font_size import change_font_size_by
|
||||
from read_book.touch import set_left_margin_handler, set_right_margin_handler
|
||||
from read_book.resources import load_resources
|
||||
from read_book.search import SearchOverlay, find_in_spine
|
||||
from read_book.toc import update_visible_toc_nodes
|
||||
from read_book.goto import get_next_section
|
||||
from book_list.theme import get_color, get_font_family
|
||||
from utils import parse_url_params, username_key, is_ios
|
||||
from read_book.touch import set_left_margin_handler, set_right_margin_handler
|
||||
from session import get_device_uuid, get_interface_data
|
||||
from utils import html_escape, is_ios, parse_url_params, username_key
|
||||
|
||||
LOADING_DOC = '''
|
||||
<!DOCTYPE html>
|
||||
@ -128,6 +130,7 @@ class View:
|
||||
),
|
||||
right_margin,
|
||||
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%; 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
|
||||
)
|
||||
@ -135,6 +138,7 @@ class View:
|
||||
)
|
||||
)
|
||||
self.search_overlay = SearchOverlay(self)
|
||||
self.content_popup_overlay = ContentPopupOverlay(self)
|
||||
self.overlay = Overlay(self)
|
||||
self.processing_spine_item_display = False
|
||||
self.iframe_ready = False
|
||||
@ -155,6 +159,7 @@ class View:
|
||||
'bump_font_size': self.bump_font_size,
|
||||
'find_in_spine': self.on_find_in_spine,
|
||||
'request_size': self.on_request_size,
|
||||
'show_footnote': self.on_show_footnote,
|
||||
'print': self.on_print,
|
||||
}
|
||||
self.currently_showing = {}
|
||||
@ -227,14 +232,25 @@ class View:
|
||||
delta = 2 if data.increase else -2
|
||||
change_font_size_by(delta)
|
||||
|
||||
def on_show_footnote(self, data):
|
||||
self.show_content_popup()
|
||||
self.content_popup_overlay.show_footnote(data)
|
||||
|
||||
def show_chrome(self):
|
||||
self.search_overlay.hide()
|
||||
self.content_popup_overlay.hide()
|
||||
self.overlay.show()
|
||||
|
||||
def show_search(self):
|
||||
self.overlay.hide()
|
||||
self.content_popup_overlay.hide()
|
||||
self.search_overlay.show()
|
||||
|
||||
def show_content_popup(self):
|
||||
self.overlay.hide()
|
||||
self.search_overlay.hide()
|
||||
self.content_popup_overlay.show()
|
||||
|
||||
def set_margins(self):
|
||||
no_margins = self.currently_showing.name is self.book.manifest.title_page_name
|
||||
sd = get_session_data()
|
||||
@ -342,6 +358,7 @@ class View:
|
||||
s.color = ans.foreground # Setting a color for the side margins causes the hover arrow to become visible
|
||||
s.backgroundColor = ans.background
|
||||
m.parentNode.style.backgroundColor = ans.background # this is needed on iOS where the bottom margin has its own margin, so we dont want the body background color to bleed through
|
||||
self.content_popup_overlay.apply_color_scheme(ans.background, ans.foreground)
|
||||
return ans
|
||||
|
||||
def on_resize(self):
|
||||
@ -376,6 +393,7 @@ class View:
|
||||
def display_book(self, book):
|
||||
self.overlay.hide()
|
||||
self.search_overlay.hide()
|
||||
self.content_popup_overlay.hide()
|
||||
self.book = current_book.book = book
|
||||
self.ui.db.update_last_read_time(book)
|
||||
self.loaded_resources = {}
|
||||
@ -479,7 +497,7 @@ class View:
|
||||
|
||||
def on_update_cfi(self, data):
|
||||
overlay_shown = not self.processing_spine_item_display and self.overlay.is_visible
|
||||
if overlay_shown or self.search_overlay.is_visible:
|
||||
if overlay_shown or self.search_overlay.is_visible or self.content_popup_overlay.is_visible:
|
||||
# Chrome on Android stupidly resizes the viewport when the on
|
||||
# screen keyboard is displayed. This means that the push_state()
|
||||
# below causes the overlay to be closed, making it impossible to
|
||||
|
Loading…
x
Reference in New Issue
Block a user