mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
More accurate detection of current ToC section when highlighting
This commit is contained in:
parent
28ef780d99
commit
c363d790ab
@ -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:
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user