diff --git a/src/pyj/read_book/highlights.pyj b/src/pyj/read_book/highlights.pyj index 456db6574f..b9d6ddb0f6 100644 --- a/src/pyj/read_book/highlights.pyj +++ b/src/pyj/read_book/highlights.pyj @@ -5,7 +5,7 @@ from __python__ import bound_methods, hash_literals from elementmaker import E from ajax import encode_query -from book_list.globals import get_session_data, get_current_query +from book_list.globals import get_current_query, get_session_data from book_list.theme import get_color from complete import create_search_bar from dom import add_extra_css, build_rule, clear, svgicon, unique_id @@ -14,7 +14,7 @@ from modals import ( create_custom_dialog, error_dialog, get_text_dialog, question_dialog, warning_dialog ) -from read_book.globals import is_dark_theme +from read_book.globals import current_book, is_dark_theme, runtime from widgets import create_button ICON_SIZE_VAL = 3 @@ -525,14 +525,32 @@ def get_container(): return document.getElementById(get_container_id()) +def get_current_link_prefix(): + if runtime.is_standalone_viewer: + return current_book().calibre_book_url + link_prefix = window.location.href + return link_prefix[:link_prefix.indexOf('#') + 1] + + +def link_to_epubcfi(epubcfi, link_prefix, current_query): + if runtime.is_standalone_viewer: + current_query = {'open_at': epubcfi} + link = link_prefix + encode_query(current_query).replace(/\)/g, '%29') + else: + if not current_query: + current_query = Object.assign({}, get_current_query()) + current_query.bookpos = epubcfi + link = link_prefix + encode_query(current_query)[1:].replace(/\)/g, '%29') + return link + + def render_highlight_as_text(hl, lines, link_prefix, current_query, as_markdown=False): lines.push(hl.highlighted_text) date = Date(hl.timestamp).toLocaleString() if as_markdown: cfi = hl.start_cfi spine_index = (1 + hl.spine_index) * 2 - current_query.bookpos = f'epubcfi(/{spine_index}{cfi})' - link = link_prefix + encode_query(current_query)[1:].replace(/\)/g, '%29') + link = link_to_epubcfi(f'epubcfi(/{spine_index}{cfi})', link_prefix, current_query) date = f'[{date}]({link})' lines.push(date) notes = hl.notes @@ -547,7 +565,6 @@ def render_highlight_as_text(hl, lines, link_prefix, current_query, as_markdown= lines.push('') - def show_export_dialog(annotations_manager): sd = get_session_data() fmt = sd.get('highlights_export_format') @@ -559,8 +576,7 @@ def show_export_dialog(annotations_manager): idx = href.indexOf('#') href = href[:idx+1] current_query = Object.assign({}, get_current_query()) - link_prefix = window.location.href - link_prefix = link_prefix[:link_prefix.indexOf('#') + 1] + link_prefix = get_current_link_prefix() def update_text(): if fmt is 'calibre_annotations_collection': diff --git a/src/pyj/read_book/shortcuts.pyj b/src/pyj/read_book/shortcuts.pyj index 10bb169836..1365756b2d 100644 --- a/src/pyj/read_book/shortcuts.pyj +++ b/src/pyj/read_book/shortcuts.pyj @@ -206,6 +206,18 @@ def shortcuts_definition(): _('Copy to clipboard'), ), + 'copy_location_to_clipboard': desc( + v"['Alt+c']", + 'ui', + _('Copy current location to clipboard'), + ), + + 'copy_location_as_url_to_clipboard': desc( + v"['Ctrl+Shift+c']", + 'ui', + _('Copy current location as calibre:// URL to clipboard'), + ), + 'start_search': desc( v"['/', 'Ctrl+f']", 'ui', diff --git a/src/pyj/read_book/view.pyj b/src/pyj/read_book/view.pyj index 9a1272b9d7..ebdde54455 100644 --- a/src/pyj/read_book/view.pyj +++ b/src/pyj/read_book/view.pyj @@ -3,7 +3,6 @@ from __python__ import bound_methods, hash_literals from elementmaker import E -from gettext import gettext as _ import read_book.iframe # noqa from ajax import ajax_send @@ -11,6 +10,7 @@ from book_list.globals import get_session_data from book_list.theme import cached_color_to_rgba, get_color, set_ui_colors from book_list.ui import query_as_href from dom import add_extra_css, build_rule, clear, set_css, svgicon, unique_id +from gettext import gettext as _ from iframe_comm import IframeWrapper from modals import error_dialog, warning_dialog from read_book.annotations import AnnotationsManager @@ -21,6 +21,8 @@ from read_book.globals import ( set_current_spine_item, ui_operations ) from read_book.goto import get_next_section +from read_book.highlights import get_current_link_prefix, link_to_epubcfi +from read_book.hints import Hints from read_book.open_book import add_book_to_recently_viewed from read_book.overlay import Overlay from read_book.prefs.colors import resolve_color_scheme @@ -30,12 +32,11 @@ from read_book.prefs.head_foot import render_head_foot from read_book.prefs.scrolling import ( MIN_SCROLL_SPEED_AUTO as SCROLL_SPEED_STEP, change_scroll_speed ) +from read_book.read_aloud import ReadAloud from read_book.resources import load_resources from read_book.scrollbar import BookScrollbar from read_book.search import SearchOverlay, find_in_spine from read_book.selection_bar import SelectionBar -from read_book.read_aloud import ReadAloud -from read_book.hints import Hints from read_book.shortcuts import create_shortcut_map from read_book.timers import Timers from read_book.toc import get_current_toc_nodes, update_visible_toc_nodes @@ -339,6 +340,19 @@ class View: def copy_to_clipboard(self): self.iframe_wrapper.send_message('copy_selection') + def copy_current_location_to_clipboard(self, as_url): + link_prefix = get_current_link_prefix() + if not link_prefix and as_url: + return error_dialog(_('Not a calibre library book'), _( + 'This book is not a part of a calibre library, so no calibre:// URL for it exists.')) + self.get_current_cfi('copy-location-url', def (req_id, data): + if as_url: + text = link_to_epubcfi(data.cfi, link_prefix) + else: + text = data.cfi + ui_operations.copy_selection(text) + ) + def set_scrollbar_visibility(self, visible): sd = get_session_data() sd.set('book_scrollbar', bool(visible)) @@ -485,6 +499,8 @@ class View: self.new_bookmark() elif data.name is 'copy_to_clipboard': self.copy_to_clipboard() + elif data.name is 'copy_location_to_clipboard' or data.name is 'copy_location_as_url_to_clipboard': + self.copy_current_location_to_clipboard('url' in data.name) elif data.name is 'toggle_inspector': ui_operations.toggle_inspector() elif data.name is 'toggle_lookup':