mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-11-24 08:55:14 +03:00
Merge pull request #2513 from ecency/sa/editor-input-focus-bug
Bug Fix: Editor crash when draft opened and closed instantly or loaded one after the other instanly
This commit is contained in:
commit
8f1baef8c8
@ -48,9 +48,9 @@ import { EditorToolbar } from '../children/editorToolbar';
|
||||
import { extractImageUrls } from '../../../utils/editor';
|
||||
import { useAppSelector } from '../../../hooks';
|
||||
|
||||
const MIN_BODY_INPUT_HEIGHT = 300;
|
||||
// const MIN_BODY_INPUT_HEIGHT = 300;
|
||||
|
||||
//These variable keep track of body text input state,
|
||||
//These variable keep track of body text input state,
|
||||
//this helps keep load on minimal compared to both useState and useRef;
|
||||
var bodyText = '';
|
||||
var bodySelection = { start: 0, end: 0 };
|
||||
@ -74,24 +74,23 @@ const MarkdownEditorView = ({
|
||||
autoFocusText,
|
||||
sharedSnippetText,
|
||||
onLoadDraftPress,
|
||||
setIsUploading
|
||||
setIsUploading,
|
||||
}) => {
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const isDarkTheme = useAppSelector(state => state.application.isDarkTheme);
|
||||
const isDarkTheme = useAppSelector((state) => state.application.isDarkTheme);
|
||||
|
||||
const [editable, setEditable] = useState(true);
|
||||
const [bodyInputHeight, setBodyInputHeight] = useState(MIN_BODY_INPUT_HEIGHT);
|
||||
// const [bodyInputHeight, setBodyInputHeight] = useState(MIN_BODY_INPUT_HEIGHT);
|
||||
const [isSnippetsOpen, setIsSnippetsOpen] = useState(false);
|
||||
const [showDraftLoadButton, setShowDraftLoadButton] = useState(false);
|
||||
const [isEditing, setIsEditing] = useState(false);
|
||||
const [insertedMediaUrls, setInsertedMediaUrls] = useState([]);
|
||||
|
||||
|
||||
const inputRef = useRef(null);
|
||||
const clearRef = useRef(null);
|
||||
const insertLinkModalRef = useRef(null);
|
||||
const tooltipRef = useRef(null);
|
||||
const inputRef = useRef<any>(null);
|
||||
const clearRef = useRef<any>(null);
|
||||
const insertLinkModalRef = useRef<any>(null);
|
||||
const tooltipRef = useRef<any>(null);
|
||||
|
||||
const isVisibleAccountsBottomSheet = useSelector(
|
||||
(state) => state.ui.isVisibleAccountsBottomSheet,
|
||||
@ -164,7 +163,6 @@ const MarkdownEditorView = ({
|
||||
}
|
||||
}, [isLoading]);
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
bodyText = draftBody;
|
||||
}, [draftBody]);
|
||||
@ -173,13 +171,11 @@ const MarkdownEditorView = ({
|
||||
if (isReply || (autoFocusText && inputRef && inputRef.current && draftBtnTooltipRegistered)) {
|
||||
// added delay to open keyboard, solves the issue of keyboard not opening
|
||||
setTimeout(() => {
|
||||
inputRef.current.focus();
|
||||
inputRef?.current?.focus();
|
||||
}, 1000);
|
||||
}
|
||||
}, [autoFocusText]);
|
||||
|
||||
|
||||
|
||||
const changeUser = async () => {
|
||||
dispatch(toggleAccountsBottomSheet(!isVisibleAccountsBottomSheet));
|
||||
};
|
||||
@ -193,33 +189,37 @@ const MarkdownEditorView = ({
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const _debouncedOnTextChange = useCallback(debounce(() => {
|
||||
console.log("setting is editing to", false)
|
||||
setIsEditing(false)
|
||||
const urls = extractImageUrls({ body: bodyText })
|
||||
if (urls.length !== insertedMediaUrls.length) {
|
||||
setInsertedMediaUrls(urls);
|
||||
}
|
||||
}, 500), [])
|
||||
const _debouncedOnTextChange = useCallback(
|
||||
debounce(() => {
|
||||
console.log('setting is editing to', false);
|
||||
setIsEditing(false);
|
||||
const urls = extractImageUrls({ body: bodyText });
|
||||
if (urls.length !== insertedMediaUrls.length) {
|
||||
setInsertedMediaUrls(urls);
|
||||
}
|
||||
}, 500),
|
||||
[],
|
||||
);
|
||||
|
||||
// eslint-disable-next-line react-hooks/exhaustive-deps
|
||||
const _changeText = useCallback((input) => {
|
||||
bodyText = input;
|
||||
const _changeText = useCallback(
|
||||
(input) => {
|
||||
bodyText = input;
|
||||
|
||||
if (!isEditing) {
|
||||
console.log('force setting is editing to true', true)
|
||||
setIsEditing(true)
|
||||
}
|
||||
if (!isEditing) {
|
||||
console.log('force setting is editing to true', true);
|
||||
setIsEditing(true);
|
||||
}
|
||||
|
||||
_debouncedOnTextChange();
|
||||
|
||||
//NOTE: onChange method is called by direct parent of MarkdownEditor that is PostForm, do not remove
|
||||
if (onChange) {
|
||||
onChange(input);
|
||||
}
|
||||
}, [isEditing]);
|
||||
_debouncedOnTextChange();
|
||||
|
||||
//NOTE: onChange method is called by direct parent of MarkdownEditor that is PostForm, do not remove
|
||||
if (onChange) {
|
||||
onChange(input);
|
||||
}
|
||||
},
|
||||
[isEditing],
|
||||
);
|
||||
|
||||
const _handleOnSelectionChange = async (event) => {
|
||||
bodySelection = event.nativeEvent.selection;
|
||||
@ -233,11 +233,11 @@ const MarkdownEditorView = ({
|
||||
});
|
||||
|
||||
const _updateSelection = () => {
|
||||
bodySelection = _selection
|
||||
bodySelection = _selection;
|
||||
inputRef?.current?.setNativeProps({
|
||||
selection: _selection,
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// Workaround for iOS selection update issue
|
||||
if (Platform.OS === 'ios') {
|
||||
@ -245,7 +245,7 @@ const MarkdownEditorView = ({
|
||||
_updateSelection();
|
||||
}, 100);
|
||||
} else {
|
||||
_updateSelection()
|
||||
_updateSelection();
|
||||
}
|
||||
|
||||
if (isSnippetsOpen) {
|
||||
@ -275,8 +275,6 @@ const MarkdownEditorView = ({
|
||||
setIsSnippetsOpen(false);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const _handleMediaInsert = (mediaArray: MediaInsertData[]) => {
|
||||
if (mediaArray.length) {
|
||||
applyMediaLink({
|
||||
@ -288,19 +286,16 @@ const MarkdownEditorView = ({
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
const _handleOnAddLinkPress = () => {
|
||||
insertLinkModalRef.current?.showModal({
|
||||
selectedText: bodyText.slice(bodySelection.start, bodySelection.end),
|
||||
selection: bodySelection,
|
||||
});
|
||||
inputRef.current?.blur();
|
||||
inputRef?.current?.blur();
|
||||
};
|
||||
|
||||
const _handleOnAddLinkSheetClose = () => {
|
||||
inputRef.current?.focus();
|
||||
inputRef?.current?.focus();
|
||||
};
|
||||
|
||||
const _handleInsertLink = ({ snippetText, selection }) => {
|
||||
@ -314,7 +309,6 @@ const MarkdownEditorView = ({
|
||||
insertLinkModalRef.current?.hideModal();
|
||||
};
|
||||
|
||||
|
||||
const _renderFloatingDraftButton = () => {
|
||||
if (showDraftLoadButton) {
|
||||
const _onPress = () => {
|
||||
@ -354,7 +348,7 @@ const MarkdownEditorView = ({
|
||||
_setTextAndSelection({ text: '', selection: { start: 0, end: 0 } });
|
||||
}
|
||||
};
|
||||
const _renderEditor = (editorScrollEnabled:boolean) => (
|
||||
const _renderEditor = (editorScrollEnabled: boolean) => (
|
||||
<>
|
||||
{isReply && !isEdit && <SummaryArea summary={headerText} />}
|
||||
{!isReply && (
|
||||
@ -397,38 +391,44 @@ const MarkdownEditorView = ({
|
||||
</View>
|
||||
)}
|
||||
{!isPreviewActive ? (
|
||||
<TextInput
|
||||
multiline
|
||||
autoCorrect={true}
|
||||
autoFocus={!draftBtnTooltipRegistered ? false : true}
|
||||
onChangeText={_changeText}
|
||||
onSelectionChange={_handleOnSelectionChange}
|
||||
placeholder={intl.formatMessage({
|
||||
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
|
||||
})}
|
||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||
selectionColor="#357ce6"
|
||||
style={styles.textWrapper}
|
||||
underlineColorAndroid="transparent"
|
||||
innerRef={inputRef}
|
||||
editable={editable}
|
||||
contextMenuHidden={false}
|
||||
scrollEnabled={editorScrollEnabled}
|
||||
/>
|
||||
<TextInput
|
||||
multiline
|
||||
autoCorrect={true}
|
||||
autoFocus={!draftBtnTooltipRegistered ? false : true}
|
||||
onChangeText={_changeText}
|
||||
onSelectionChange={_handleOnSelectionChange}
|
||||
placeholder={intl.formatMessage({
|
||||
id: isReply ? 'editor.reply_placeholder' : 'editor.default_placeholder',
|
||||
})}
|
||||
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
|
||||
selectionColor="#357ce6"
|
||||
style={styles.textWrapper}
|
||||
underlineColorAndroid="transparent"
|
||||
innerRef={inputRef}
|
||||
editable={editable}
|
||||
contextMenuHidden={false}
|
||||
scrollEnabled={editorScrollEnabled}
|
||||
/>
|
||||
) : (
|
||||
_renderPreview()
|
||||
)}
|
||||
</>
|
||||
);
|
||||
|
||||
const _editorWithScroll = <ScrollView style={styles.container}>{_renderEditor(false)}</ScrollView>;
|
||||
const _editorWithScroll = (
|
||||
<ScrollView style={styles.container}>{_renderEditor(false)}</ScrollView>
|
||||
);
|
||||
const _editorWithoutScroll = <View style={styles.container}>{_renderEditor(true)}</View>;
|
||||
|
||||
const _renderContent = () => {
|
||||
const _innerContent = (
|
||||
<>
|
||||
{isAndroidOreo() ? _editorWithoutScroll : _editorWithScroll}
|
||||
<UsernameAutofillBar text={bodyText} selection={bodySelection} onApplyUsername={_onApplyUsername} />
|
||||
<UsernameAutofillBar
|
||||
text={bodyText}
|
||||
selection={bodySelection}
|
||||
onApplyUsername={_onApplyUsername}
|
||||
/>
|
||||
{_renderFloatingDraftButton()}
|
||||
|
||||
<EditorToolbar
|
||||
@ -445,11 +445,10 @@ const MarkdownEditorView = ({
|
||||
text: bodyText,
|
||||
selection: bodySelection,
|
||||
setTextAndSelection: _setTextAndSelection,
|
||||
item
|
||||
})
|
||||
item,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
|
||||
</>
|
||||
);
|
||||
|
||||
@ -480,8 +479,6 @@ const MarkdownEditorView = ({
|
||||
<SnippetsModal handleOnSelect={_handleOnSnippetReceived} />
|
||||
</Modal>
|
||||
|
||||
|
||||
|
||||
<InsertLinkModal
|
||||
ref={insertLinkModalRef}
|
||||
handleOnInsertLink={_handleInsertLink}
|
||||
|
@ -31,7 +31,6 @@ import {
|
||||
extractMetadata,
|
||||
makeJsonMetadataForUpdate,
|
||||
createPatch,
|
||||
extractImageUrls,
|
||||
} from '../../../utils/editor';
|
||||
// import { generateSignature } from '../../../utils/image';
|
||||
|
||||
@ -55,7 +54,6 @@ import { PointActivityIds } from '../../../providers/ecency/ecency.types';
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
_isMounted = false;
|
||||
_updatedDraftFields = null;
|
||||
@ -267,9 +265,9 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
_loadMeta = (draft: any) => {
|
||||
const { dispatch, currentAccount } = this.props;
|
||||
// if meta exist on draft, get the index of 1st image in meta from images urls in body
|
||||
const body = draft.body;
|
||||
// const body = draft.body;
|
||||
if (draft.meta && draft.meta.image) {
|
||||
const urls = extractImageUrls({ body });
|
||||
// const urls = extractImageUrls({ body });
|
||||
this.setState({
|
||||
thumbUrl: draft.meta.image[0],
|
||||
});
|
||||
@ -434,7 +432,13 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
|
||||
//update draft is draftId is present
|
||||
if (draftId && draftField && !saveAsNew) {
|
||||
await updateDraft(draftId, draftField.title, draftField.body, draftField.tags, jsonMeta);
|
||||
await updateDraft(
|
||||
draftId,
|
||||
draftField.title || '',
|
||||
draftField.body,
|
||||
draftField.tags,
|
||||
jsonMeta,
|
||||
);
|
||||
|
||||
if (this._isMounted) {
|
||||
this.setState({
|
||||
@ -447,7 +451,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
//create new darft otherwise
|
||||
else if (draftField) {
|
||||
const response = await addDraft(
|
||||
draftField.title,
|
||||
draftField.title || '',
|
||||
draftField.body,
|
||||
draftField.tags,
|
||||
jsonMeta,
|
||||
@ -520,7 +524,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
const username = currentAccount && currentAccount.name ? currentAccount.name : '';
|
||||
|
||||
const draftField = {
|
||||
title: fields.title,
|
||||
title: fields.title || '',
|
||||
body: fields.body,
|
||||
tags: fields.tags && fields.tags.length > 0 ? fields.tags.toString() : '',
|
||||
author: username,
|
||||
@ -549,7 +553,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
intl,
|
||||
navigation,
|
||||
pinCode,
|
||||
userActivityMutation
|
||||
userActivityMutation,
|
||||
// isDefaultFooter,
|
||||
} = this.props;
|
||||
const { rewardType, isPostSending, thumbUrl, draftId, shouldReblog } = this.state;
|
||||
@ -570,7 +574,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
|
||||
const jsonMeta = makeJsonMetadata(meta, _tags);
|
||||
// TODO: check if permlink is available github: #314 https://github.com/ecency/ecency-mobile/pull/314
|
||||
let permlink = generatePermlink(fields.title);
|
||||
let permlink = generatePermlink(fields.title || '');
|
||||
|
||||
let dublicatePost;
|
||||
try {
|
||||
@ -580,7 +584,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
}
|
||||
|
||||
if (dublicatePost && dublicatePost.permlink === permlink) {
|
||||
permlink = generatePermlink(fields.title, true);
|
||||
permlink = generatePermlink(fields.title || '', true);
|
||||
}
|
||||
|
||||
const author = currentAccount.name;
|
||||
@ -611,7 +615,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
'',
|
||||
parentPermlink,
|
||||
permlink,
|
||||
fields.title,
|
||||
fields.title || '',
|
||||
fields.body,
|
||||
jsonMeta,
|
||||
options,
|
||||
@ -621,9 +625,9 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
console.log(response);
|
||||
// track user activity for points
|
||||
userActivityMutation.mutate({
|
||||
pointsTy:PointActivityIds.POST,
|
||||
transactionId:response.id
|
||||
})
|
||||
pointsTy: PointActivityIds.POST,
|
||||
transactionId: response.id,
|
||||
});
|
||||
|
||||
//reblog if flag is active
|
||||
if (shouldReblog) {
|
||||
@ -631,9 +635,9 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
.then((resp) => {
|
||||
//track user activity for points on reblog
|
||||
userActivityMutation.mutate({
|
||||
pointsTy:PointActivityIds.REBLOG,
|
||||
transactionId:resp.id
|
||||
})
|
||||
pointsTy: PointActivityIds.REBLOG,
|
||||
transactionId: resp.id,
|
||||
});
|
||||
console.log('Successfully reblogged post', resp);
|
||||
})
|
||||
.catch((err) => {
|
||||
@ -710,9 +714,9 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
.then((response) => {
|
||||
//record user activity for points
|
||||
userActivityMutation.mutate({
|
||||
pointsTy:PointActivityIds.COMMENT,
|
||||
transactionId:response.id
|
||||
})
|
||||
pointsTy: PointActivityIds.COMMENT,
|
||||
transactionId: response.id,
|
||||
});
|
||||
|
||||
AsyncStorage.setItem('temp-reply', '');
|
||||
this._handleSubmitSuccess();
|
||||
@ -785,7 +789,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
parentAuthor || '',
|
||||
parentPermlink || '',
|
||||
permlink,
|
||||
title,
|
||||
title || '',
|
||||
newBody,
|
||||
jsonMeta,
|
||||
null,
|
||||
@ -1001,7 +1005,7 @@ class EditorContainer extends Component<EditorContainerProps, any> {
|
||||
|
||||
addSchedule(
|
||||
data.permlink,
|
||||
data.fields.title,
|
||||
data.fields.title || '',
|
||||
data.fields.body,
|
||||
data.jsonMeta,
|
||||
options,
|
||||
@ -1150,9 +1154,9 @@ const mapStateToProps = (state) => ({
|
||||
});
|
||||
|
||||
const mapQueriesToProps = () => ({
|
||||
queryClient:useQueryClient(),
|
||||
userActivityMutation:useUserActivityMutation()
|
||||
})
|
||||
queryClient: useQueryClient(), // eslint-disable-line
|
||||
userActivityMutation: useUserActivityMutation(), // eslint-disable-line
|
||||
});
|
||||
|
||||
export default connect(mapStateToProps)(
|
||||
injectIntl((props) => <EditorContainer {...props} {...mapQueriesToProps()} />),
|
||||
|
Loading…
Reference in New Issue
Block a user