From f2e7f3e924b865746d113c5a6abd7eff2d27b418 Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Sun, 16 Aug 2020 11:00:39 +0530 Subject: [PATCH] UI to remove bookmarks --- src/pyj/book_list/item_list.pyj | 52 ++++++++++++++++++++++++------- src/pyj/read_book/annotations.pyj | 11 +++++++ src/pyj/read_book/bookmarks.pyj | 19 +++++++++-- 3 files changed, 68 insertions(+), 14 deletions(-) diff --git a/src/pyj/book_list/item_list.pyj b/src/pyj/book_list/item_list.pyj index 38bdda9ac8..64dc241009 100644 --- a/src/pyj/book_list/item_list.pyj +++ b/src/pyj/book_list/item_list.pyj @@ -12,14 +12,24 @@ CLASS_NAME = 'generic-items-list' add_extra_css(def(): sel = '.' + CLASS_NAME + ' ' style = '' - style += build_rule(sel + 'li', padding='1em', border_bottom='solid 1px ' + get_color('window-foreground'), border_top='solid 1px ' + get_color('window-background'), cursor='pointer', list_style='none') + style += build_rule(sel + 'li', padding='0', border_bottom='solid 1px ' + get_color('window-foreground'), border_top='solid 1px ' + get_color('window-background'), cursor='pointer', list_style='none') style += build_rule(sel + '.item-title', font_size=get_font_size('item-list-title')) style += build_rule(sel + ' .item-subtitle', font_size=get_font_size('item-list-subtitle'), font_style='italic') - style += build_rule(sel + ' li:hover', color=get_color('list-hover-foreground'), background_color=get_color('list-hover-background'), border_top_color=get_color('list-hover-foreground')) - style += build_rule(sel + ' li:active', transform='scale(1, 1.5)') + sel += ' li > div:nth-child(1)' + style += build_rule(sel, padding='1rem') + style += build_rule(sel + ':hover', color=get_color('list-hover-foreground'), background_color=get_color('list-hover-background'), border_top_color=get_color('list-hover-foreground')) + style += build_rule(sel + ':active', transform='scale(1, 1.5)') return style ) + +def side_action(action, ev): + ev.stopPropagation(), ev.preventDefault() + if action: + li = ev.currentTarget.closest('li') + action(li) + + def build_list(container, items, subtitle): c = container clear(c) @@ -40,20 +50,38 @@ def build_list(container, items, subtitle): if item.icon: ic = svgicon(item.icon) ic = E.span(ic, '\xa0') - ul.appendChild(E.li( - E.div(ic, item.title, class_='item-title') - )) - div = ul.lastChild.firstChild + li = E.li(E.div(ic, item.title, class_='item-title')) + ul.appendChild(li) if item.subtitle: - div.appendChild(E.div(item.subtitle, class_='item-subtitle', style='padding-top:1ex')) + li.firstChild.appendChild(E.div(item.subtitle, class_='item-subtitle', style='padding-top:1ex')) if item.action: - ul.lastChild.addEventListener('click', item.action) + li.addEventListener('click', item.action) if item.data: - ul.lastChild.dataset.userData = item.data + li.dataset.userData = item.data + if item.side_actions?.length: + s = li.style + s.display = 'flex' + s.alignItems = 'center' + li.firstChild.style.flexGrow = '10' + li.appendChild(E.div( + style='display: flex; align-items: center; margin-left: 0.5rem' + )) + for x in item.side_actions: + li.lastChild.appendChild(E.div( + class_='simple-link', + style='padding: 0.5rem', + title=x.tooltip or '', + onclick=side_action.bind(None, x.action), + svgicon(x.icon) + )) -def create_item(title, action=None, subtitle=None, icon=None, data=None): - return {'title':title, 'action':action, 'subtitle':subtitle, 'icon':icon, 'data': data} +def create_side_action(icon, action=None, tooltip=None): + return {'icon':icon, 'action': action, 'tooltip': tooltip} + + +def create_item(title, action=None, subtitle=None, icon=None, data=None, side_actions=None): + return {'title':title, 'action':action, 'subtitle':subtitle, 'icon':icon, 'data': data, 'side_actions': side_actions or v'[]'} def create_item_list(container, items, subtitle=None): diff --git a/src/pyj/read_book/annotations.pyj b/src/pyj/read_book/annotations.pyj index 26febdb198..eff359b194 100644 --- a/src/pyj/read_book/annotations.pyj +++ b/src/pyj/read_book/annotations.pyj @@ -128,6 +128,17 @@ class AnnotationsManager: # {{{ if ui_operations.bookmarks_changed: ui_operations.bookmarks_changed(self.bookmarks.as_array()) + def remove_bookmark(self, title): + changed = False + for b in self.bookmarks: + if b.title is title: + b.removed = True + b.timestamp = Date().toISOString() + changed = True + if changed and ui_operations.bookmarks_changed: + ui_operations.bookmarks_changed(self.bookmarks.as_array()) + return changed + def default_bookmark_title(self): all_titles = {bm.title:True for bm in self.bookmarks if not bm.removed} base_default_title = _('Bookmark') diff --git a/src/pyj/read_book/bookmarks.pyj b/src/pyj/read_book/bookmarks.pyj index 53a4b13389..2d2365370e 100644 --- a/src/pyj/read_book/bookmarks.pyj +++ b/src/pyj/read_book/bookmarks.pyj @@ -5,8 +5,9 @@ from __python__ import bound_methods, hash_literals from elementmaker import E from gettext import gettext as _ -from book_list.item_list import build_list, create_item +from book_list.item_list import build_list, create_item, create_side_action from dom import ensure_id, set_css +from modals import question_dialog from widgets import create_button @@ -14,12 +15,26 @@ def goto_cfi(cfi, view): view.goto_cfi(cfi) +def remove_bookmark(annotations_manager, title, list_dom_node): + question_dialog(_('Are you sure?'), _('Do you want to permanently delete this bookmark?'), def (yes): + if yes: + annotations_manager.remove_bookmark(title) + list_dom_node.style.display = 'none' + ) + + + def create_bookmarks_list(annotations_manager, onclick): bookmarks = sorted(annotations_manager.all_bookmarks(), key=def(x): return x.title.toLowerCase();) items = [] for bookmark in bookmarks: if not bookmark.removed: - items.push(create_item(bookmark.title, data=bookmark.pos, action=onclick.bind(None, goto_cfi.bind(None, bookmark.pos)))) + sa = create_side_action('trash', remove_bookmark.bind(None, annotations_manager, bookmark.title), _('Remove this bookmark')) + items.push(create_item( + bookmark.title, data=bookmark.pos, + action=onclick.bind(None, goto_cfi.bind(None, bookmark.pos)), + side_actions=[sa] + )) c = E.div(style='margin-top: 1ex') build_list(c, items) return c