More accurate detection of current ToC section when highlighting

This commit is contained in:
Kovid Goyal 2020-09-13 16:02:41 +05:30
parent 28ef780d99
commit c363d790ab
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
3 changed files with 75 additions and 25 deletions

View File

@ -57,7 +57,7 @@ from read_book.settings import (
from read_book.shortcuts import (
create_shortcut_map, keyevent_as_shortcut, shortcut_for_key_event
)
from read_book.toc import update_visible_toc_anchors
from read_book.toc import update_visible_toc_anchors, find_anchor_before_range
from read_book.touch import (
create_handlers as create_touch_handlers, reset_handlers as reset_touch_handlers
)
@ -793,9 +793,10 @@ class IframeBoss:
sel.removeAllRanges()
elif dtype is 'apply-highlight':
sel = window.getSelection()
text = sel.toString()
if not sel.rangeCount:
return
anchor_before = find_anchor_before_range(sel.getRangeAt(0), self.book.manifest.toc_anchor_map, self.anchor_funcs)
text = sel.toString()
bounds = cfi_for_selection()
style = highlight_style_as_css(data.style, opts.is_dark_theme, opts.color_scheme.foreground)
cls = 'crw-has-dot' if data.has_notes else None
@ -824,6 +825,7 @@ class IframeBoss:
bounds=bounds,
removed_highlights=removed_highlights,
highlighted_text=text,
anchor_before=anchor_before
)
reset_find_caches()
else:

View File

@ -15,6 +15,7 @@ from read_book.highlights import (
ICON_SIZE, EditNotesAndColors, HighlightStyle, all_styles, render_notes
)
from read_book.shortcuts import shortcut_for_key_event
from read_book.toc import get_toc_nodes_bordering_spine_item, family_for_toc_node
DRAG_SCROLL_ZONE_MIN_HEIGHT = 10
BUTTON_MARGIN = '0.5rem'
@ -965,8 +966,15 @@ class SelectionBar:
_('Highlighting failed'),
_('Failed to apply highlighting, try adjusting extent of highlight')
)
toc_family = v'[]'
if msg.anchor_before:
toc_family = family_for_toc_node(msg.anchor_before.id)
else:
before = get_toc_nodes_bordering_spine_item()[0]
if before:
toc_family = family_for_toc_node(before.id)
self.annotations_manager.add_highlight(
msg, self.current_highlight_style.style, notes, self.view.current_toc_family)
msg, self.current_highlight_style.style, notes, toc_family)
elif msg.type is 'edit-highlight':
if self.state is WAITING:
self.create_highlight()

View File

@ -24,28 +24,20 @@ def iter_toc_descendants(node, callback):
iter_toc_descendants(child, callback)
def get_border_nodes(toc, id_map):
data = update_visible_toc_nodes.data
before, after = data.before, data.after
if before:
before = id_map[before]
if after:
after = id_map[after]
if before and after:
# Both border nodes are in the current spine item
return before, after
def get_toc_nodes_bordering_spine_item(toc, csi):
# Find the ToC entries that point to the closest files on either side of the
# current spine item
# spine item
toc = toc or current_book().manifest.toc
csi = csi or current_spine_item()
spine = current_book().manifest.spine
spine_before, spine_after = {}, {}
which = spine_before
csi = current_spine_item()
before = after = prev = None
for name in spine:
if name is csi:
which = spine_after
else:
which[name] = True
prev = None
iter_toc_descendants(toc, def(node):
nonlocal prev, before, after
if node.dest:
@ -63,6 +55,37 @@ def get_border_nodes(toc, id_map):
return before, after
def get_border_nodes(toc, id_map):
data = update_visible_toc_nodes.data
before, after = data.before, data.after
if before:
before = id_map[before]
if after:
after = id_map[after]
if before and after:
# Both border nodes are in the current spine item
return before, after
sb, sa = get_toc_nodes_bordering_spine_item(toc)
before = before or sb
after = after or sa
return before, after
def family_for_toc_node(toc_node_id, parent_map, id_map):
if not id_map or not parent_map:
toc = current_book().manifest.toc
parent_map, id_map = get_toc_maps(toc)
family = v'[]'
node = id_map[toc_node_id]
while node and node.title:
family.unshift(node)
parent = parent_map[node.id]
node = None
if parent:
node = id_map[parent.id]
return family
def get_current_toc_nodes():
toc = current_book().manifest.toc
parent_map, id_map = get_toc_maps(toc)
@ -78,16 +101,9 @@ def get_current_toc_nodes():
if before:
ans[before.id] = True
ans = Object.keys(ans)
family = v'[]'
if ans.length:
node = id_map[ans[0]]
while node and node.title:
family.unshift(node)
parent = parent_map[node.id]
node = None
if parent:
node = id_map[parent.id]
return family
return family_for_toc_node(ans[0], parent_map, id_map)
return v'[]'
def get_highlighted_toc_nodes(toc, parent_map, id_map):
@ -207,3 +223,27 @@ def update_visible_toc_anchors(toc_anchor_map, anchor_funcs):
break
return {'visible_anchors':visible_anchors, 'has_visible':has_visible, 'before':before, 'after':after, 'sorted_anchors':tam.sorted_anchors}
def find_anchor_before_range(r, toc_anchor_map, anchor_funcs):
name = current_spine_item().name
prev_anchor = None
tam = current_toc_anchor_map(toc_anchor_map, anchor_funcs)
anchors = toc_anchor_map[name]
if anchors:
amap = {x.id: x for x in anchors}
for anchor_id in tam.sorted_anchors:
anchor = amap[anchor_id]
is_before = True
if anchor.frag:
elem = document.getElementById(anchor.frag)
if elem:
q = document.createRange()
q.selectNode(elem)
if q.compareBoundaryPoints(window.Range.START_TO_START, r) > 0:
is_before = False
if is_before:
prev_anchor = anchor
else:
break
return prev_anchor