diff --git a/src/pyj/read_book/annotations.pyj b/src/pyj/read_book/annotations.pyj index 1ff5c40917..baed12a360 100644 --- a/src/pyj/read_book/annotations.pyj +++ b/src/pyj/read_book/annotations.pyj @@ -3,6 +3,7 @@ from __python__ import bound_methods, hash_literals from read_book.cfi import create_cfi_cmp, cfi_sort_key +from read_book.globals import ui_operations no_cfi = '/99999999' @@ -93,3 +94,118 @@ def merge_annotation_maps(a, b): updated = True return updated, ans + + + +class AnnotationsManager: # {{{ + + def __init__(self, view): + self.view = view + self.set_highlights() + + def set_highlights(self, highlights): + highlights = highlights or v'[]' + self.highlights = {h.uuid: h for h in highlights} + + def merge_highlights(self, highlights): + highlights = highlights or v'[]' + updated = False + if highlights.length: + base = {'highlight': Object.values(self.highlights)} + newvals = {'highlight': highlights} + updated, ans = merge_annotation_maps(base, newvals) + if updated: + self.set_highlights(ans.highlight) + return updated + + def remove_highlight(self, uuid): + h = self.highlights[uuid] + if h: + h.timestamp = Date().toISOString() + h.removed = True + v'delete h.style' + v'delete h.highlighted_text' + v'delete h.start_cfi' + v'delete h.end_cfi' + v'delete h.notes' + v'delete h.spine_name' + v'delete h.spine_index' + return True + + def delete_highlight(self, uuid): + if self.remove_highlight(uuid): + if ui_operations.highlights_changed: + ui_operations.highlights_changed(Object.values(self.highlights)) + + def notes_for_highlight(self, uuid): + h = self.highlights[uuid] if uuid else None + if h: + return h.notes + + def set_notes_for_highlight(self, uuid, notes): + h = self.highlights[uuid] + if h: + if notes: + h.notes = notes + else: + v'delete h.notes' + if ui_operations.highlights_changed: + ui_operations.highlights_changed(Object.values(self.highlights)) + return True + return False + + def style_for_highlight(self, uuid): + h = self.highlights[uuid] + if h: + return h.style + + def data_for_highlight(self, uuid): + return self.highlights[uuid] + + def spine_index_for_highlight(self, uuid, spine): + h = self.highlights[uuid] + if not h: + return -1 + ans = h.spine_index + name = h.spine_name + if name: + idx = spine.indexOf(name) + if idx > -1: + ans = idx + return ans + + def cfi_for_highlight(self, uuid, spine_index): + h = self.highlights[uuid] + if h: + x = 2 * (spine_index + 1) + return f'epubcfi(/{x}{h.start_cfi})' + + def add_highlight(self, msg, style, notes): + now = Date().toISOString() + for uuid in msg.removed_highlights: + self.remove_highlight(uuid) + + annot = self.highlights[msg.uuid] = { + 'type': 'highlight', + 'timestamp': now, + 'uuid': msg.uuid, + 'highlighted_text': msg.highlighted_text, + 'start_cfi': msg.bounds.start, + 'end_cfi': msg.bounds.end, + 'style': style, # dict with color and background-color + 'spine_name': self.view.currently_showing.name, + 'spine_index': self.view.currently_showing.spine_index, + } + if notes: + annot.notes = notes + if ui_operations.highlights_changed: + ui_operations.highlights_changed(Object.values(self.highlights)) + + def highlights_for_currently_showing(self): + name = self.view.currently_showing.name + ans = v'[]' + for h in Object.values(self.highlights): + if h.spine_name is name and not h.removed and h.start_cfi: + ans.push(h) + return ans +# }}} diff --git a/src/pyj/read_book/create_annotation.pyj b/src/pyj/read_book/create_annotation.pyj index bd51a10be0..b2acc425c6 100644 --- a/src/pyj/read_book/create_annotation.pyj +++ b/src/pyj/read_book/create_annotation.pyj @@ -10,126 +10,11 @@ from book_list.globals import get_session_data from book_list.theme import cached_color_to_rgba, get_color from dom import clear, ensure_id, svgicon, unique_id from modals import error_dialog, question_dialog -from read_book.annotations import merge_annotation_maps from read_book.globals import ui_operations from read_book.shortcuts import shortcut_for_key_event from widgets import create_button -class AnnotationsManager: # {{{ - - def __init__(self, view): - self.view = view - self.set_highlights() - - def set_highlights(self, highlights): - highlights = highlights or v'[]' - self.highlights = {h.uuid: h for h in highlights} - - def merge_highlights(self, highlights): - highlights = highlights or v'[]' - updated = False - if highlights.length: - base = {'highlight': Object.values(self.highlights)} - newvals = {'highlight': highlights} - updated, ans = merge_annotation_maps(base, newvals) - if updated: - self.set_highlights(ans.highlight) - return updated - - def remove_highlight(self, uuid): - h = self.highlights[uuid] - if h: - h.timestamp = Date().toISOString() - h.removed = True - v'delete h.style' - v'delete h.highlighted_text' - v'delete h.start_cfi' - v'delete h.end_cfi' - v'delete h.notes' - v'delete h.spine_name' - v'delete h.spine_index' - return True - - def delete_highlight(self, uuid): - if self.remove_highlight(uuid): - if ui_operations.highlights_changed: - ui_operations.highlights_changed(Object.values(self.highlights)) - - def notes_for_highlight(self, uuid): - h = self.highlights[uuid] if uuid else None - if h: - return h.notes - - def set_notes_for_highlight(self, uuid, notes): - h = self.highlights[uuid] - if h: - if notes: - h.notes = notes - else: - v'delete h.notes' - if ui_operations.highlights_changed: - ui_operations.highlights_changed(Object.values(self.highlights)) - return True - return False - - def style_for_highlight(self, uuid): - h = self.highlights[uuid] - if h: - return h.style - - def data_for_highlight(self, uuid): - return self.highlights[uuid] - - def spine_index_for_highlight(self, uuid, spine): - h = self.highlights[uuid] - if not h: - return -1 - ans = h.spine_index - name = h.spine_name - if name: - idx = spine.indexOf(name) - if idx > -1: - ans = idx - return ans - - def cfi_for_highlight(self, uuid, spine_index): - h = self.highlights[uuid] - if h: - x = 2 * (spine_index + 1) - return f'epubcfi(/{x}{h.start_cfi})' - - def add_highlight(self, msg, style, notes): - now = Date().toISOString() - for uuid in msg.removed_highlights: - self.remove_highlight(uuid) - - annot = self.highlights[msg.uuid] = { - 'type': 'highlight', - 'timestamp': now, - 'uuid': msg.uuid, - 'highlighted_text': msg.highlighted_text, - 'start_cfi': msg.bounds.start, - 'end_cfi': msg.bounds.end, - 'style': style, # dict with color and background-color - 'spine_name': self.view.currently_showing.name, - 'spine_index': self.view.currently_showing.spine_index, - } - if notes: - annot.notes = notes - if ui_operations.highlights_changed: - ui_operations.highlights_changed(Object.values(self.highlights)) - - def highlights_for_currently_showing(self): - name = self.view.currently_showing.name - ans = v'[]' - for h in Object.values(self.highlights): - if h.spine_name is name and not h.removed and h.start_cfi: - ans.push(h) - return ans -# }}} - - WAITING_FOR_CLICK = 1 WAITING_FOR_DRAG = 2 DRAGGING_LEFT = 3 diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index ee097d529e..803219207a 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -12,8 +12,9 @@ from book_list.theme import cached_color_to_rgba, get_color from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id from iframe_comm import IframeWrapper from modals import error_dialog, warning_dialog +from read_book.annotations import AnnotationsManager from read_book.content_popup import ContentPopupOverlay -from read_book.create_annotation import AnnotationsManager, CreateAnnotation +from read_book.create_annotation import CreateAnnotation from read_book.globals import ( current_book, rtl_page_progression, runtime, set_current_spine_item, ui_operations