mirror of
https://github.com/kovidgoyal/calibre.git
synced 2025-07-09 03:04:10 -04:00
Selection bar: Allow customizing to add quick highlight buttons with specific styles
This commit is contained in:
parent
1ef9d7b7da
commit
8343e8165a
@ -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'
|
||||
|
@ -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: # {{{
|
||||
|
@ -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()
|
||||
|
@ -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:
|
||||
|
@ -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
|
||||
|
@ -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 = {
|
||||
|
Loading…
x
Reference in New Issue
Block a user