E-book viewer: Allow adding a button to the selection bar that copies the currently selected text along with a calibre:// URL to show the text in the book. See #1912070 ([Enhancement] Additional access to copying Go To URL location link)

This commit is contained in:
Kovid Goyal 2021-01-18 13:14:22 +05:30
parent 9032d92954
commit 15e8980cb2
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 37 additions and 11 deletions

View File

@ -535,13 +535,13 @@ def get_current_link_prefix():
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')
link = encode_query(current_query)
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
link = encode_query(current_query)[1:]
return link_prefix + link.replace(/\)/g, '%29').replace(/\(/g, '%28')
def render_highlight_as_text(hl, lines, link_prefix, current_query, as_markdown=False):

View File

@ -849,6 +849,14 @@ class IframeBoss:
anchor_before=anchor_before
)
reset_find_caches()
elif dtype is 'cite-current-selection':
sel = window.getSelection()
if not sel.rangeCount:
return
bounds = cfi_for_selection()
anchor_before = find_anchor_before_range(sel.getRangeAt(0), self.book.manifest.toc_anchor_map, self.anchor_funcs)
text = sel.toString()
self.send_message('annotations', type='cite-data', bounds=bounds, highlighted_text=text)
else:
console.log('Ignoring annotations message to iframe with unknown type: ' + dtype)

View File

@ -3,20 +3,21 @@
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
from dom import change_icon_image, clear, svgicon, unique_id
from modals import error_dialog, question_dialog, create_custom_dialog
from gettext import gettext as _
from modals import create_custom_dialog, error_dialog, question_dialog
from read_book.globals import runtime, ui_operations
from read_book.highlights import (
ICON_SIZE, EditNotesAndColors, HighlightStyle, all_styles, render_notes
ICON_SIZE, EditNotesAndColors, HighlightStyle, all_styles,
get_current_link_prefix, link_to_epubcfi, render_notes
)
from widgets import create_button
from read_book.shortcuts import shortcut_for_key_event
from read_book.toc import get_toc_nodes_bordering_spine_item, family_for_toc_node
from read_book.toc import family_for_toc_node, get_toc_nodes_bordering_spine_item
from uuid import short_uuid
from widgets import create_button
DRAG_SCROLL_ZONE_MIN_HEIGHT = 10
BUTTON_MARGIN = '0.5rem'
@ -193,6 +194,7 @@ def all_actions():
'remove_highlight': a('trash', _('Remove this highlight'), 'remove_highlight', True),
'clear': a('close', _('Clear selection'), 'clear_selection'),
'speak': a('bullhorn', _('Read aloud'), 'speak_aloud'),
'cite': a('reference-mode', _('Copy citation to clipboard'), 'cite'),
}
qh = all_actions.ans.quick_highlight
qh.icon_function = quick_highlight_icon.bind(None, qh.icon, qh.text)
@ -961,6 +963,9 @@ class SelectionBar:
ui_operations.speak_simple_text(text)
self.spoken_aloud_at_least_once = True
def cite(self):
self.send_message('cite-current-selection')
def create_highlight(self):
cs = self.view.currently_showing.selection
hs = self.current_highlight_style
@ -1042,6 +1047,16 @@ class SelectionBar:
self.report_failed_edit_highlight(msg.uuid)
elif msg.type is 'double-click':
self.last_double_click_at = window.performance.now()
elif msg.type is 'cite-data':
spine_index = self.view.currently_showing.spine_index
spine_index = (1 + spine_index) * 2
cfi = msg.bounds.start
link_prefix = get_current_link_prefix()
if not link_prefix:
return self.view.show_not_a_library_book_error()
url = link_to_epubcfi(f'epubcfi(/{spine_index}{cfi})', link_prefix)
text = msg.highlighted_text.replace(/\[/g, r'\[').replace(/\]/g, r'\]')
ui_operations.copy_selection(f'[{text}]({url})')
else:
print('Ignoring annotations message with unknown type:', msg.type)

View File

@ -340,11 +340,14 @@ class View:
def copy_to_clipboard(self):
self.iframe_wrapper.send_message('copy_selection')
def show_not_a_library_book_error(self):
error_dialog(_('Not a calibre library book'), _(
'This book is not a part of a calibre library, so no calibre:// URL for it exists.'))
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.'))
return self.show_not_a_library_book_error()
self.get_current_cfi('copy-location-url', def (req_id, data):
if as_url:
text = link_to_epubcfi(data.cfi, link_prefix)