import { DirectUpload } from "@rails/activestorage" import {Plugin} from "prosemirror-state" import {Decoration, DecorationSet} from "prosemirror-view" let placeholderPlugin = new Plugin({ state: { init() { return DecorationSet.empty }, apply(tr, set) { // Adjust decoration positions to changes made by the transaction set = set.map(tr.mapping, tr.doc) // See if the transaction adds or removes any placeholders let action = tr.getMeta(this) if (action && action.add) { let widget = document.createElement( action.add.blobUrl ? 'img' : 'placeholder' ) // mostrar imágen en cache mientras tanto if (action.add.blobUrl) { widget.src = action.add.blobUrl widget.classList.add('sutty-editor-loading-image') } let deco = Decoration.widget(action.add.pos, widget, {id: action.add.id}) set = set.add(tr.doc, [deco]) } else if (action && action.remove) { set = set.remove( set.find( null, null, spec => spec.id == action.remove.id, ), ) } return set } }, props: { decorations(state) { return this.getState(state) } } }) export {placeholderPlugin} function findPlaceholder(state, id) { let decos = placeholderPlugin.getState(state) let found = decos.find(null, null, spec => spec.id == id) return found.length ? found[0].from : null } // XXX: buscar una manera mejor de pasar el schema export function startImageUpload (view, file, schema) { const altText = window.prompt('descripción de imágen', '') let id = {} const blobUrl = URL.createObjectURL(file) // Replace the selection with a placeholder let tr = view.state.tr if (!tr.selection.empty) tr.deleteSelection() tr.setMeta(placeholderPlugin, { add: {id, pos: tr.selection.from, blobUrl}, }) view.dispatch(tr) uploadFile(file).then(url => { let pos = findPlaceholder(view.state, id) // If the content around the placeholder has been deleted, drop // the image if (pos == null) return // Otherwise, insert it at the placeholder's position, and remove // the placeholder view.dispatch( view.state.tr .replaceWith(pos, pos, schema.nodes.image.create({ src: url, alt: altText.length ? altText : undefined, })) .setMeta(placeholderPlugin, {remove: {id}}) ) }, () => { // On failure, just clean up the placeholder view.dispatch(tr.setMeta(placeholderPlugin, {remove: {id}})) }) } export function uploadFile (file) { return new Promise((resolve, reject) => { const upload = new DirectUpload( file, location.origin + '/rails/active_storage/direct_uploads', ) upload.create((error, blob) => { if (error) { reject(error) } else { const url = `${location.origin}/rails/active_storage/blobs/${blob.signed_id}/${blob.filename}` resolve(url) } }) }) }