Commit a2bb3efa authored by Яков's avatar Яков
Browse files

update fix issue

parent 18e10c9c
{ {
"name": "react-ag-qeditor", "name": "react-ag-qeditor",
"version": "1.1.49", "version": "1.1.50",
"description": "WYSIWYG html editor", "description": "WYSIWYG html editor",
"author": "atma", "author": "atma",
"license": "MIT", "license": "MIT",
......
...@@ -53,7 +53,7 @@ import { isMobile } from 'react-device-detect' ...@@ -53,7 +53,7 @@ import { isMobile } from 'react-device-detect'
import { ExportPdf } from './extensions/ExportPdf' import { ExportPdf } from './extensions/ExportPdf'
import { mergeAttributes } from "@tiptap/core"; import { mergeAttributes } from "@tiptap/core";
import Upload from "rc-upload"; import Upload from "rc-upload";
import { NodeSelection } from 'prosemirror-state' import { NodeSelection, TextSelection } from 'prosemirror-state'
// const CustomImage = Image.extend({ // const CustomImage = Image.extend({
// options: {inline: true}, // options: {inline: true},
...@@ -1540,7 +1540,13 @@ const QEditor = ({ ...@@ -1540,7 +1540,13 @@ const QEditor = ({
align: 'center', align: 'center',
'data-node-id': `img-${Date.now()}-${Math.random().toString(36).slice(2, 10)}` 'data-node-id': `img-${Date.now()}-${Math.random().toString(36).slice(2, 10)}`
}) })
.createParagraphNear() .command(({ tr, state }) => {
// После setImage курсор — NodeSelection на картинке.
// Переводим в TextSelection сразу после неё.
const { $to } = state.selection
tr.setSelection(TextSelection.create(tr.doc, $to.pos))
return true
})
.run() .run()
} }
}) })
......
...@@ -2,15 +2,90 @@ import React, { Fragment } from "react"; ...@@ -2,15 +2,90 @@ import React, { Fragment } from "react";
import Upload from "rc-upload"; import Upload from "rc-upload";
import axios from "axios"; import axios from "axios";
// Читает EXIF-тег ориентации из JPEG-файла (только первые 64 КБ)
function getExifOrientation(file) {
return new Promise((resolve) => {
const reader = new FileReader()
reader.onload = (e) => {
const view = new DataView(e.target.result)
if (view.getUint16(0, false) !== 0xFFD8) { resolve(1); return }
let offset = 2
while (offset < view.byteLength) {
const marker = view.getUint16(offset, false)
offset += 2
if (marker === 0xFFE1) {
if (view.getUint32(offset + 2, false) !== 0x45786966) { resolve(1); return }
const little = view.getUint16(offset + 8, false) === 0x4949
const ifdStart = offset + 8 + view.getUint32(offset + 12, little)
const entries = view.getUint16(ifdStart, little)
for (let i = 0; i < entries; i++) {
if (view.getUint16(ifdStart + 2 + 12 * i, little) === 0x0112) {
resolve(view.getUint16(ifdStart + 2 + 12 * i + 8, little))
return
}
}
resolve(1); return
} else if ((marker & 0xFF00) !== 0xFF00) {
break
} else {
offset += view.getUint16(offset, false)
}
}
resolve(1)
}
reader.readAsArrayBuffer(file.slice(0, 65536))
})
}
// Поворачивает JPEG на canvas согласно EXIF-ориентации, возвращает исправленный File
function fixImageOrientation(file) {
if (!file.type.match(/^image\/(jpeg|jpg)/i)) return Promise.resolve(file)
return getExifOrientation(file).then(orientation => {
if (orientation <= 1) return file
return new Promise(resolve => {
const img = new window.Image()
img.onload = () => {
const { naturalWidth: w, naturalHeight: h } = img
const canvas = document.createElement('canvas')
const ctx = canvas.getContext('2d')
// Для поворотов 5–8 меняем местами ширину и высоту
if (orientation >= 5) { canvas.width = h; canvas.height = w }
else { canvas.width = w; canvas.height = h }
const transforms = {
2: [-1, 0, 0, 1, w, 0],
3: [-1, 0, 0, -1, w, h],
4: [ 1, 0, 0, -1, 0, h],
5: [ 0, 1, 1, 0, 0, 0],
6: [ 0, 1,-1, 0, h, 0],
7: [ 0,-1,-1, 0, h, w],
8: [ 0,-1, 1, 0, 0, w],
}
if (transforms[orientation]) ctx.transform(...transforms[orientation])
ctx.drawImage(img, 0, 0)
URL.revokeObjectURL(img.src)
canvas.toBlob(
blob => resolve(new File([blob], file.name, { type: file.type, lastModified: Date.now() })),
file.type,
0.92
)
}
img.src = URL.createObjectURL(file)
})
})
}
class Item extends React.Component { class Item extends React.Component {
get src () { get src () {
return this.props.src; return this.props.src;
} }
render () { render () {
switch (this.src) { switch (this.src) {
default: default:
return null; return null;
} }
...@@ -37,10 +112,6 @@ export default class Uploader extends React.Component { ...@@ -37,10 +112,6 @@ export default class Uploader extends React.Component {
this.files = {}; this.files = {};
} }
// componentDidUpdate (prevProps, prevState, snapshot) {
// console.log(this.state.files);
// }
get action () { get action () {
return this.props.action; return this.props.action;
} }
...@@ -73,6 +144,10 @@ export default class Uploader extends React.Component { ...@@ -73,6 +144,10 @@ export default class Uploader extends React.Component {
return this.props.modalType; return this.props.modalType;
} }
get processingMessage () {
return this.props.processingMessage;
}
mediaItem(){ mediaItem(){
} }
...@@ -102,12 +177,8 @@ export default class Uploader extends React.Component { ...@@ -102,12 +177,8 @@ export default class Uploader extends React.Component {
} }
} }
get processingMessage () {
return this.props.processingMessage;
}
render () { render () {
let {disabledFileUpload, isUpload, progress, dropFiles} = this.state; let {disabledFileUpload, isUpload} = this.state;
if(this.action === null){ if(this.action === null){
return <div style={{ textAlign: 'left' }}>{ this.errorMessage }</div> return <div style={{ textAlign: 'left' }}>{ this.errorMessage }</div>
...@@ -153,24 +224,35 @@ export default class Uploader extends React.Component { ...@@ -153,24 +224,35 @@ export default class Uploader extends React.Component {
action={this.action} action={this.action}
multiple={this.multiple} multiple={this.multiple}
disabled={disabledFileUpload} disabled={disabledFileUpload}
beforeUpload={(a, files) => { beforeUpload={(a) => {
this.files[a.uid] = {...a, percent: 0, uploaded: false}; this.files[a.uid] = {...a, percent: 0, uploaded: false};
this.setState({ isUpload: true, files: this.files });
this.setState({
isUpload: true,
files: this.files
});
}} }}
onStart={(a) => { onStart={() => {
this.setState({disabledFileUpload: true, isUpload: true}); this.setState({disabledFileUpload: true, isUpload: true});
// console.log('start'); }}
customRequest={({ file, action, onSuccess, onError, onProgress }) => {
fixImageOrientation(file).then(correctedFile => {
const data = new FormData()
data.append('file', correctedFile, correctedFile.name)
axios.post(action, data, {
headers: { 'Content-Type': 'multipart/form-data' },
withCredentials: true,
onUploadProgress: (e) => {
const percent = e.total ? Math.round((e.loaded * 100) / e.total) : 0
onProgress({ percent }, file)
}
})
.then(response => onSuccess(response.data, file))
.catch(err => onError(err))
})
}} }}
onSuccess={(resp, file) => { onSuccess={(resp, file) => {
if (resp.state === 'success' && resp.file_path) { if (resp.state === 'success' && resp.file_path) {
let curFile = this.files[file.uid]; let curFile = this.files[file.uid];
curFile['uploaded'] = true; curFile['uploaded'] = true;
curFile['path'] = resp.poster || resp.file_path; curFile['path'] = resp.poster || resp.file_path;
curFile['name'] = resp.file_name; curFile['name'] = resp.file_name;
curFile['size'] = resp.file_size; curFile['size'] = resp.file_size;
...@@ -195,22 +277,16 @@ export default class Uploader extends React.Component { ...@@ -195,22 +277,16 @@ export default class Uploader extends React.Component {
} }
}); });
} }
if (resp.state === 'success' && resp.html) { if (resp.state === 'success' && resp.html) {
this.setState({html: resp.html, uploaderSuccess: true}, () => this.onSuccess(undefined, resp.html)) this.setState({html: resp.html, uploaderSuccess: true}, () => this.onSuccess(undefined, resp.html))
} }
}} }}
onProgress={(o, file) => { onProgress={(o, file) => {
if (this.files[file.uid]) { if (this.files[file.uid]) {
this.files[file.uid].percent = parseInt(o.percent); this.files[file.uid].percent = parseInt(o.percent);
} }
// this.setState({ files: this.files })
this.setState({
files: this.files
})
// console.log(o, file);
}} }}
component={'div'} component={'div'}
type="drag" type="drag"
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment