E-book viewer: Redesign the reference mode to also work on touch screens without a mouse. Now in reference mode paragraph numbers are displayed for all paragraphs

This commit is contained in:
Kovid Goyal 2021-01-26 09:46:18 +05:30
parent 40b355478e
commit da53430e77
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
5 changed files with 25 additions and 54 deletions

View File

@ -93,7 +93,7 @@ Reference mode
calibre also has a very handy :guilabel:`Reference mode`. You can turn it on calibre also has a very handy :guilabel:`Reference mode`. You can turn it on
by clicking the :guilabel:`Reference mode` button in the viewer controls. Once by clicking the :guilabel:`Reference mode` button in the viewer controls. Once
you do this, every mouse over a paragraph, calibre will display a unique number you do this, every paragraph will have a unique number displayed at the start,
made up of the section and paragraph numbers. made up of the section and paragraph numbers.
You can use this number to unambiguously refer to parts of the books when You can use this number to unambiguously refer to parts of the books when

View File

@ -750,9 +750,6 @@ class IframeBoss:
else: else:
self.send_message('search_result_not_found', search_result=data.search_result) self.send_message('search_result_not_found', search_result=data.search_result)
def reference_item_changed(self, ref_num_or_none):
self.send_message('reference_item_changed', refnum=ref_num_or_none, index=current_spine_item().index)
def set_reference_mode(self, data): def set_reference_mode(self, data):
self.reference_mode_enabled = data.enabled self.reference_mode_enabled = data.enabled
if data.enabled: if data.enabled:

View File

@ -3,39 +3,19 @@
# noqa: eol-semicolon # noqa: eol-semicolon
from __python__ import bound_methods, hash_literals from __python__ import bound_methods, hash_literals
from read_book.globals import get_boss from read_book.globals import current_spine_item
def elem_for_ref(refnum): def elem_for_ref(refnum):
refnum = int(refnum) refnum = int(refnum)
p = document.getElementsByTagName('p')[refnum - 1] return document.getElementsByTagName('p')[refnum - 1]
return p
def on_mouse_over(ev):
p = this
if p.dataset.calibreRefNum:
refnum = int(p.dataset.calibreRefNum)
get_boss().reference_item_changed(refnum)
def on_mouse_out(ev):
get_boss().reference_item_changed(None)
def start_reference_mode(): def start_reference_mode():
i = 0 si = current_spine_item().index
for p in document.getElementsByTagName('p'): for i, p in enumerate(document.getElementsByTagName('p')):
i += 1 p.dataset.calibreRefNum = f'{si}.{i + 1}'
if not p.dataset.calibreRefNum: document.body.classList.add('calibre-reference-mode')
p.dataset.calibreRefNum = i + ''
p.addEventListener('mouseover', on_mouse_over, {'passive': True})
p.addEventListener('mouseout', on_mouse_out, {'passive': True})
def end_reference_mode(): def end_reference_mode():
for p in document.getElementsByTagName('p'): document.body.classList.remove('calibre-reference-mode')
if p.dataset.calibreRefNum:
p.removeEventListener('mouseover', on_mouse_over, {'passive': True})
p.removeEventListener('mouseout', on_mouse_out, {'passive': True})
v'delete p.dataset.calibreRefNum'

View File

@ -111,6 +111,23 @@ def apply_colors(is_content_popup):
} }
''' '''
# reference mode hint box
text += f'''\n\n
.calibre-reference-mode [data-calibre-ref-num]::before {{
content: attr(data-calibre-ref-num) !important;\
display: inline-block !important;\
position: absolute !important;\
text-indent: 0 !important;\
text-decoration: none !important;\
font-weight: bold !important;\
color: {selfg} !important;\
background: {selbg} !important;\
cursor: default !important;\
padding: 1px !important;\
border: solid 1px {opts.color_scheme.foreground} !important;\
}}
'''
# follow links hint box # follow links hint box
text += f'''\n\n text += f'''\n\n
.calibre-hint-visible::before {{ .calibre-hint-visible::before {{

View File

@ -254,11 +254,6 @@ class View:
E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='controls-help-overlay'), # controls help overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='controls-help-overlay'), # controls help overlay
) )
), ),
E.div(
style=f'color: {get_color("window-foreground")}; background: {get_color("window-background")};' +
'position: absolute; display: none; left: 0; top: 0; padding: 0.5ex; border: solid 2px; z-index: 3000',
id='reference-mode-overlay'
),
), ),
) )
handlers = { handlers = {
@ -280,7 +275,6 @@ class View:
'next_spine_item': self.on_next_spine_item, 'next_spine_item': self.on_next_spine_item,
'print': self.on_print, 'print': self.on_print,
'ready': self.on_iframe_ready, 'ready': self.on_iframe_ready,
'reference_item_changed': self.on_reference_item_changed,
'report_cfi': self.on_report_cfi, 'report_cfi': self.on_report_cfi,
'request_size': self.on_request_size, 'request_size': self.on_request_size,
'scroll_to_anchor': self.on_scroll_to_anchor, 'scroll_to_anchor': self.on_scroll_to_anchor,
@ -333,10 +327,6 @@ class View:
def iframe(self): def iframe(self):
return self.iframe_wrapper.iframe return self.iframe_wrapper.iframe
@property
def reference_mode_overlay(self):
return document.getElementById('reference-mode-overlay')
def copy_to_clipboard(self): def copy_to_clipboard(self):
self.iframe_wrapper.send_message('copy_selection') self.iframe_wrapper.send_message('copy_selection')
@ -694,7 +684,6 @@ class View:
self.overlay.hide() self.overlay.hide()
self.search_overlay.hide() self.search_overlay.hide()
self.content_popup_overlay.hide() self.content_popup_overlay.hide()
self.reference_mode_overlay.style.display = 'none'
self.focus_iframe() self.focus_iframe()
def focus_iframe(self): def focus_iframe(self):
@ -1337,7 +1326,6 @@ class View:
self.hide_loading() self.hide_loading()
self.set_progress_frac(data.progress_frac, data.file_progress_frac, data.page_counts) self.set_progress_frac(data.progress_frac, data.file_progress_frac, data.page_counts)
self.update_header_footer() self.update_header_footer()
self.on_reference_item_changed()
window.scrollTo(0, 0) # ensure window is at 0 on mobile where the navbar causes issues window.scrollTo(0, 0) # ensure window is at 0 on mobile where the navbar causes issues
if self.book_load_started: if self.book_load_started:
self.book_load_started = False self.book_load_started = False
@ -1369,21 +1357,10 @@ class View:
def toggle_reference_mode(self): def toggle_reference_mode(self):
self.reference_mode_enabled = not self.reference_mode_enabled self.reference_mode_enabled = not self.reference_mode_enabled
self.on_reference_item_changed()
self.iframe_wrapper.send_message('set_reference_mode', enabled=self.reference_mode_enabled) self.iframe_wrapper.send_message('set_reference_mode', enabled=self.reference_mode_enabled)
if ui_operations.reference_mode_changed: if ui_operations.reference_mode_changed:
ui_operations.reference_mode_changed(self.reference_mode_enabled) ui_operations.reference_mode_changed(self.reference_mode_enabled)
def on_reference_item_changed(self, data):
data = data or {'refnum': None, 'index': None}
refnum, index = data.refnum, data.index
div = self.reference_mode_overlay
if refnum is None:
div.style.display = 'none'
else:
div.style.display = 'block'
div.textContent = f'{index}.{refnum}'
def show_search_result(self, sr): def show_search_result(self, sr):
if self.currently_showing.name is sr.file_name: if self.currently_showing.name is sr.file_name:
self.iframe_wrapper.send_message('show_search_result', search_result=sr) self.iframe_wrapper.send_message('show_search_result', search_result=sr)