From 5d9515c11588bdcb15ce46b4a5da2893f89e092f Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 24 Mar 2020 13:51:32 +0530 Subject: [PATCH] Implementation of marking selection using spans --- src/pyj/range_utils.pyj | 11 ++++++++--- src/pyj/read_book/create_annotation.pyj | 22 ++++++++++++++++++++-- src/pyj/read_book/iframe.pyj | 10 ++++++++++ 3 files changed, 38 insertions(+), 5 deletions(-) diff --git a/src/pyj/range_utils.pyj b/src/pyj/range_utils.pyj index a2b118bbec..2187d6a95f 100644 --- a/src/pyj/range_utils.pyj +++ b/src/pyj/range_utils.pyj @@ -75,7 +75,7 @@ def create_wrapper_function(wrapper_elem, r): current_range.setStart(node, start_offset) start_node = current_wrapper start_offset = 0 - elif node is end_node and end_node.nodeType is Node.TEXT_NODE: + if node is end_node and end_node.nodeType is Node.TEXT_NODE: current_range.setEnd(node, end_offset) end_node = current_wrapper end_offset = 1 @@ -89,7 +89,7 @@ def create_wrapper_function(wrapper_elem, r): wrapper_counter = 0 -def wrap_text_in_range(r, style): +def wrap_text_in_range(style, r): if not r: r = window.getSelection().getRangeAt(0) if r.isCollapsed: @@ -101,6 +101,11 @@ def wrap_text_in_range(r, style): wrapper_elem.setAttribute('style', style) wrap_node = create_wrapper_function(wrapper_elem, r) - nodes = get_text_nodes(r) + nodes = text_nodes_in_range(r) nodes = nodes.map(wrap_node) return wrapper_elem.dataset.calibreRangeWrapper + + +def reset_highlight_counter(): + nonlocal wrapper_counter + wrapper_counter = 0 diff --git a/src/pyj/read_book/create_annotation.pyj b/src/pyj/read_book/create_annotation.pyj index b6c372d47a..9d813d56f7 100644 --- a/src/pyj/read_book/create_annotation.pyj +++ b/src/pyj/read_book/create_annotation.pyj @@ -4,10 +4,12 @@ from __python__ import bound_methods, hash_literals from elementmaker import E from gettext import gettext as _ +from uuid import short_uuid from book_list.globals import get_session_data -from book_list.theme import get_color, cached_color_to_rgba +from book_list.theme import cached_color_to_rgba, get_color from dom import add_extra_css, clear, ensure_id, svgicon, unique_id +from modals import error_dialog from read_book.shortcuts import shortcut_for_key_event WAITING_FOR_CLICK = 1 @@ -241,10 +243,19 @@ class CreateAnnotation: h.style.display = h.dataset.savedState def accept(self): - self.send_message('apply-highlight', style=self.current_highlight_style) + s = self.current_highlight_style + style = '' + for k in Object.keys(self.current_highlight_style): + style += f'{k}: {s[k]}; ' + self.send_message( + 'apply-highlight', style=style, uuid=short_uuid() + ) + self.hide() def on_keydown(self, ev): ev.stopPropagation(), ev.preventDefault() + if ev.key is 'Enter': + return self.accept() sc_name = shortcut_for_key_event(ev, self.view.keyboard_shortcut_map) if sc_name is 'show_chrome': self.hide() @@ -366,6 +377,13 @@ class CreateAnnotation: self.place_handles(msg.extents) elif msg.type is 'update-handles': self.place_handles(msg.extents) + elif msg.type is 'highlight-applied': + if not msg.ok: + return error_dialog( + _('Highlighting failed'), + _('Failed to apply highlighting, try adjusting extent of highlight') + ) + else: print('Ignoring annotations message with unknown type:', msg.type) diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index 0f7a627c9b..b1d8adae95 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -11,6 +11,7 @@ from select import ( from fs_images import fix_fullscreen_svg_images from iframe_comm import IframeClient +from range_utils import reset_highlight_counter, wrap_text_in_range from read_book.cfi import scroll_to as scroll_to_cfi from read_book.extract import get_elements from read_book.find import reset_find_caches, select_search_result @@ -99,6 +100,7 @@ class IframeBoss: self.reference_mode_enabled = False self.replace_history_on_next_cfi_update = True self.blob_url_map = {} + self.annot_id_uuid_map = {} self.content_ready = False self.last_window_width = self.last_window_height = -1 self.forward_keypresses = False @@ -193,6 +195,8 @@ class IframeBoss: def display(self, data): self.length_before = None self.content_ready = False + self.annot_id_uuid_map = {} + reset_highlight_counter() self.replace_history_on_next_cfi_update = True self.book = current_book.book = data.book self.reference_mode_enabled = data.reference_mode_enabled @@ -637,6 +641,12 @@ class IframeBoss: self.send_message('annotations', type='update-handles', extents=selection_extents(in_flow_mode)) elif data.type is 'set-highlight-style': set_selection_style(data.style) + elif data.type is 'apply-highlight': + annot_id = wrap_text_in_range(data.style) + if annot_id is not None: + window.getSelection().removeAllRanges() + self.annot_id_uuid_map[annot_id] = data.uuid + self.send_message('annotations', type='highlight-applied', uuid=data.uuid, ok=annot_id is not None) else: console.log('Ignoring annotations message to iframe with unknown type: ' + data.type)