mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Start work on highlights panel for browser viewer
This commit is contained in:
parent
8343e8165a
commit
9e91907268
@ -161,6 +161,10 @@ class AnnotationsManager: # {{{
|
||||
highlights = highlights or v'[]'
|
||||
self.highlights = {h.uuid: h for h in highlights}
|
||||
|
||||
def all_highlights(self):
|
||||
ans = [h for h in Object.values(self.highlights) if not h.removed].as_array()
|
||||
return ans
|
||||
|
||||
def merge_highlights(self, highlights):
|
||||
highlights = highlights or v'[]'
|
||||
updated = False
|
||||
|
@ -7,7 +7,8 @@ from gettext import gettext as _
|
||||
|
||||
from book_list.globals import get_session_data
|
||||
from book_list.theme import get_color
|
||||
from dom import svgicon, unique_id
|
||||
from complete import create_search_bar
|
||||
from dom import add_extra_css, build_rule, svgicon, unique_id
|
||||
from modals import error_dialog
|
||||
from widgets import create_button
|
||||
|
||||
@ -505,3 +506,116 @@ class EditNotesAndColors: # {{{
|
||||
style = self.container.getElementsByClassName('current-swatch')[0].dataset.style
|
||||
return HighlightStyle(JSON.parse(style))
|
||||
# }}}
|
||||
|
||||
|
||||
# Browse highlights panel {{{
|
||||
|
||||
def get_container_id():
|
||||
if not get_container_id.ans:
|
||||
get_container_id.ans = unique_id()
|
||||
return get_container_id.ans
|
||||
|
||||
|
||||
def get_container():
|
||||
return document.getElementById(get_container_id())
|
||||
|
||||
|
||||
def find_previous():
|
||||
pass
|
||||
|
||||
|
||||
def find_next():
|
||||
pass
|
||||
|
||||
add_extra_css(def():
|
||||
sel = '#' + get_container_id()
|
||||
ans = ''
|
||||
qsel = sel + ' .highlight'
|
||||
ans += build_rule(qsel, margin_top='1ex', border_top='solid 1px', padding_top='1ex', cursor='pointer')
|
||||
ans += build_rule(qsel + ' .notes', display='none', margin_top='1ex', max_height='20ex', overflow='auto')
|
||||
ans += build_rule(qsel + ' .actions', display='none', margin_top='1ex', justify_content='space-between')
|
||||
current = qsel + '.current'
|
||||
ans += build_rule(current + ' .title', font_weight='bold', font_size='larger')
|
||||
ans += build_rule(current + ' .notes', display='block')
|
||||
ans += build_rule(current + ' .actions', display='flex')
|
||||
return ans
|
||||
)
|
||||
|
||||
|
||||
def render_notes(notes, container):
|
||||
current_block = ''
|
||||
def add_para():
|
||||
nonlocal current_block
|
||||
container.appendChild(E.p(current_block))
|
||||
if container.childNodes.length > 1:
|
||||
container.lastChild.style.marginTop = '2ex'
|
||||
current_block = ''
|
||||
|
||||
for line in notes.splitlines():
|
||||
if not line or not line.strip():
|
||||
if current_block:
|
||||
add_para()
|
||||
continue
|
||||
current_block += line + '\n'
|
||||
if current_block:
|
||||
add_para()
|
||||
return container
|
||||
|
||||
|
||||
def highlight_entry_clicked(ev):
|
||||
set_current_highlight_entry(ev.currentTarget)
|
||||
|
||||
|
||||
def set_current_highlight_entry(entry):
|
||||
c = get_container()
|
||||
for h in c.querySelectorAll('.highlight'):
|
||||
h.classList.remove('current')
|
||||
entry.classList.add('current')
|
||||
|
||||
|
||||
def show_in_text(annot_id, view):
|
||||
view.highlight_action(annot_id, 'goto')
|
||||
|
||||
|
||||
def highlight_entry(h, onclick):
|
||||
|
||||
def action(func, ev):
|
||||
ev.stopPropagation(), ev.preventDefault()
|
||||
onclick(func)
|
||||
|
||||
ans = E.div(
|
||||
class_='highlight',
|
||||
onclick=highlight_entry_clicked,
|
||||
E.div(class_='title', h.highlighted_text),
|
||||
E.div(
|
||||
class_='actions',
|
||||
E.a(class_='blue-link', _('Show in text'), onclick=action.bind(None, show_in_text.bind(None, h.uuid))),
|
||||
'\xa0\xa0',
|
||||
E.a(class_='blue-link', _('Remove highlight')),
|
||||
),
|
||||
E.div(class_='notes')
|
||||
)
|
||||
if h.notes:
|
||||
render_notes(h.notes, ans.querySelector('.notes'))
|
||||
return ans
|
||||
|
||||
|
||||
def create_highlights_panel(annotations_manager, book, container, onclick):
|
||||
next_button = E.div(style='margin-left: 1rem', class_='simple-link', svgicon('chevron-down'), title=_('Next match'))
|
||||
prev_button = E.div(style='margin-left: 1rem', class_='simple-link', svgicon('chevron-up'), title=_('Previous match'))
|
||||
prev_button.addEventListener('click', def(ev): find_previous();)
|
||||
sb = create_search_bar(find_next, 'search-in-highlights', placeholder=_('Search') + '…', button=next_button, associated_widgets=[prev_button])
|
||||
sb.style.flexGrow = '10'
|
||||
c = E.div(
|
||||
style='margin: 1rem',
|
||||
id=get_container_id(),
|
||||
E.div(
|
||||
style='display: flex',
|
||||
sb, next_button, prev_button
|
||||
),
|
||||
)
|
||||
container.appendChild(c)
|
||||
c.appendChild(E.div())
|
||||
for h in annotations_manager.all_highlights():
|
||||
c.lastChild.appendChild(highlight_entry(h, onclick))
|
||||
# }}}
|
||||
|
@ -21,6 +21,7 @@ from modals import error_dialog
|
||||
from read_book.bookmarks import create_bookmarks_panel
|
||||
from read_book.globals import runtime, ui_operations
|
||||
from read_book.goto import create_goto_panel, create_location_overlay
|
||||
from read_book.highlights import create_highlights_panel
|
||||
from read_book.open_book import create_open_book
|
||||
from read_book.prefs.font_size import create_font_size_panel
|
||||
from read_book.prefs.main import create_prefs_panel
|
||||
@ -271,9 +272,13 @@ class MainOverlay: # {{{
|
||||
reload_actions = E.ul(sync_action, delete_action, reload_action)
|
||||
|
||||
bookmarks_action = ac(_('Bookmarks'), None, self.overlay.show_bookmarks, 'bookmark')
|
||||
highlights_action = ac(
|
||||
_('Browse highlights'), _('Browse all highlights'), def():
|
||||
self.overlay.show_highlights()
|
||||
, 'image')
|
||||
|
||||
toc_actions = E.ul(ac(_('Table of Contents'), None, self.overlay.show_toc, 'toc'))
|
||||
|
||||
toc_actions.appendChild(bookmarks_action)
|
||||
toc_actions.appendChild(ac(_('Reference mode'), _('Toggle the Reference mode'), self.overlay.toggle_reference_mode, 'reference-mode'))
|
||||
|
||||
actions_div = E.div( # actions
|
||||
@ -288,6 +293,8 @@ class MainOverlay: # {{{
|
||||
|
||||
toc_actions,
|
||||
|
||||
E.ul(highlights_action, bookmarks_action),
|
||||
|
||||
E.ul(
|
||||
ac(_('Font size'), _('Change text size'), self.overlay.show_font_size_chooser, 'Aa', True),
|
||||
ac(_('Preferences'), _('Configure the book viewer'), self.overlay.show_prefs, 'cogs'),
|
||||
@ -331,10 +338,6 @@ class MainOverlay: # {{{
|
||||
ac(_('Lookup/search word'), _('Lookup or search for the currently selected word'),
|
||||
def(): self.overlay.hide(), ui_operations.toggle_lookup(True);, 'library')
|
||||
))
|
||||
actions_div.lastChild.appendChild(
|
||||
ac(_('Browse highlights'), _('Browse all highlights'),
|
||||
def(): self.overlay.hide(), ui_operations.toggle_highlights();, 'image')
|
||||
)
|
||||
copy_actions = E.ul()
|
||||
if self.elements.link:
|
||||
copy_actions.appendChild(ac(_('Copy link'), _('Copy the current link'), def():
|
||||
@ -671,6 +674,14 @@ class Overlay:
|
||||
self.show_current_panel()
|
||||
self.view.get_current_cfi('show-bookmarks', do_it)
|
||||
|
||||
def show_highlights(self):
|
||||
if ui_operations.toggle_highlights:
|
||||
self.hide()
|
||||
ui_operations.toggle_highlights()
|
||||
return
|
||||
self.panels.push(TOCOverlay(self, create_highlights_panel.bind(None, self.view.annotations_manager), _('Highlights')))
|
||||
self.show_current_panel()
|
||||
|
||||
def show_goto(self):
|
||||
self.hide_current_panel()
|
||||
self.panels.push(TOCOverlay(self, create_goto_panel.bind(None, self.view.current_position_data), _('Go to…')))
|
||||
|
@ -12,7 +12,7 @@ from dom import clear, svgicon, unique_id
|
||||
from modals import error_dialog, question_dialog
|
||||
from read_book.globals import runtime, ui_operations
|
||||
from read_book.highlights import (
|
||||
ICON_SIZE, EditNotesAndColors, HighlightStyle, all_styles
|
||||
ICON_SIZE, EditNotesAndColors, HighlightStyle, all_styles, render_notes
|
||||
)
|
||||
from read_book.shortcuts import shortcut_for_key_event
|
||||
|
||||
@ -340,23 +340,7 @@ class SelectionBar:
|
||||
c.style.maxHeight = 'min(20ex, 40vh)'
|
||||
else:
|
||||
c.style.maxHeight = '20ex'
|
||||
current_block = ''
|
||||
|
||||
def add_para():
|
||||
nonlocal current_block
|
||||
c.appendChild(E.p(current_block))
|
||||
if c.childNodes.length > 1:
|
||||
c.lastChild.style.marginTop = '2ex'
|
||||
current_block = ''
|
||||
|
||||
for line in notes.splitlines():
|
||||
if not line or not line.strip():
|
||||
if current_block:
|
||||
add_para()
|
||||
continue
|
||||
current_block += line + '\n'
|
||||
if current_block:
|
||||
add_para()
|
||||
render_notes(notes, c)
|
||||
# }}}
|
||||
|
||||
# accessors {{{
|
||||
|
Loading…
x
Reference in New Issue
Block a user