Merge branch 'feature/rich_text_editor' of https://code.gab.com/gab/social/gab-social into develop
This commit is contained in:
@@ -15,6 +15,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
|
||||
static propTypes = {
|
||||
value: PropTypes.string,
|
||||
valueMarkdown: PropTypes.string,
|
||||
suggestions: ImmutablePropTypes.list,
|
||||
disabled: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
@@ -45,11 +46,12 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
tokenStart: 0,
|
||||
}
|
||||
|
||||
onChange = (e, value, selectionStart, markdown) => {
|
||||
onChange = (e, value, markdown, selectionStart) => {
|
||||
if (!isObject(e)) {
|
||||
e = {
|
||||
target: {
|
||||
value,
|
||||
markdown,
|
||||
selectionStart,
|
||||
},
|
||||
}
|
||||
@@ -65,7 +67,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
this.props.onSuggestionsClearRequested();
|
||||
}
|
||||
|
||||
this.props.onChange(e, markdown);
|
||||
this.props.onChange(e);
|
||||
}
|
||||
|
||||
onKeyDown = (e) => {
|
||||
@@ -191,7 +193,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
}
|
||||
|
||||
setTextbox = (c) => {
|
||||
this.textbox = c;
|
||||
this.textbox = c
|
||||
}
|
||||
|
||||
render() {
|
||||
@@ -203,6 +205,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
placeholder,
|
||||
onKeyUp,
|
||||
children,
|
||||
valueMarkdown,
|
||||
id,
|
||||
} = this.props
|
||||
|
||||
@@ -246,29 +249,14 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
<label htmlFor={id} className={_s.visiblyHidden}>
|
||||
{placeholder}
|
||||
</label>
|
||||
<Textarea
|
||||
id={id}
|
||||
inputRef={this.setTextbox}
|
||||
className={textareaClasses}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
autoFocus={false}
|
||||
value={value}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={onKeyUp}
|
||||
onFocus={this.onFocus}
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
aria-autocomplete='list'
|
||||
/>
|
||||
|
||||
{/*<Composer
|
||||
<Composer
|
||||
inputRef={this.setTextbox}
|
||||
disabled={disabled}
|
||||
placeholder={placeholder}
|
||||
autoFocus={autoFocus}
|
||||
value={value}
|
||||
valueMarkdown={valueMarkdown}
|
||||
onChange={this.onChange}
|
||||
onKeyDown={this.onKeyDown}
|
||||
onKeyUp={onKeyUp}
|
||||
@@ -276,7 +264,7 @@ export default class AutosuggestTextbox extends ImmutablePureComponent {
|
||||
onBlur={this.onBlur}
|
||||
onPaste={this.onPaste}
|
||||
small={small}
|
||||
/>*/}
|
||||
/>
|
||||
|
||||
{children}
|
||||
</div>
|
||||
|
||||
@@ -7,8 +7,8 @@ import {
|
||||
convertFromRaw,
|
||||
ContentState,
|
||||
} from 'draft-js'
|
||||
import { draftToMarkdown } from 'markdown-draft-js'
|
||||
// import draftToMarkdown from 'draftjs-to-markdown'
|
||||
import draftToMarkdown from '../features/ui/util/draft-to-markdown'
|
||||
import markdownToDraft from '../features/ui/util/markdown-to-draft'
|
||||
import { urlRegex } from '../features/ui/util/url_regex'
|
||||
import classNames from 'classnames/bind'
|
||||
import RichTextEditorBar from './rich_text_editor_bar'
|
||||
@@ -30,11 +30,11 @@ function handleStrategy(contentBlock, callback, contentState) {
|
||||
findWithRegex(HANDLE_REGEX, contentBlock, callback)
|
||||
}
|
||||
|
||||
function hashtagStrategy (contentBlock, callback, contentState) {
|
||||
function hashtagStrategy(contentBlock, callback, contentState) {
|
||||
findWithRegex(HASHTAG_REGEX, contentBlock, callback)
|
||||
}
|
||||
|
||||
function urlStrategy (contentBlock, callback, contentState) {
|
||||
function urlStrategy(contentBlock, callback, contentState) {
|
||||
findWithRegex(urlRegex, contentBlock, callback)
|
||||
}
|
||||
|
||||
@@ -73,24 +73,17 @@ const compositeDecorator = new CompositeDecorator([
|
||||
}
|
||||
])
|
||||
|
||||
const HANDLE_REGEX = /\@[\w]+/g;
|
||||
const HASHTAG_REGEX = /\#[\w\u0590-\u05ff]+/g;
|
||||
const HANDLE_REGEX = /\@[\w]+/g
|
||||
const HASHTAG_REGEX = /\#[\w\u0590-\u05ff]+/g
|
||||
|
||||
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
|
||||
})
|
||||
|
||||
export default
|
||||
@connect(null, mapDispatchToProps)
|
||||
class Composer extends PureComponent {
|
||||
export default class Composer extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
inputRef: PropTypes.func,
|
||||
disabled: PropTypes.bool,
|
||||
placeholder: PropTypes.string,
|
||||
autoFocus: PropTypes.bool,
|
||||
value: PropTypes.string,
|
||||
valueMarkdown: PropTypes.string,
|
||||
onChange: PropTypes.func,
|
||||
onKeyDown: PropTypes.func,
|
||||
onKeyUp: PropTypes.func,
|
||||
@@ -101,59 +94,69 @@ class Composer extends PureComponent {
|
||||
}
|
||||
|
||||
state = {
|
||||
markdownText: '',
|
||||
plainText: '',
|
||||
editorState: EditorState.createEmpty(compositeDecorator),
|
||||
}
|
||||
|
||||
static getDerivedStateFromProps(nextProps, prevState) {
|
||||
// if (!nextProps.isHidden && nextProps.isIntersecting && !prevState.fetched) {
|
||||
// return {
|
||||
// fetched: true
|
||||
// }
|
||||
// }
|
||||
|
||||
return null
|
||||
plainText: this.props.value,
|
||||
}
|
||||
|
||||
componentDidUpdate (prevProps) {
|
||||
// console.log("this.props.value:", this.props.value)
|
||||
if (prevProps.value !== this.props.value) {
|
||||
// const editorState = EditorState.push(this.state.editorState, ContentState.createFromText(this.props.value));
|
||||
// this.setState({ editorState })
|
||||
componentDidMount() {
|
||||
if (this.props.valueMarkdown) {
|
||||
const rawData = markdownToDraft(this.props.valueMarkdown)
|
||||
const contentState = convertFromRaw(rawData)
|
||||
const editorState = EditorState.createWithContent(contentState)
|
||||
this.setState({
|
||||
editorState,
|
||||
plainText: this.props.value,
|
||||
})
|
||||
} else if (this.props.value) {
|
||||
editorState = EditorState.push(this.state.editorState, ContentState.createFromText(this.props.value))
|
||||
this.setState({
|
||||
editorState,
|
||||
plainText: this.props.value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// EditorState.createWithContent(ContentState.createFromText('Hello'))
|
||||
|
||||
onChange = (editorState) => {
|
||||
this.setState({ editorState })
|
||||
const content = this.state.editorState.getCurrentContent();
|
||||
const text = content.getPlainText('\u0001')
|
||||
|
||||
// const selectionState = editorState.getSelection()
|
||||
// const selectionStart = selectionState.getStartOffset()
|
||||
|
||||
// const rawObject = convertToRaw(content);
|
||||
// const markdownString = draftToMarkdown(rawObject);
|
||||
// const markdownString = draftToMarkdown(rawObject, {
|
||||
// trigger: '#',
|
||||
// separator: ' ',
|
||||
// });
|
||||
|
||||
// console.log("text:", text, this.props.value)
|
||||
|
||||
this.props.onChange(null, text, selectionStart, markdownString)
|
||||
componentDidUpdate() {
|
||||
if (this.state.plainText !== this.props.value) {
|
||||
let editorState
|
||||
if (!this.props.value) {
|
||||
editorState = EditorState.createEmpty(compositeDecorator)
|
||||
} else {
|
||||
editorState = EditorState.push(this.state.editorState, ContentState.createFromText(this.props.value))
|
||||
}
|
||||
this.setState({
|
||||
editorState,
|
||||
plainText: this.props.value,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
// **bold**
|
||||
// *italic*
|
||||
// __underline__
|
||||
// ~strikethrough~
|
||||
// # title
|
||||
// > quote
|
||||
// `code`
|
||||
// ```code```
|
||||
onChange = (editorState) => {
|
||||
const content = editorState.getCurrentContent()
|
||||
const plainText = content.getPlainText('\u0001')
|
||||
|
||||
this.setState({ editorState, plainText })
|
||||
|
||||
const selectionState = editorState.getSelection()
|
||||
const selectionStart = selectionState.getStartOffset()
|
||||
|
||||
const rawObject = convertToRaw(content)
|
||||
const markdownString = draftToMarkdown(rawObject, {
|
||||
escapeMarkdownCharacters: false,
|
||||
preserveNewlines: false,
|
||||
remarkablePreset: 'commonmark',
|
||||
remarkableOptions: {
|
||||
disable: {
|
||||
block: ['table']
|
||||
},
|
||||
enable: {
|
||||
inline: ['del', 'ins'],
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
this.props.onChange(null, plainText, markdownString, selectionStart)
|
||||
}
|
||||
|
||||
focus = () => {
|
||||
this.textbox.editor.focus()
|
||||
@@ -171,27 +174,24 @@ class Composer extends PureComponent {
|
||||
return false
|
||||
}
|
||||
|
||||
handleOnTogglePopoutEditor = () => {
|
||||
//
|
||||
}
|
||||
|
||||
onTab = (e) => {
|
||||
const maxDepth = 4
|
||||
this.onChange(RichUtils.onTab(e, this.state.editorState, maxDepth))
|
||||
}
|
||||
|
||||
setRef = (n) => {
|
||||
this.textbox = n
|
||||
try {
|
||||
this.textbox = n
|
||||
this.props.inputRef(n)
|
||||
} catch (error) {
|
||||
//
|
||||
}
|
||||
}
|
||||
|
||||
render() {
|
||||
const {
|
||||
inputRef,
|
||||
disabled,
|
||||
placeholder,
|
||||
autoFocus,
|
||||
value,
|
||||
onChange,
|
||||
onKeyDown,
|
||||
onKeyUp,
|
||||
onFocus,
|
||||
@@ -211,15 +211,13 @@ class Composer extends PureComponent {
|
||||
pt15: !small,
|
||||
px15: !small,
|
||||
px10: small,
|
||||
pt5: small,
|
||||
pb5: small,
|
||||
pb10: !small,
|
||||
})
|
||||
|
||||
return (
|
||||
<div className={_s.default}>
|
||||
|
||||
{ /** : todo : */
|
||||
{
|
||||
!small &&
|
||||
<RichTextEditorBar
|
||||
editorState={editorState}
|
||||
@@ -241,6 +239,9 @@ class Composer extends PureComponent {
|
||||
placeholder={placeholder}
|
||||
ref={this.setRef}
|
||||
readOnly={disabled}
|
||||
onBlur={onBlur}
|
||||
onFocus={onFocus}
|
||||
stripPastedStyles
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -42,6 +42,7 @@ class ProUpgradeModal extends ImmutablePureComponent {
|
||||
<Text>• Larger Video and Image Uploads</Text>
|
||||
<Text>• Receive the PRO Badge</Text>
|
||||
<Text>• Remove in-feed promotions</Text>
|
||||
<Text>• Compose Rich Text posts (Bold, Italic, Underline and more)</Text>
|
||||
</div>
|
||||
|
||||
<Button
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
import { RichUtils } from 'draft-js'
|
||||
import { defineMessages, injectIntl } from 'react-intl'
|
||||
import classNames from 'classnames/bind'
|
||||
import { me } from '../initial_state'
|
||||
import { makeGetAccount } from '../selectors'
|
||||
@@ -39,41 +38,37 @@ const RTE_ITEMS = [
|
||||
// icon: 'circle',
|
||||
// },
|
||||
{
|
||||
label: 'H1',
|
||||
label: 'Title',
|
||||
style: 'header-one',
|
||||
type: 'block',
|
||||
icon: 'text-size',
|
||||
},
|
||||
{
|
||||
label: 'Blockquote',
|
||||
style: 'blockquote',
|
||||
type: 'block',
|
||||
icon: 'blockquote',
|
||||
},
|
||||
{
|
||||
label: 'Code Block',
|
||||
style: 'code-block',
|
||||
type: 'block',
|
||||
icon: 'code',
|
||||
},
|
||||
{
|
||||
label: 'UL',
|
||||
style: 'unordered-list-item',
|
||||
type: 'block',
|
||||
icon: 'ul-list',
|
||||
},
|
||||
{
|
||||
label: 'OL',
|
||||
style: 'ordered-list-item',
|
||||
type: 'block',
|
||||
icon: 'ol-list',
|
||||
},
|
||||
// {
|
||||
// label: 'Blockquote',
|
||||
// style: 'blockquote',
|
||||
// type: 'block',
|
||||
// icon: 'blockquote',
|
||||
// },
|
||||
// {
|
||||
// label: 'Code Block',
|
||||
// style: 'code-block',
|
||||
// type: 'block',
|
||||
// icon: 'code',
|
||||
// },
|
||||
// {
|
||||
// label: 'UL',
|
||||
// style: 'unordered-list-item',
|
||||
// type: 'block',
|
||||
// icon: 'ul-list',
|
||||
// },
|
||||
// {
|
||||
// label: 'OL',
|
||||
// style: 'ordered-list-item',
|
||||
// type: 'block',
|
||||
// icon: 'ol-list',
|
||||
// },
|
||||
]
|
||||
|
||||
const messages = defineMessages({
|
||||
follow: { id: 'follow', defaultMessage: 'Follow' },
|
||||
})
|
||||
|
||||
const mapStateToProps = (state) => {
|
||||
const getAccount = makeGetAccount()
|
||||
const account = getAccount(state, me)
|
||||
@@ -86,13 +81,11 @@ const mapStateToProps = (state) => {
|
||||
}
|
||||
|
||||
export default
|
||||
@injectIntl
|
||||
@connect(mapStateToProps)
|
||||
class RichTextEditorBar extends PureComponent {
|
||||
|
||||
static propTypes = {
|
||||
editorState: PropTypes.object.isRequired,
|
||||
intl: PropTypes.object.isRequired,
|
||||
isPro: PropTypes.bool.isRequired,
|
||||
rteControlsVisible: PropTypes.bool.isRequired,
|
||||
onChange: PropTypes.func.isRequired,
|
||||
@@ -127,7 +120,7 @@ class RichTextEditorBar extends PureComponent {
|
||||
/>
|
||||
))
|
||||
}
|
||||
<Button
|
||||
{/*<Button
|
||||
backgroundColor='none'
|
||||
color='secondary'
|
||||
onClick={this.handleOnTogglePopoutEditor}
|
||||
@@ -137,7 +130,7 @@ class RichTextEditorBar extends PureComponent {
|
||||
iconClassName={_s.inheritFill}
|
||||
iconSize='12px'
|
||||
radiusSmall
|
||||
/>
|
||||
/>*/}
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ class TimelineComposeBlock extends ImmutablePureComponent {
|
||||
return (
|
||||
<section className={_s.default}>
|
||||
<div className={[_s.default, _s.flexRow].join(' ')}>
|
||||
<ComposeFormContainer {...rest} />
|
||||
<ComposeFormContainer {...rest} modal={modal} />
|
||||
</div>
|
||||
</section>
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user