From 1d950c40e2fa18858f7afea014d78d6c804bfd46 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Mon, 16 Mar 2020 14:03:22 +0530 Subject: [PATCH] Start work on UI for creating annotations --- src/calibre/gui2/viewer/web_view.py | 4 ++- src/pyj/read_book/create_annotation.pyj | 34 +++++++++++++++++++++++++ src/pyj/read_book/globals.pyj | 1 + src/pyj/read_book/iframe.pyj | 2 ++ src/pyj/read_book/shortcuts.pyj | 9 +++++++ src/pyj/read_book/view.pyj | 7 +++++ 6 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/pyj/read_book/create_annotation.pyj diff --git a/src/calibre/gui2/viewer/web_view.py b/src/calibre/gui2/viewer/web_view.py index e5830a4159..720b6888dd 100644 --- a/src/calibre/gui2/viewer/web_view.py +++ b/src/calibre/gui2/viewer/web_view.py @@ -34,7 +34,7 @@ from calibre.srv.code import get_translations_data from calibre.utils.config import JSONConfig from calibre.utils.serialize import json_loads from calibre.utils.shared_file import share_open -from polyglot.builtins import as_bytes, iteritems, unicode_type +from polyglot.builtins import as_bytes, hasenv, iteritems, unicode_type try: from PyQt5 import sip @@ -219,6 +219,8 @@ def create_profile(): # DO NOT change the user agent as it is used to workaround # Qt bugs see workaround_qt_bug() in ajax.pyj ua = 'calibre-viewer {} {}'.format(__version__, osname) + if hasenv('CALIBRE_ENABLE_DEVELOP_MODE'): + ua += ' CALIBRE_ENABLE_DEVELOP_MODE' ans.setHttpUserAgent(ua) if is_running_from_develop: from calibre.utils.rapydscript import compile_viewer diff --git a/src/pyj/read_book/create_annotation.pyj b/src/pyj/read_book/create_annotation.pyj new file mode 100644 index 0000000000..69a7cc8f84 --- /dev/null +++ b/src/pyj/read_book/create_annotation.pyj @@ -0,0 +1,34 @@ +# vim:fileencoding=utf-8 +# License: GPL v3 Copyright: 2020, Kovid Goyal +from __python__ import bound_methods, hash_literals + + +class CreateAnnotation: + + container_id = 'create-annotation-overlay' + + def __init__(self, view): + self.view = view + + @property + def container(self): + return document.getElementById(self.container_id) + + @property + def is_visible(self): + return self.container.style.display is not 'none' + + def show(self): + self.container.style.display = 'block' + + def hide(self): + self.container.style.display = 'none' + + def send_message(self, **kw): + self.view.iframe_wrapper.send_message('annotations', **kw) + + def handle_message(self, msg): + if msg.type is 'create-annotation': + self.show() + else: + print('Ignoring annotations message with unknown type:', msg.type) diff --git a/src/pyj/read_book/globals.pyj b/src/pyj/read_book/globals.pyj index 27d6b4a18b..b88783c600 100644 --- a/src/pyj/read_book/globals.pyj +++ b/src/pyj/read_book/globals.pyj @@ -79,6 +79,7 @@ register_callback(def(): runtime = { 'is_standalone_viewer': False, 'viewer_in_full_screen': False, + 'in_develop_mode': window.navigator.userAgent.indexOf('CALIBRE_ENABLE_DEVELOP_MODE') > 0, } diff --git a/src/pyj/read_book/iframe.pyj b/src/pyj/read_book/iframe.pyj index cf4d256249..3adcace5d3 100644 --- a/src/pyj/read_book/iframe.pyj +++ b/src/pyj/read_book/iframe.pyj @@ -494,6 +494,8 @@ class IframeBoss: if sc_name: if self.handle_navigation_shortcut(sc_name, evt): evt.preventDefault() + elif sc_name is 'create_annotation': + self.send_message('annotations', type='create-annotation') else: self.send_message('handle_shortcut', name=sc_name) diff --git a/src/pyj/read_book/shortcuts.pyj b/src/pyj/read_book/shortcuts.pyj index fdc6c93c28..ddbc8ad898 100644 --- a/src/pyj/read_book/shortcuts.pyj +++ b/src/pyj/read_book/shortcuts.pyj @@ -4,6 +4,8 @@ from __python__ import bound_methods, hash_literals from gettext import gettext as _ +from read_book.globals import runtime + def parse_key_repr(sc): parts = sc.split('+') @@ -382,6 +384,13 @@ def add_standalone_viewer_shortcuts(): _('Toggle the toolbar'), ) + if runtime.in_develop_mode: + sc['create_annotation'] = desc( + "a", + 'ui', + _('Create a highlight'), + ) + def create_shortcut_map(custom_shortcuts): ans = {} diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index fe306e30ef..d234ba87f3 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -18,6 +18,7 @@ from read_book.globals import ( ) from read_book.goto import get_next_section from read_book.open_book import add_book_to_recently_viewed +from read_book.create_annotation import CreateAnnotation from read_book.overlay import Overlay from read_book.prefs.colors import resolve_color_scheme from read_book.prefs.font_size import change_font_size_by @@ -218,6 +219,7 @@ class View: E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id='book-content-popup-overlay'), # content popup overlay E.div(style='position: absolute; top:0; left:0; width: 100%; height: 100%; overflow: auto; display:none', id='book-overlay'), # main 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='position: absolute; top:0; left:0; width: 100%; height: 100%; display:none', id=CreateAnnotation.container_id), # create annotation overlay ) ), E.div( @@ -260,6 +262,7 @@ class View: 'search_result_not_found': def (data): if ui_operations.search_result_not_found: ui_operations.search_result_not_found(data.search_result) , + 'annotations': self.on_annotations_message, } entry_point = None if runtime.is_standalone_viewer else 'read_book.iframe' if runtime.is_standalone_viewer: @@ -275,6 +278,7 @@ class View: self.pending_load = None self.currently_showing = {} self.book_scrollbar.apply_visibility() + self.create_annotation = CreateAnnotation(self) @property def iframe(self): @@ -299,6 +303,9 @@ class View: return self.overlay.show_word_actions(data.word) + def on_annotations_message(self, data): + self.create_annotation.handle_message(data) + def left_margin_clicked(self, event): if event.button is 0: event.preventDefault(), event.stopPropagation()