Start work on highlights panel for browser viewer

This commit is contained in:
Kovid Goyal 2020-08-17 15:24:37 +05:30
parent 8343e8165a
commit 9e91907268
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
4 changed files with 137 additions and 24 deletions

View File

@ -161,6 +161,10 @@ class AnnotationsManager: # {{{
highlights = highlights or v'[]' highlights = highlights or v'[]'
self.highlights = {h.uuid: h for h in highlights} 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): def merge_highlights(self, highlights):
highlights = highlights or v'[]' highlights = highlights or v'[]'
updated = False updated = False

View File

@ -7,7 +7,8 @@ from gettext import gettext as _
from book_list.globals import get_session_data from book_list.globals import get_session_data
from book_list.theme import get_color 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 modals import error_dialog
from widgets import create_button from widgets import create_button
@ -505,3 +506,116 @@ class EditNotesAndColors: # {{{
style = self.container.getElementsByClassName('current-swatch')[0].dataset.style style = self.container.getElementsByClassName('current-swatch')[0].dataset.style
return HighlightStyle(JSON.parse(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))
# }}}

View File

@ -21,6 +21,7 @@ from modals import error_dialog
from read_book.bookmarks import create_bookmarks_panel from read_book.bookmarks import create_bookmarks_panel
from read_book.globals import runtime, ui_operations from read_book.globals import runtime, ui_operations
from read_book.goto import create_goto_panel, create_location_overlay 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.open_book import create_open_book
from read_book.prefs.font_size import create_font_size_panel from read_book.prefs.font_size import create_font_size_panel
from read_book.prefs.main import create_prefs_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) reload_actions = E.ul(sync_action, delete_action, reload_action)
bookmarks_action = ac(_('Bookmarks'), None, self.overlay.show_bookmarks, 'bookmark') 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 = 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')) toc_actions.appendChild(ac(_('Reference mode'), _('Toggle the Reference mode'), self.overlay.toggle_reference_mode, 'reference-mode'))
actions_div = E.div( # actions actions_div = E.div( # actions
@ -288,6 +293,8 @@ class MainOverlay: # {{{
toc_actions, toc_actions,
E.ul(highlights_action, bookmarks_action),
E.ul( E.ul(
ac(_('Font size'), _('Change text size'), self.overlay.show_font_size_chooser, 'Aa', True), 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'), 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'), ac(_('Lookup/search word'), _('Lookup or search for the currently selected word'),
def(): self.overlay.hide(), ui_operations.toggle_lookup(True);, 'library') 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() copy_actions = E.ul()
if self.elements.link: if self.elements.link:
copy_actions.appendChild(ac(_('Copy link'), _('Copy the current link'), def(): copy_actions.appendChild(ac(_('Copy link'), _('Copy the current link'), def():
@ -671,6 +674,14 @@ class Overlay:
self.show_current_panel() self.show_current_panel()
self.view.get_current_cfi('show-bookmarks', do_it) 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): def show_goto(self):
self.hide_current_panel() self.hide_current_panel()
self.panels.push(TOCOverlay(self, create_goto_panel.bind(None, self.view.current_position_data), _('Go to…'))) self.panels.push(TOCOverlay(self, create_goto_panel.bind(None, self.view.current_position_data), _('Go to…')))

View File

@ -12,7 +12,7 @@ from dom import clear, svgicon, unique_id
from modals import error_dialog, question_dialog from modals import error_dialog, question_dialog
from read_book.globals import runtime, ui_operations from read_book.globals import runtime, ui_operations
from read_book.highlights import ( 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 from read_book.shortcuts import shortcut_for_key_event
@ -340,23 +340,7 @@ class SelectionBar:
c.style.maxHeight = 'min(20ex, 40vh)' c.style.maxHeight = 'min(20ex, 40vh)'
else: else:
c.style.maxHeight = '20ex' c.style.maxHeight = '20ex'
current_block = '' render_notes(notes, c)
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()
# }}} # }}}
# accessors {{{ # accessors {{{