# HG changeset patch # User Goffi # Date 1592578071 -7200 # Node ID 6e110baa707f52b24d8394c03e3430bc45ffffe9 # Parent 053141849206c8b826b436d6b24a0936d892291f browser (photos/album): photo(s) upload and deletion diff -r 053141849206 -r 6e110baa707f libervia/pages/photos/album/_browser/__init__.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/libervia/pages/photos/album/_browser/__init__.py Fri Jun 19 16:47:51 2020 +0200 @@ -0,0 +1,155 @@ +from browser import document, window, bind, html, DOMNode +from browser import aio +from browser import timer +from javascript import JSON +from interpreter import Inspector +from bridge import Bridge +from template import Template +import dialog + +files_service = window.files_service +files_path = window.files_path +bridge = Bridge() + + +def on_progress(ev, photo_elt): + if ev.lengthComputable: + percent = int(ev.loaded/ev.total*100) + update_progress(photo_elt, percent) + + +def on_load(file_, photo_elt): + update_progress(photo_elt, 100) + photo_elt.classList.add("progress_finished") + photo_elt.classList.remove("progress_started") + photo_elt.select_one('.action_delete').bind("click", on_delete) + print(f"file {file_.name} uploaded correctly") + + +def on_error(failure, file_, photo_elt): + # TODO: cleaner error notification + window.alert(f"can't upload {file_.name}: failure") + + +def update_progress(photo_elt, new_value): + progress_elt = photo_elt.select_one("progress") + progress_elt.value = new_value + progress_elt.text = f"{new_value}%" + + +def on_slot_cb(file_, upload_slot, photo_elt): + put_url, get_url, headers = upload_slot + xhr = window.XMLHttpRequest.new() + xhr.open("PUT", put_url, True) + xhr.upload.bind('progress', lambda ev: on_progress(ev, photo_elt)) + xhr.upload.bind('load', lambda ev: on_load(file_, photo_elt)) + xhr.upload.bind('error', lambda ev: on_error(xhr.response, file_, photo_elt)) + xhr.setRequestHeader('Xmpp-File-Path', window.encodeURIComponent(files_path)) + xhr.setRequestHeader('Xmpp-File-No-Http', "true") + xhr.send(file_) + + +def on_slot_eb(file_, failure, photo_elt): + breakpoint() + + +def upload_files(files): + print(f"uploading {len(files)} files") + photo_tpl = Template('photo/item.html') + album_items = document['album_items'] + for file_ in files: + url = window.URL.createObjectURL(file_) + photo_elt = photo_tpl.get_elt({ + "file": { + "name": file_.name, + # we don't want to open the file on click, it's not yet the + # uploaded URL + "url": url, + # we have no thumb yet, so we use the whole image + # TODO: reduce image for preview + "thumb_url": url, + }, + "uploading": True, + }) + photo_elt.classList.add("progress_started") + print(photo_elt.outerHTML) + album_items <= photo_elt + # timer.set_timeout(lambda photo_elt=photo_elt: fake_finish(photo_elt), 5000) + + bridge.fileHTTPUploadGetSlot( + file_.name, + file_.size, + file_.type or '', + files_service, + callback=lambda upload_slot, file_=file_, photo_elt=photo_elt: + on_slot_cb(file_, upload_slot, photo_elt), + errback=lambda failure, file_=file_, photo_elt=photo_elt: + on_slot_eb(file_, failure, photo_elt), + ) + + +@bind("#file_drop", "drop") +def on_file_select(evt): + evt.stopPropagation() + evt.preventDefault() + files = evt.dataTransfer.files + upload_files(files) + + +@bind("#file_drop", "dragover") +def on_drag_over(evt): + evt.stopPropagation() + evt.preventDefault() + evt.dataTransfer.dropEffect = 'copy' + + +@bind("#file_input", "change") +def on_file_input_change(evt): + files = evt.currentTarget.files + upload_files(files) + + +def file_delete_cb(item_elt, item): + item_elt.classList.add("state_deleted") + item_elt.bind("transitionend", lambda evt: item_elt.remove()) + print(f"deleted {item['name']}") + + +def file_delete_eb(failure, item_elt, item): + # TODO: cleaner error notification + window.alert(f"error while deleting {item['name']}: failure") + + +def delete_ok(evt, notif_elt, item_elt, item): + file_path = f"{files_path.rstrip('/')}/{item['name']}" + bridge.fileSharingDelete( + files_service, + file_path, + "", + callback=lambda : file_delete_cb(item_elt, item), + errback=lambda failure: file_delete_eb(failure, item_elt, item), + ) + + +def delete_cancel(evt, notif_elt, item_elt, item): + notif_elt.remove() + item_elt.classList.remove("selected_for_deletion") + + +def on_delete(evt): + evt.stopPropagation() + target = evt.currentTarget + item_elt = DOMNode(target.elt.closest('.item')) + item_elt.classList.add("selected_for_deletion") + item = JSON.parse(item_elt.dataset.item) + dialog.Confirm( + f"{item['name']!r} will be deleted, are you sure?", + ok_label="delete", + ).show( + ok_cb=lambda evt, notif_elt: delete_ok(evt, notif_elt, item_elt, item), + cancel_cb=lambda evt, notif_elt: delete_cancel(evt, notif_elt, item_elt, item), + ) + + +for elt in document.select('.action_delete'): + elt.bind("click", on_delete)