From b87cd867b1a10452b943489d0c1adc80428ced89 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Tue, 10 Nov 2020 16:47:54 +0530 Subject: [PATCH] Viewer: Show URL for current book in the Goto location panel --- src/calibre/gui2/actions/view.py | 2 +- src/calibre/gui2/ui.py | 4 ++-- src/calibre/gui2/viewer/ui.py | 3 ++- src/calibre/gui2/viewer/web_view.py | 9 ++++++-- src/pyj/read_book/goto.pyj | 34 ++++++++++++++++++++--------- src/pyj/read_book/overlay.pyj | 2 +- src/pyj/viewer-main.pyj | 7 +++--- 7 files changed, 41 insertions(+), 20 deletions(-) diff --git a/src/calibre/gui2/actions/view.py b/src/calibre/gui2/actions/view.py index 293fccca49..702d772459 100644 --- a/src/calibre/gui2/actions/view.py +++ b/src/calibre/gui2/actions/view.py @@ -128,7 +128,7 @@ class ViewAction(InterfaceAction): merge_annotations(other_annotations_map, annotations_map, merge_last_read=False) return { 'book_id': book_id, 'uuid': db.field_for('uuid', book_id), 'fmt': fmt.upper(), - 'annotations_map': annotations_map, + 'annotations_map': annotations_map, 'library_id': getattr(self.gui.current_db.new_api, 'server_library_id', None) } def view_format_by_id(self, id_, format, open_at=None): diff --git a/src/calibre/gui2/ui.py b/src/calibre/gui2/ui.py index 676528fe7d..a76f04e9b3 100644 --- a/src/calibre/gui2/ui.py +++ b/src/calibre/gui2/ui.py @@ -635,8 +635,8 @@ class Main(MainWindow, MainWindowMixin, DeviceMixin, EmailMixin, # {{{ def decode_library_id(x): if x == '_': return getattr(self.current_db.new_api, 'server_library_id', None) or '_' - if x.startswith('hex-'): - return bytes.fromhex(x[4:]).decode('utf-8') + if x.startswith('_hex_-'): + return bytes.fromhex(x[6:]).decode('utf-8') return x if action == 'switch-library': diff --git a/src/calibre/gui2/viewer/ui.py b/src/calibre/gui2/viewer/ui.py index 6a3b3e149a..52c1fc5b34 100644 --- a/src/calibre/gui2/viewer/ui.py +++ b/src/calibre/gui2/viewer/ui.py @@ -537,7 +537,7 @@ class EbookViewer(MainWindow): initial_position = {'type': 'bookpos', 'data': float(open_at)} highlights = self.current_book_data['annotations_map']['highlight'] self.highlights_widget.load(highlights) - self.web_view.start_book_load(initial_position=initial_position, highlights=highlights) + self.web_view.start_book_load(initial_position=initial_position, highlights=highlights, current_book_data=self.current_book_data) def load_book_data(self, calibre_book_data=None): self.current_book_data['book_library_details'] = get_book_library_details(self.current_book_data['pathtoebook']) @@ -545,6 +545,7 @@ class EbookViewer(MainWindow): self.current_book_data['calibre_book_id'] = calibre_book_data['book_id'] self.current_book_data['calibre_book_uuid'] = calibre_book_data['uuid'] self.current_book_data['calibre_book_fmt'] = calibre_book_data['fmt'] + self.current_book_data['calibre_library_id'] = calibre_book_data['library_id'] self.load_book_annotations(calibre_book_data) path = os.path.join(self.current_book_data['base'], 'calibre-book-manifest.json') with open(path, 'rb') as f: diff --git a/src/calibre/gui2/viewer/web_view.py b/src/calibre/gui2/viewer/web_view.py index 7928484737..c1b987a70e 100644 --- a/src/calibre/gui2/viewer/web_view.py +++ b/src/calibre/gui2/viewer/web_view.py @@ -598,9 +598,14 @@ class WebView(RestartingWebEngineView): def on_content_file_changed(self, data): self.current_content_file = data - def start_book_load(self, initial_position=None, highlights=None): + def start_book_load(self, initial_position=None, highlights=None, current_book_data=None): key = (set_book_path.path,) - self.execute_when_ready('start_book_load', key, initial_position, set_book_path.pathtoebook, highlights or []) + cbd = current_book_data or {} + book_url = None + if 'calibre_library_id' in cbd: + lid = cbd['calibre_library_id'].encode('utf-8').hex() + book_url = f'calibre://view-book/_hex_-{lid}/{cbd["calibre_book_id"]}/{cbd["calibre_book_fmt"]}' + self.execute_when_ready('start_book_load', key, initial_position, set_book_path.pathtoebook, highlights or [], book_url) def execute_when_ready(self, action, *args): if self.bridge.ready: diff --git a/src/pyj/read_book/goto.pyj b/src/pyj/read_book/goto.pyj index d686bc12b6..df4630363a 100644 --- a/src/pyj/read_book/goto.pyj +++ b/src/pyj/read_book/goto.pyj @@ -5,6 +5,7 @@ from __python__ import bound_methods, hash_literals from elementmaker import E from gettext import gettext as _ +from ajax import encode_query_component from book_list.item_list import build_list, create_item from dom import ensure_id, set_css from modals import error_dialog @@ -58,22 +59,18 @@ def create_goto_panel(current_position_data, book, container, onclick): container.appendChild(panel) -def create_location_overlay(current_position_data, overlay, container): +def create_location_overlay(current_position_data, book, overlay, container): container_id = ensure_id(container) container.appendChild(E.div(style='margin: 0 1rem')) container = container.lastChild current_cfi = current_position_data.cfi - if current_cfi: - container.appendChild(E.div( - style='margin: 1rem; margin-bottom: calc(1rem - 1ex); display: flex; align-items: baseline; flex-wrap: wrap', - E.div( - _('Current location: {}').format(current_cfi), - style='flex-grow: 10; text-overflow: ellipsis; margin-bottom: 1ex' - ), - create_button(_('Copy'), action=def(): + calibre_book_url = book?.calibre_book_url + + def copy_button(text_to_copy): + return create_button(_('Copy'), action=def(): src = document.querySelector(f'#{container_id} input') orig = src.value - src.value = current_cfi + src.value = text_to_copy src.focus() src.select() try: @@ -81,8 +78,18 @@ def create_location_overlay(current_position_data, overlay, container): finally: src.value = orig ) + + def display_and_copy(label, text): + container.appendChild(E.div( + style='margin: 1rem; margin-bottom: calc(1rem - 1ex); display: flex; align-items: baseline; flex-wrap: wrap', + E.div(style='flex-grow: 10; text-overflow: ellipsis; margin-bottom: 1ex', + label, ' ', E.span(text, style='font-size: smaller; font-family: monospace')), + copy_button(text) )) + if current_cfi: + display_and_copy(_('Current location:'), current_cfi) + def goto_cfi(cfi): if ui_operations.goto_cfi(cfi): overlay.hide() @@ -134,4 +141,11 @@ def create_location_overlay(current_position_data, overlay, container): create_button(_('Go'), action=goto_pos) ) )) + + if calibre_book_url: + if current_cfi: + calibre_book_url += '?open_at=' + encode_query_component(current_cfi) + display_and_copy(_('URL for this position:'), calibre_book_url) + elif not runtime.is_standalone_viewer: + display_and_copy(_('URL for this position:'), window.top.location.toString()) container.querySelector('[name=newpos]').focus() diff --git a/src/pyj/read_book/overlay.pyj b/src/pyj/read_book/overlay.pyj index 635390a756..0b193ba26e 100644 --- a/src/pyj/read_book/overlay.pyj +++ b/src/pyj/read_book/overlay.pyj @@ -761,7 +761,7 @@ class Overlay: def show_ask_for_location(self): self.hide_current_panel() self.panels.push(SimpleOverlay( - self, create_location_overlay.bind(None, self.view.current_position_data), _('Go to location, position or reference…'))) + self, create_location_overlay.bind(None, self.view.current_position_data, self.view.book), _('Go to location, position or reference…'))) self.show_current_panel() def show_search(self): diff --git a/src/pyj/viewer-main.pyj b/src/pyj/viewer-main.pyj index 80e23722dc..add3a0eb07 100644 --- a/src/pyj/viewer-main.pyj +++ b/src/pyj/viewer-main.pyj @@ -91,7 +91,7 @@ def show_error(title, msg, details): to_python.show_error(title, msg, details) -def manifest_received(key, initial_position, pathtoebook, highlights, end_type, xhr, ev): +def manifest_received(key, initial_position, pathtoebook, highlights, book_url, end_type, xhr, ev): nonlocal book end_type = workaround_qt_bug(xhr, end_type) if end_type is 'load': @@ -102,6 +102,7 @@ def manifest_received(key, initial_position, pathtoebook, highlights, end_type, book.manifest.pathtoebook = pathtoebook book.highlights = highlights book.stored_files = {} + book.calibre_book_url = book_url book.is_complete = True v'delete book.manifest["metadata"]' v'delete book.manifest["last_read_positions"]' @@ -210,8 +211,8 @@ def show_home_page(): @from_python -def start_book_load(key, initial_position, pathtoebook, highlights): - xhr = ajax('manifest', manifest_received.bind(None, key, initial_position, pathtoebook, highlights), ok_code=0) +def start_book_load(key, initial_position, pathtoebook, highlights, book_url): + xhr = ajax('manifest', manifest_received.bind(None, key, initial_position, pathtoebook, highlights, book_url), ok_code=0) xhr.responseType = 'json' xhr.send()