mirror of
https://github.com/TryGhost/Ghost.git
synced 2024-12-25 03:44:29 +03:00
Added drag/drop and paste support for video files
refs https://github.com/TryGhost/Team/issues/1229 - generalized `insertImageCards()` to `insertCardsFromFiles()` and added support for video cards - added `canInsertCardsFromFiles()` function so the editor can check before starting an editor run loop and generating an undo point
This commit is contained in:
parent
7e4a277163
commit
09cae883a8
@ -21,6 +21,7 @@ import {TrackedObject} from 'tracked-built-ins';
|
||||
import {action} from '@ember/object';
|
||||
import {assign} from '@ember/polyfills';
|
||||
import {camelize, capitalize} from '@ember/string';
|
||||
import {canInsertCardsFromFiles, insertCardsFromFiles} from '../utils/insert-cards-from-files';
|
||||
import {captureMessage} from '@sentry/browser';
|
||||
import {createParserPlugins} from '@tryghost/kg-parser-plugins';
|
||||
import {getContentFromPasteEvent} from 'mobiledoc-kit/utils/parse-utils';
|
||||
@ -29,7 +30,6 @@ import {getOwner} from '@ember/application';
|
||||
import {getParent} from '../lib/dnd/utils';
|
||||
import {utils as ghostHelperUtils} from '@tryghost/helpers';
|
||||
import {guidFor} from '@ember/object/internals';
|
||||
import {insertImageCards} from '../utils/insert-cards-from-files';
|
||||
import {run} from '@ember/runloop';
|
||||
import {inject as service} from '@ember/service';
|
||||
import {svgJar} from 'ghost-admin/helpers/svg-jar';
|
||||
@ -956,19 +956,11 @@ export default Component.extend({
|
||||
return;
|
||||
}
|
||||
|
||||
// if we have image files pasted, create an image card for each and set
|
||||
// the payload.files property which will cause the image to be auto-uploaded
|
||||
// NOTE: browser support varies as of May 2018:
|
||||
// - Safari: will paste all images
|
||||
// - Chrome: will only paste the first image
|
||||
// - Firefox: will not paste any images
|
||||
let images = Array.from(event.clipboardData.files).filter(file => file.type.indexOf('image') > -1);
|
||||
if (images.length > 0) {
|
||||
event.preventDefault();
|
||||
event.stopImmediatePropagation();
|
||||
|
||||
// if we have files pasted, create a card for each and set the
|
||||
// payload.files property which will cause the file to be auto-uploaded
|
||||
if (canInsertCardsFromFiles(event.clipboardData.files)) {
|
||||
editor.run((postEditor) => {
|
||||
insertImageCards(images, postEditor);
|
||||
insertCardsFromFiles(event.clipboardData.files, postEditor);
|
||||
});
|
||||
return;
|
||||
}
|
||||
@ -1139,14 +1131,11 @@ export default Component.extend({
|
||||
|
||||
event.preventDefault();
|
||||
|
||||
if (event.dataTransfer.files) {
|
||||
let images = Array.from(event.dataTransfer.files).filter(file => file.type.indexOf('image') > -1);
|
||||
if (images.length > 0) {
|
||||
this.editor.run((postEditor) => {
|
||||
insertImageCards(images, postEditor);
|
||||
});
|
||||
this._scrollCursorIntoView({jumpToCard: true});
|
||||
}
|
||||
if (canInsertCardsFromFiles(event.dataTransfer.files)) {
|
||||
this.editor.run((postEditor) => {
|
||||
insertCardsFromFiles(event.dataTransfer.files, postEditor);
|
||||
});
|
||||
this._scrollCursorIntoView({jumpToCard: true});
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -1,12 +1,22 @@
|
||||
// helper function to insert image cards at or after the current active section
|
||||
export function canInsertCardsFromFiles(files) {
|
||||
return filterAllowedFiles(files).length > 0;
|
||||
}
|
||||
|
||||
// helper function to insert cards at or after the current active section
|
||||
// used when pasting or dropping image files
|
||||
export function insertImageCards(files, postEditor) {
|
||||
let {builder, editor} = postEditor;
|
||||
let collection = editor.post.sections;
|
||||
export function insertCardsFromFiles(_files, postEditor) {
|
||||
const files = filterAllowedFiles(_files);
|
||||
|
||||
if (!files.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
const {builder, editor} = postEditor;
|
||||
const collection = editor.post.sections;
|
||||
let section = editor.activeSection;
|
||||
|
||||
// when dropping an image on the editor before it's had focus there will be
|
||||
// no active section so we insert the image at the end of the document
|
||||
// when dropping an file on the editor before it's had focus there will be
|
||||
// no active section so we insert the card at the end of the document
|
||||
if (!section) {
|
||||
section = editor.post.sections.tail;
|
||||
|
||||
@ -14,7 +24,7 @@ export function insertImageCards(files, postEditor) {
|
||||
// we use `insertSectionBefore` and don't want the image to be added
|
||||
// before the last card
|
||||
if (!section.isMarkerable) {
|
||||
let blank = builder.createMarkupSection();
|
||||
const blank = builder.createMarkupSection();
|
||||
postEditor.insertSectionAtEnd(blank);
|
||||
postEditor.setRange(blank.toRange());
|
||||
section = postEditor._range.head.section;
|
||||
@ -29,8 +39,8 @@ export function insertImageCards(files, postEditor) {
|
||||
// list items cannot contain card sections so insert a blank paragraph after
|
||||
// the whole list ready to be replaced by the image cards
|
||||
if (section.isListItem) {
|
||||
let list = section.parent;
|
||||
let blank = builder.createMarkupSection();
|
||||
const list = section.parent;
|
||||
const blank = builder.createMarkupSection();
|
||||
if (list.next) {
|
||||
postEditor.insertSectionBefore(collection, blank, list.next);
|
||||
} else {
|
||||
@ -40,15 +50,16 @@ export function insertImageCards(files, postEditor) {
|
||||
section = postEditor._range.head.section;
|
||||
}
|
||||
|
||||
// insert an image card for each image, keep track of the last card to be
|
||||
// insert a card for each file, keep track of the last card to be
|
||||
// inserted so that the cursor can be placed on it at the end
|
||||
let lastImageSection;
|
||||
let lastCardSection;
|
||||
files.forEach((file) => {
|
||||
let payload = {
|
||||
const cardName = getCardNameFromFile(file);
|
||||
const payload = {
|
||||
files: [file]
|
||||
};
|
||||
lastImageSection = builder.createCardSection('image', payload);
|
||||
postEditor.insertSectionBefore(collection, lastImageSection, section);
|
||||
lastCardSection = builder.createCardSection(cardName, payload);
|
||||
postEditor.insertSectionBefore(collection, lastCardSection, section);
|
||||
});
|
||||
|
||||
// remove the current section if it's blank - avoids unexpected blank
|
||||
@ -58,5 +69,19 @@ export function insertImageCards(files, postEditor) {
|
||||
}
|
||||
|
||||
// place cursor on the last inserted image
|
||||
postEditor.setRange(lastImageSection.tailPosition());
|
||||
postEditor.setRange(lastCardSection.tailPosition());
|
||||
}
|
||||
|
||||
function filterAllowedFiles(files) {
|
||||
return Array.from(files).filter(file => file.type.match(/^(image|video)/));
|
||||
}
|
||||
|
||||
function getCardNameFromFile(file) {
|
||||
if (file.type.startsWith('image')) {
|
||||
return 'image';
|
||||
}
|
||||
|
||||
if (file.type.startsWith('video')) {
|
||||
return 'video';
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user