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:
Feruz M 2022-10-19 06:51:04 +05:30 committed by GitHub
commit 8f1baef8c8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 99 additions and 98 deletions

View File

@ -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}

View File

@ -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()} />),