Selection bar: Allow customizing to add quick highlight buttons with specific styles

This commit is contained in:
Kovid Goyal 2020-08-17 11:05:34 +05:30
parent 1ef9d7b7da
commit 8343e8165a
No known key found for this signature in database
GPG Key ID: 06BC317B515ACE7C
6 changed files with 97 additions and 25 deletions

View File

@ -119,3 +119,9 @@ annot_id_uuid_map = {}
def clear_annot_id_uuid_map():
nonlocal annot_id_uuid_map
annot_id_uuid_map = {}
def is_dark_theme(set_val):
if set_val?:
is_dark_theme.ans = set_val
return v'!!is_dark_theme.ans'

View File

@ -38,7 +38,7 @@ builtin_decorations_light = builtin_decorations_dark = {
}
def friendly_name(kind, which):
def builtin_friendly_name(kind, which):
if kind is 'color':
return {
'yellow': _('Yellow highlight'),
@ -49,7 +49,7 @@ def friendly_name(kind, which):
}[which] or _('Unknown highlight')
return {
'wavy': _('Red wavy underline'),
'strikeout': _('Red underline'),
'strikeout': _('Red strikeout'),
}[which] or _('Unknown underline')
@ -124,7 +124,7 @@ class HighlightStyle:
style.textDecorationStyle = tds
if tdc:
style.textDecorationColor = tdc
return
return container
bg = None
if s.type is 'builtin':
@ -136,6 +136,7 @@ class HighlightStyle:
if bg:
style.backgroundColor = bg
style.borderRadius = f'{br}{ICON_SIZE_UNIT}'
return container
def highlight_shade(self, is_dark):
s = self.style
@ -158,7 +159,7 @@ class HighlightStyle:
def friendly_name(self):
s = self.style
if s.type is 'builtin':
return friendly_name(s.kind, s.which)
return builtin_friendly_name(s.kind, s.which)
return s.friendly_name or _('Custom style')
@ -206,22 +207,14 @@ def custom_styles_equal(a, b):
return True
class StyleCollection:
def __init__(self):
custom_highlight_styles = get_session_data().get('custom_highlight_styles')
self.styles = []
self.style_id_counter = 0
def add(raw):
hs = HighlightStyle(raw)
hs.style_id = v'++self.style_id_counter'
self.styles.push(hs)
for raw in custom_highlight_styles:
add(raw)
for raw in all_builtin_styles():
add(raw)
def all_styles():
ans = v'[]'
custom_highlight_styles = get_session_data().get('custom_highlight_styles')
for raw in custom_highlight_styles:
ans.push(HighlightStyle(raw))
for raw in all_builtin_styles():
ans.push(HighlightStyle(raw))
return ans
class AddStyle: # {{{

View File

@ -7,6 +7,8 @@ from gettext import gettext as _
from book_list.globals import get_session_data
from dom import clear, svgicon, unique_id
from read_book.globals import is_dark_theme
from read_book.highlights import all_styles
from read_book.prefs.utils import create_button_box
from read_book.selection_bar import all_actions
from session import defaults
@ -17,12 +19,16 @@ CONTAINER = unique_id('selection-settings')
def set_actions(use_defaults):
c = get_container()
adef = all_actions()
actions = defaults.selection_bar_actions if use_defaults else get_session_data().get('selection_bar_actions')
sd = get_session_data()
actions = defaults.selection_bar_actions if use_defaults else sd.get('selection_bar_actions')
current = [x for x in actions if adef[x]]
c.querySelector('.current-actions').dataset.actions = JSON.stringify(current)
available_actions = [x for x in adef if current.indexOf(x) is -1]
c.querySelector('.available-actions').dataset.actions = JSON.stringify(available_actions)
update_action_tables()
quick_actions = defaults.selection_bar_quick_highlights if use_defaults else sd.get('selection_bar_quick_highlights')
c.querySelector('.quick-actions').dataset.actions = JSON.stringify(quick_actions)
update_quick_action_table()
def restore_defaults():
@ -113,6 +119,32 @@ def update_action_tables():
build_action_table(current, False)
def update_quick_action_table():
c = get_container().querySelector('.quick-actions')
clear(c)
c.style.display = 'flex'
c.style.flexWrap = 'wrap'
current = {x: True for x in JSON.parse(c.dataset.actions)}
for hs in all_styles():
c.appendChild(E.label(
style='margin: 1ex; display: flex; align-contents: center',
hs.make_swatch(E.span(), is_dark_theme()),
'\xa0',
hs.friendly_name,
'\xa0',
E.input(type='checkbox', value=hs.key, checked=current[hs.key]),
))
def selected_quick_actions():
ans = v'[]'
c = get_container().querySelector('.quick-actions')
for inp in c.querySelectorAll('input:checked'):
if inp.value:
ans.push(inp.value)
return ans
def create_selection_panel(container, apply_func, cancel_func):
container.appendChild(E.div(id=CONTAINER, style='margin: 1rem'))
container = container.lastChild
@ -144,6 +176,11 @@ def create_selection_panel(container, apply_func, cancel_func):
E.h3(_('Available actions')),
E.div(class_='available-actions')
))
container.appendChild(E.div(style='padding: 1ex; border-bottom: solid 1px; margin-bottom: 1ex',
E.h3(_('Quick highlight actions')),
E.div(_('Choose highlight styles that will have dedicated buttons in the selection bar to create highlights with a single click')),
E.div(class_='quick-actions'),
))
set_actions()
container.appendChild(create_button_box(restore_defaults, apply_func, cancel_func))
@ -171,5 +208,9 @@ def commit_selection(onchange):
if list(actions) != list(sd.get('selection_bar_actions')):
changed = True
sd.set('selection_bar_actions', actions)
quick_highlights = selected_quick_actions()
if list(quick_highlights) != list(sd.get('selection_bar_quick_highlights')):
changed = True
sd.set('selection_bar_quick_highlights', quick_highlights)
if changed:
onchange()

View File

@ -11,10 +11,13 @@ from book_list.theme import get_color
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
from read_book.highlights import (
ICON_SIZE, EditNotesAndColors, HighlightStyle, all_styles
)
from read_book.shortcuts import shortcut_for_key_event
DRAG_SCROLL_ZONE_MIN_HEIGHT = 10
BUTTON_MARGIN = '0.5rem'
# Utils {{{
@ -291,7 +294,7 @@ class SelectionBar:
self.view.focus_iframe()
)
ans.classList.add('simple-link')
ans.style.marginLeft = ans.style.marginRight = '0.5rem'
ans.style.marginLeft = ans.style.marginRight = BUTTON_MARGIN
return ans
actions = all_actions()
@ -300,9 +303,31 @@ class SelectionBar:
ac = actions[acname]
if ac and (not ac.needs_highlight or v'!!annot_id'):
bar.appendChild(cb(ac, self[ac.function_name]))
selection_bar_quick_highlights = sd.get('selection_bar_quick_highlights')
if selection_bar_quick_highlights?.length:
self.show_quick_highlight_buttons(bar, selection_bar_quick_highlights)
self.show_notes(bar_container, notes)
return bar_container
def show_quick_highlight_buttons(self, bar, actions):
all = {x.key:x for x in all_styles()}
actions = [a for a in actions if all[a]]
if not actions.length:
return
bar.appendChild(E.div(
style=f'background: currentColor; width: 1px; height: {ICON_SIZE}; margin-left: {BUTTON_MARGIN}; margin-right: {BUTTON_MARGIN}'
))
dark = self.view.current_color_scheme.is_dark_theme
for key in actions:
hs = all[key]
sw = E.div(
class_='simple-link', style=f'margin-left: {BUTTON_MARGIN}; margin-right: {BUTTON_MARGIN}',
title=_('Highlight using: {}').format(hs.friendly_name),
onclick=self.quick_highlight_with_style.bind(None, hs),
)
hs.make_swatch(sw, dark)
bar.appendChild(sw)
def show_notes(self, bar, notes):
notes = (notes or "").strip()
if not notes:
@ -793,6 +818,10 @@ class SelectionBar:
self.state = WAITING
self.update_position()
def quick_highlight_with_style(self, hs):
self.current_highlight_style = hs
self.quick_highlight()
def remove_highlight(self):
annot_id = self.view.currently_showing.selection.annot_id
if annot_id:

View File

@ -17,8 +17,8 @@ from read_book.annotations import AnnotationsManager
from read_book.bookmarks import create_new_bookmark
from read_book.content_popup import ContentPopupOverlay
from read_book.globals import (
current_book, rtl_page_progression, runtime, set_current_spine_item,
ui_operations
current_book, is_dark_theme, rtl_page_progression, runtime,
set_current_spine_item, ui_operations
)
from read_book.goto import get_next_section
from read_book.open_book import add_book_to_recently_viewed
@ -301,6 +301,7 @@ class View:
if runtime.is_standalone_viewer:
document.documentElement.addEventListener('keydown', self.handle_keypress, {'passive': False})
set_ui_colors(self.current_color_scheme.is_dark_theme)
is_dark_theme(self.current_color_scheme.is_dark_theme)
self.iframe_wrapper = IframeWrapper(
handlers, document.getElementById(iframe_id), entry_point, _('Bootstrapping book reader...'),
f'{runtime.FAKE_PROTOCOL}://{runtime.SANDBOX_HOST}/book/__index__')
@ -741,6 +742,7 @@ class View:
self.current_color_scheme = ans = resolve_color_scheme()
if runtime.is_standalone_viewer:
set_ui_colors(self.current_color_scheme.is_dark_theme)
is_dark_theme(self.current_color_scheme.is_dark_theme)
for which in 'left top right bottom'.split(' '):
m = document.getElementById('book-{}-margin'.format(which))
s = m.style

View File

@ -67,6 +67,7 @@ defaults = {
'show_selection_bar': True,
'net_search_url': 'https://google.com/search?q={q}',
'selection_bar_actions': v"['copy', 'lookup', 'highlight', 'remove_highlight', 'search_net', 'clear']",
'selection_bar_quick_highlights': v"[]",
}
is_local_setting = {