Implement header bar for footnote popup

This commit is contained in:
Kovid Goyal 2017-10-15 11:27:40 +05:30
parent c2f050ed2a
commit f4a6f0117d
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 143 additions and 24 deletions

View 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

View File

@ -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)

View File

@ -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

View File

@ -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