diff --git a/src/pyj/read_book/create_annotation.pyj b/src/pyj/read_book/create_annotation.pyj index 887252e12e..3772017273 100644 --- a/src/pyj/read_book/create_annotation.pyj +++ b/src/pyj/read_book/create_annotation.pyj @@ -6,8 +6,8 @@ from elementmaker import E from gettext import gettext as _ from book_list.globals import get_session_data -from book_list.theme import get_color -from dom import add_extra_css, ensure_id, svgicon, unique_id +from book_list.theme import get_color, cached_color_to_rgba +from dom import add_extra_css, clear, ensure_id, svgicon, unique_id from read_book.shortcuts import shortcut_for_key_event WAITING_FOR_CLICK = 1 @@ -27,10 +27,10 @@ add_extra_css(def(): dark_fg = '#111' light_fg = '#eee' highlight_colors = { - '#FCE2AE': dark_fg, - '#B6FFEA': dark_fg, - '#FFB3B3': dark_fg, - '#FFDCF7': dark_fg, + '#fce2ae': dark_fg, + '#b6ffea': dark_fg, + '#ffb3b3': dark_fg, + '#ffdcf7': dark_fg, '#cae8d5': dark_fg, '#204051': light_fg, @@ -70,10 +70,13 @@ def map_to_iframe_coords(point): return point -def create_bar(size=32): +BAR_SIZE = 32 + + +def create_bar(): ans = E.div( id=unique_id('annot-bar'), - style=f'height: {size}px; width: 100vw; display: flex; justify-content: space-between;', + style=f'height: {BAR_SIZE}px; width: 100vw; display: flex; justify-content: space-between;', ) return ans @@ -116,6 +119,10 @@ class CreateAnnotation: button(tb, 'chevron-up', _('Scroll up'), self.scroll_up) button(tb, 'check', _('Finish creation of highlight'), self.accept) + middle = E.div(id=unique_id('middle'), style='display: none') + self.middle_id = middle.id + container.appendChild(middle) + bb = create_bar() container.appendChild(bb) button(bb, 'fg', _('Change highlight color'), self.choose_color) @@ -149,8 +156,88 @@ class CreateAnnotation: def scroll_down(self): self.send_message('scroll', backwards=False) + @property + def middle(self): + return document.getElementById(self.middle_id) + def choose_color(self): - pass + container = self.middle + container.style.display = 'block' + container.style.textAlign = 'center' + clear(container) + c = E.div( + E.h3(_('Choose highlight color')), + E.div( + style=f'display: flex; flex-wrap: wrap; max-width: calc({BAR_SIZE}px * 6); margin: auto', + onclick=def(ev): + ev.stopPropagation(), ev.preventDefault() + ), + onclick=def(ev): + ev.stopPropagation(), ev.preventDefault() + self.hide_middle() + , + style=f'background: {get_color("window-background")}; margin: auto; padding: 1rem', + + ) + current_style = self.current_highlight_style + container.appendChild(c) + found_current = False + self.save_handle_state() + self.handle_state = self.left_handle.display, self.right_hand + + def add(bg): + ic = svgicon('swatch', BAR_SIZE, BAR_SIZE) + ic.classList.add('simple-link') + is_current = bg.lower() is current_style['background-color'].lower() + sqbg = get_color('window-background2') if is_current else 'unset' + ic.querySelector('use').style.fill = bg + item = E.div( + ic, style=f'padding: 4px; background-color: {sqbg}; margin: 4px', + onclick=self.change_color.bind(None, bg) + ) + c.lastChild.appendChild(item) + return is_current + + + for bg in highlight_colors: + if add(bg): + found_current = True + if not found_current: + add(current_style['background-color']) + + def change_color(self, new_color): + self.hide_middle() + c = self.middle + c.style.display = 'none' + current_style = self.current_highlight_style + if not new_color or current_style['background-color'].lower() is new_color.lower(): + return + fg = highlight_colors[new_color] + if not fg: + rgba = cached_color_to_rgba(new_color) + is_dark = max(rgba[0], rgba[1], rgba[2]) < 115 + fg = light_fg if is_dark else dark_fg + self.current_highlight_style = {'background-color': new_color, 'color': fg} + self.send_message('set-highlight-style', style=self.current_highlight_style) + + def show_middle(self): + self.save_handle_state() + self.middle.style.display = 'block' + + def hide_middle(self): + m = self.middle + if m.style.display is not 'none': + self.restore_handle_state() + m.style.display = 'none' + + def save_handle_state(self): + for h in (self.left_handle, self.right_handle): + h.dataset.savedState = h.style.display + h.style.display = 'none' + + def restore_handle_state(self): + for h in (self.left_handle, self.right_handle): + h.style.display = h.dataset.savedState def accept(self): pass @@ -170,6 +257,7 @@ class CreateAnnotation: def container_clicked(self, ev): ev.stopPropagation(), ev.preventDefault() + self.hide_middle() if self.state is WAITING_FOR_CLICK: pt = map_to_iframe_coords({'x': ev.clientX, 'y': ev.clientY}) self.send_message('position-handles-at-point', x=pt.x, y=pt.y)