From 278985f3534cbfa74df5ff5b349f8beb3446c80c Mon Sep 17 00:00:00 2001 From: Kovid Goyal Date: Fri, 20 Oct 2023 20:35:43 +0530 Subject: [PATCH] Work on the image file select dialog --- src/pyj/book_list/comments_editor.pyj | 78 +++++++++++++++++++++++++-- src/pyj/book_list/edit_metadata.pyj | 4 +- src/pyj/book_list/show_note.pyj | 5 +- src/pyj/modals.pyj | 5 +- 4 files changed, 83 insertions(+), 9 deletions(-) diff --git a/src/pyj/book_list/comments_editor.pyj b/src/pyj/book_list/comments_editor.pyj index a9f63cdd6a..02192d3c8b 100644 --- a/src/pyj/book_list/comments_editor.pyj +++ b/src/pyj/book_list/comments_editor.pyj @@ -60,6 +60,67 @@ def insert_heading(editor_id, cmd): editor.focus() +def insert_image(): + acceptable_image_types = v'["image/png", "image/jpeg", "image/gif", "image/webp"]' + create_custom_dialog(_('Insert image'), def(parent, close_modal): + container = parent.closest('.modal_height_container') + max_container_height = container.style.maxHeight + + def action(ok, evt): + close_modal() + + def handle_files(files): + img = parent.getElementsByTagName('img')[0] + if img.src: + window.URL.revokeObjectURL(img.src) + img.src = '' + for f in files: + if acceptable_image_types.indexOf(f.type) > -1: + h = parent.querySelector('.button-box').offsetHeight + non_content_height = (container.offsetHeight - parent.offsetHeight) + 'px' + img.style.maxHeight = f'calc({max_container_height} - {non_content_height} - {h}px - 1rem)' + img.src = window.URL.createObjectURL(f) + return + alert(_('No valid image file found')) + + parent.appendChild(E.div(class_='moose', + ondragenter=def(e): + e.stopPropagation(), e.preventDefault() + , + ondragover=def(e): + e.stopPropagation(), e.preventDefault() + , + ondrop=def(e): + e.stopPropagation(), e.preventDefault() + handle_files(e.dataTransfer.files) + , + E.div( + style='display: flex;', + E.div( + style='min-width: 40%; max-width: 40%; margin-right: 0.5rem', + E.img(style='max-width: 100%'), + ), + E.div( + E.input( + type='file', accept=','.join(acceptable_image_types), + onchange=def(e): handle_files(e.target.files);, style='display: none' + ), + E.a( + _('Select an image from your files'), + class_='blue-link', href='javascript:void(0)', onclick=def (): + parent.querySelector('input[type=file]').click() + ), E.span(_(' or drag and drop an image onto this dialog.')) + ), + ), + E.div(class_='button-box', + create_button(_('OK'), action=action.bind(None, True), highlight=True), + '\xa0', + create_button(_('Cancel'), action=action.bind(None, False), highlight=False), + ), + + )) + ) + def insert_link(title, msg, proceed): create_custom_dialog(title, def(parent, close_modal): @@ -258,7 +319,10 @@ def all_editor_actions(): # {{{ 'icon': 'image', 'title': _('Insert an image'), 'execute': def (editor, activated): - insert_link(_('Insert an image'), _('Enter the image URL and optionally the image name'), insert_link_or_image.bind(None, editor.id, True)) + if editor.insert_image_files: + insert_image() + else: + insert_link(_('Insert an image'), _('Enter the image URL and optionally the image name'), insert_link_or_image.bind(None, editor.id, True)) }, 'fg': { 'icon': 'fg', @@ -325,7 +389,12 @@ class CommentsEditorBoss: document.body.lastChild.innerHTML = data.html def get_html(self, data): - self.comm.send_message('html', html=document.body.lastChild.innerHTML) + c = document.body.lastChild + img_urls = v'[]' + for img in c.getElementByTagName('img'): + if img.src: + img_urls.push(img.src) + self.comm.send_message('html', html=c.innerHTML, extra_data={'img_urls': img_urls}) def exec_command(self, data): document.execCommand(data.name, False, data.value) @@ -406,7 +475,7 @@ class Editor: def on_html_received(self, data): if self.get_html_callbacks.length: for f in self.get_html_callbacks: - f(data.html) + f(data.html, data.img_urls) self.get_html_callbacks = v'[]' def exec_command(self, name, value=None): @@ -452,8 +521,9 @@ def add_action(toolbar, ac_name, action, editor_id): toolbar.appendChild(b) -def create_comments_editor(container): +def create_comments_editor(container, options): iframe, editor = create_editor() + editor.insert_image_files = v'!!options.insert_image_files' toolbars = E.div(style='flex-grow: 0') toolbar1 = E.div(class_=TOOLBAR_CLASS) toolbar2 = E.div(class_=TOOLBAR_CLASS) diff --git a/src/pyj/book_list/edit_metadata.pyj b/src/pyj/book_list/edit_metadata.pyj index 16d0d745d0..93ae6f123e 100644 --- a/src/pyj/book_list/edit_metadata.pyj +++ b/src/pyj/book_list/edit_metadata.pyj @@ -187,7 +187,9 @@ def text_edit(container_id, book_id, field, fm, div, mi, get_name): def html_edit_get_value(container, proceed): - get_comments_html(container, proceed) + get_comments_html(container, def (html, data): + proceed(html) + ) def html_edit(container_id, book_id, field, fm, div, mi): diff --git a/src/pyj/book_list/show_note.pyj b/src/pyj/book_list/show_note.pyj index 8475bcd139..b8f91ed495 100644 --- a/src/pyj/book_list/show_note.pyj +++ b/src/pyj/book_list/show_note.pyj @@ -144,8 +144,9 @@ def save(container_id): c = document.getElementById(container_id) if not c: return - get_comments_html(c, def(html): + get_comments_html(c, def(html, extra_data): print(html) + console.log(extra_data) print('TODO: Implement saving') ) @@ -171,7 +172,7 @@ def init_edit(container_id): def create_editor(container, html): c = container.appendChild(E.div(style='flex-grow:10')) - editor = create_comments_editor(c) + editor = create_comments_editor(c, {'insert_image_files': True}) set_comments_html(c, html) focus_comments_editor(c) editor.init() diff --git a/src/pyj/modals.pyj b/src/pyj/modals.pyj index 80ce170a3b..ef0e0fa004 100644 --- a/src/pyj/modals.pyj +++ b/src/pyj/modals.pyj @@ -38,12 +38,13 @@ class Modal: modal_count += 1 self.id = modal_count + class ModalContainer: def __init__(self): div = E.div(id='modal-container', tabindex='0', E.div( # popup - E.div(), # content area + E.div(class_='modal_height_container'), # content area E.a(svgicon('close'), title=_('Close'), onclick=self.close_current_modal.bind(self)) ) ) @@ -189,13 +190,13 @@ def create_simple_dialog(title, msg, details, icon, prefix, on_close=None, icon_ def create_custom_dialog(title, content_generator_func, on_close=None, onkeydown=None): def create_func(parent, close_modal): content_div = E.div() - content_generator_func(content_div, close_modal) parent.appendChild( E.div( style='max-width:60em; text-align: left', E.h2(title, style='font-weight: bold; font-size: ' + get_font_size('title')), E.div(content_div, style='padding-top: 1em; margin-top: 1em; border-top: 1px solid currentColor'), )) + content_generator_func(content_div, close_modal) show_modal(create_func, on_close=on_close, onkeydown=onkeydown)