Wire up the hints overlay

This commit is contained in:
Kovid Goyal 2020-12-15 14:12:37 +05:30
parent 99dedc4ac3
commit b4731c552c
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 90 additions and 5 deletions

View File

@ -3,6 +3,53 @@
from __python__ import bound_methods, hash_literals
class Hints:
def __init__(self, view):
self.view = view
container = self.container
container.setAttribute('tabindex', '0')
container.style.overflow = 'hidden'
container.addEventListener('keydown', self.on_keydown, {'passive': False})
container.addEventListener('click', self.container_clicked, {'passive': False})
@property
def container(self):
return document.getElementById('book-hints-overlay')
@property
def is_visible(self):
return self.container.style.display is not 'none'
def focus(self):
self.container.focus()
def hide(self):
if self.is_visible:
self.container.style.display = 'none'
self.send_message('hide')
def show(self):
if not self.is_visible:
self.container.style.display = 'block'
self.focus()
self.send_message('show')
def on_keydown(self, ev):
ev.preventDefault(), ev.stopPropagation()
def container_clicked(self, ev):
ev.stopPropagation(), ev.preventDefault()
self.hide()
def send_message(self, type, **kw):
self.view.iframe_wrapper.send_message('hints', type=type, **kw)
def handle_message(self, msg):
if msg.type is 'shown':
self.hints_map = msg.hints_map
def is_visible(a):
if not a.offsetParent:
return False

View File

@ -11,6 +11,7 @@ from range_utils import (
last_span_for_crw, reset_highlight_counter, select_crw, unwrap_all_crw,
unwrap_crw, wrap_text_in_range
)
from read_book.hints import hint_visible_links, unhint_links
from read_book.cfi import cfi_for_selection, range_from_cfi
from read_book.extract import get_elements
from read_book.find import (
@ -148,6 +149,7 @@ class IframeBoss:
'handle_navigation_shortcut': self.on_handle_navigation_shortcut,
'annotations': self.annotations_msg_received,
'tts': self.tts_msg_received,
'hints': self.hints_msg_received,
'copy_selection': self.copy_selection,
'replace_highlights': self.replace_highlights,
'clear_selection': def(): window.getSelection().removeAllRanges();,
@ -228,6 +230,7 @@ class IframeBoss:
set_toc_anchor_map()
self.replace_history_on_next_cfi_update = True
self.book = current_book.book = data.book
self.link_attr = 'data-' + self.book.manifest.link_uid
self.reference_mode_enabled = data.reference_mode_enabled
self.is_titlepage = data.is_titlepage
spine = self.book.manifest.spine
@ -650,9 +653,9 @@ class IframeBoss:
def send_message(self, action, **data):
self.comm.send_message(action, data)
def connect_links(self):
link_attr = 'data-' + self.book.manifest.link_uid
for a in document.body.querySelectorAll(f'a[{link_attr}]'):
for a in document.body.querySelectorAll(f'a[{self.link_attr}]'):
a.addEventListener('click', self.link_activated)
if runtime.is_standalone_viewer:
# links with a target get turned into requests to open a new window by Qt
@ -669,11 +672,10 @@ class IframeBoss:
self.send_message('view_image', calibre_src=img.dataset.calibreSrc)
def link_activated(self, evt):
link_attr = 'data-' + self.book.manifest.link_uid
try:
data = JSON.parse(evt.currentTarget.getAttribute(link_attr))
data = JSON.parse(evt.currentTarget.getAttribute(self.link_attr))
except:
print('WARNING: Failed to parse link data {}, ignoring'.format(evt.currentTarget?.getAttribute?(link_attr)))
print('WARNING: Failed to parse link data {}, ignoring'.format(evt.currentTarget?.getAttribute?(self.link_attr)))
return
name, frag = data.name, data.frag
if not name:
@ -917,5 +919,15 @@ class IframeBoss:
if select_tts_mark(occurrence_number):
self.ensure_selection_visible()
def hints_msg_received(self, data):
if data.type is 'show':
# clear selection so that it does not confuse with the hints which use the same colors
window.getSelection().removeAllRanges()
hints_map = hint_visible_links(self.link_attr)
self.send_message('hints', type='shown', hints_map=hints_map)
elif data.type is 'hide':
unhint_links(self.link_attr)
def main():
main.boss = IframeBoss()

View File

@ -194,6 +194,12 @@ def shortcuts_definition():
_('Read aloud')
),
'toggle_hints': desc(
'Alt+f',
'ui',
_('Follow links with the keyboard')
),
'copy_to_clipboard': desc(
v"['Ctrl+c', 'Meta+c']",
'ui',

View File

@ -35,6 +35,7 @@ from read_book.scrollbar import BookScrollbar
from read_book.search import SearchOverlay, find_in_spine
from read_book.selection_bar import SelectionBar
from read_book.read_aloud import ReadAloud
from read_book.hints import Hints
from read_book.shortcuts import create_shortcut_map
from read_book.timers import Timers
from read_book.toc import get_current_toc_nodes, update_visible_toc_nodes
@ -245,6 +246,7 @@ class View:
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
@ -317,6 +319,7 @@ class View:
self.overlay = Overlay(self)
self.selection_bar = SelectionBar(self)
self.read_aloud = ReadAloud(self)
self.hints = Hints(self)
self.processing_spine_item_display = False
self.pending_load = None
self.currently_showing = {'selection': {'empty': True}}
@ -349,6 +352,9 @@ class View:
def on_tts_message(self, data):
self.read_aloud.handle_message(data)
def on_hints_message(self, data):
self.hints.handle_message(data)
def left_margin_clicked(self, event):
if event.button is 0:
event.preventDefault(), event.stopPropagation()
@ -452,6 +458,7 @@ class View:
if visible:
self.selection_bar.hide()
self.read_aloud.hide()
self.hints.hide()
else:
self.selection_bar.update_position()
@ -507,6 +514,8 @@ class View:
self.toggle_reference_mode()
elif data.name is 'read_aloud':
self.start_read_aloud()
elif data.name is 'toggle_hints':
self.toggle_hints()
elif data.name is 'toggle_read_aloud':
self.toggle_read_aloud()
elif data.name is 'reload_book':
@ -673,11 +682,14 @@ class View:
self.selection_bar.focus()
elif self.read_aloud.is_visible:
self.read_aloud.focus()
elif self.hints.is_visible:
self.hints.focus()
else:
self.iframe.contentWindow.focus()
def start_read_aloud(self, dont_start_talking):
self.selection_bar.hide()
self.hints.hide()
self.read_aloud.show()
if not dont_start_talking:
self.read_aloud.play()
@ -688,6 +700,14 @@ class View:
else:
self.start_read_aloud()
def toggle_hints(self):
if self.hints.is_visible:
self.hints.hide()
else:
self.selection_bar.hide()
self.read_aloud.hide()
self.hints.show()
def show_chrome(self, data):
elements = {}
if data and data.elements: