Merge pull request #1887 from ecency/nt/post-draft-master

Nt/post draft master
This commit is contained in:
Feruz M 2021-03-31 22:20:32 +03:00 committed by GitHub
commit 8c214a0927
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 598 additions and 401 deletions

File diff suppressed because one or more lines are too long

View File

@ -1,22 +1,22 @@
PODS: PODS:
- appcenter-analytics (3.1.0): - appcenter-analytics (4.1.0):
- AppCenter/Analytics - AppCenter/Analytics (~> 4.0)
- AppCenterReactNativeShared - AppCenterReactNativeShared (~> 4.0)
- React - React-Core
- appcenter-core (3.1.0): - appcenter-core (4.1.0):
- AppCenterReactNativeShared - AppCenterReactNativeShared (~> 4.0)
- React - React-Core
- appcenter-crashes (3.1.0): - appcenter-crashes (4.1.0):
- AppCenter/Crashes - AppCenter/Crashes (~> 4.0)
- AppCenterReactNativeShared - AppCenterReactNativeShared (~> 4.0)
- React - React-Core
- AppCenter/Analytics (3.3.4): - AppCenter/Analytics (4.1.1):
- AppCenter/Core - AppCenter/Core
- AppCenter/Core (3.3.4) - AppCenter/Core (4.1.1)
- AppCenter/Crashes (3.3.4): - AppCenter/Crashes (4.1.1):
- AppCenter/Core - AppCenter/Core
- AppCenterReactNativeShared (3.1.2): - AppCenterReactNativeShared (4.1.0):
- AppCenter/Core (= 3.3.4) - AppCenter/Core (= 4.1.1)
- boost-for-react-native (1.63.0) - boost-for-react-native (1.63.0)
- BugsnagReactNative (2.23.10): - BugsnagReactNative (2.23.10):
- BugsnagReactNative/Core (= 2.23.10) - BugsnagReactNative/Core (= 2.23.10)
@ -641,11 +641,11 @@ EXTERNAL SOURCES:
:path: "../node_modules/react-native/ReactCommon/yoga" :path: "../node_modules/react-native/ReactCommon/yoga"
SPEC CHECKSUMS: SPEC CHECKSUMS:
AppCenter: 0487be185c038ed2ecc5ed38219af1dcd280af23 AppCenter: cd53e3ed3563cc720bcb806c9731a12389b40d44
appcenter-analytics: cca12b5d07593a309e99db475f6da7f1a61ae694 appcenter-analytics: aa074250b2cb182d6f7d67d9c236dd4606673ab5
appcenter-core: cd5eaa48cfc6dd87dad2912d6718f21f4955327f appcenter-core: c97920e79eba2321a262d3733cb2a6f1097db539
appcenter-crashes: 369cc9160392c137b791304ee96957f28ef143d1 appcenter-crashes: 804ae51c5d1742ce20fdb6a68b3d06208a404ad5
AppCenterReactNativeShared: 66667cd2dfad295b84bbf0f462e0e139e2128284 AppCenterReactNativeShared: 2d5a53b6cbd2fe7f63f0033e9f0a40757a4eacf5
boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c boost-for-react-native: 39c7adb57c4e60d6c5479dd8623128eb5b3f0f2c
BugsnagReactNative: 98fb350df4bb0c94cce903023531a1a5cc11fa51 BugsnagReactNative: 98fb350df4bb0c94cce903023531a1a5cc11fa51
BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872 BVLinearGradient: e3aad03778a456d77928f594a649e96995f1c872

View File

@ -45,9 +45,9 @@
"@react-native-firebase/app": "^8.4.7", "@react-native-firebase/app": "^8.4.7",
"@react-native-firebase/dynamic-links": "^7.4.2", "@react-native-firebase/dynamic-links": "^7.4.2",
"@react-native-firebase/messaging": "^7.4.2", "@react-native-firebase/messaging": "^7.4.2",
"appcenter": "3.1.0", "appcenter": "^4.1.0",
"appcenter-analytics": "3.1.0", "appcenter-analytics": "^4.1.0",
"appcenter-crashes": "3.1.0", "appcenter-crashes": "^4.1.0",
"axios": "^0.21.1", "axios": "^0.21.1",
"buffer": "^5.4.3", "buffer": "^5.4.3",
"bugsnag-react-native": "^2.23.10", "bugsnag-react-native": "^2.23.10",

View File

@ -1,4 +1,5 @@
import EStyleSheet from 'react-native-extended-stylesheet'; import EStyleSheet from 'react-native-extended-stylesheet';
import { Platform } from 'react-native';
export default EStyleSheet.create({ export default EStyleSheet.create({
container: { container: {
@ -9,12 +10,12 @@ export default EStyleSheet.create({
textWrapper: { textWrapper: {
fontSize: 12, fontSize: 12,
paddingTop: 16, paddingTop: 16,
paddingBottom: 0, // On android side, textinput has default padding paddingBottom: Platform.OS === 'ios' ? 32 : 0, // On android side, textinput has default padding
paddingHorizontal: 16, paddingHorizontal: 16,
color: '$primaryBlack', color: '$primaryBlack',
backgroundColor: '$primaryBackgroundColor', backgroundColor: '$primaryBackgroundColor',
// fontFamily: '$editorFont', minHeight: 200,
// textAlignVertical: 'top', textAlignVertical: 'top',
}, },
previewContainer: { previewContainer: {
flex: 1, flex: 1,

View File

@ -41,6 +41,8 @@ import { ThemeContainer } from '../../../containers';
import styles from './markdownEditorStyles'; import styles from './markdownEditorStyles';
import applySnippet from './formats/applySnippet'; import applySnippet from './formats/applySnippet';
const MIN_BODY_INPUT_HEIGHT = 200;
const MarkdownEditorView = ({ const MarkdownEditorView = ({
draftBody, draftBody,
handleIsFormValid, handleIsFormValid,
@ -66,7 +68,7 @@ const MarkdownEditorView = ({
const [text, setText] = useState(draftBody || ''); const [text, setText] = useState(draftBody || '');
const [selection, setSelection] = useState({ start: 0, end: 0 }); const [selection, setSelection] = useState({ start: 0, end: 0 });
const [editable, setEditable] = useState(true); const [editable, setEditable] = useState(true);
const [height, setHeight] = useState(0); const [bodyInputHeight, setBodyInputHeight] = useState(MIN_BODY_INPUT_HEIGHT);
const [isSnippetsOpen, setIsSnippetsOpen] = useState(false); const [isSnippetsOpen, setIsSnippetsOpen] = useState(false);
const inputRef = useRef(null); const inputRef = useRef(null);
@ -161,6 +163,11 @@ const MarkdownEditorView = ({
setSelection(event.nativeEvent.selection); setSelection(event.nativeEvent.selection);
}; };
const _handleOnContentSizeChange = async (event) => {
const height = Math.max(MIN_BODY_INPUT_HEIGHT, event.nativeEvent.contentSize.height + 30);
setBodyInputHeight(height);
};
// eslint-disable-next-line react-hooks/exhaustive-deps // eslint-disable-next-line react-hooks/exhaustive-deps
const _setTextAndSelection = useCallback(({ selection: _selection, text: _text }) => { const _setTextAndSelection = useCallback(({ selection: _selection, text: _text }) => {
inputRef.current.setNativeProps({ inputRef.current.setNativeProps({
@ -337,13 +344,14 @@ const MarkdownEditorView = ({
})} })}
placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'} placeholderTextColor={isDarkTheme ? '#526d91' : '#c1c5c7'}
selectionColor="#357ce6" selectionColor="#357ce6"
style={styles.textWrapper} style={{ ...styles.textWrapper, height: bodyInputHeight }}
underlineColorAndroid="transparent" underlineColorAndroid="transparent"
innerRef={inputRef} innerRef={inputRef}
editable={editable} editable={editable}
contextMenuHidden={false} contextMenuHidden={false}
autoGrow={false} autoGrow={false}
scrollEnabled={false} scrollEnabled={false}
onContentSizeChange={_handleOnContentSizeChange}
/> />
)} )}
</ThemeContainer> </ThemeContainer>

View File

@ -301,7 +301,19 @@
"my_communities": "My Communities", "my_communities": "My Communities",
"top_communities": "Top Communities", "top_communities": "Top Communities",
"schedule_modal_title": "Schedule Post", "schedule_modal_title": "Schedule Post",
"snippets": "Snippets" "snippets": "Snippets",
"alert_init_title":"Initialize",
"alert_init_body":"Load recent draft or create new post",
"alert_btn_draft":"Load Draft",
"alert_btn_new":"New Post",
"alert_pub_edit_title":"Publishing edits",
"alert_pub_new_title":"Publishing new post",
"alert_pub_body":"Are you sure?",
"alert_btn_yes":"Yes",
"alert_btn_no":"No",
"draft_save_success":"Draft Saved",
"draft_save_fail":"Failed to save draft"
}, },
"snippets":{ "snippets":{
"label_no_snippets":"No Snippets Found", "label_no_snippets":"No Snippets Found",
@ -406,7 +418,8 @@
"title": "Drafts", "title": "Drafts",
"load_error": "Could not load drafts", "load_error": "Could not load drafts",
"empty_list": "Nothing here", "empty_list": "Nothing here",
"deleted": "Draft deleted" "deleted": "Draft deleted",
}, },
"schedules": { "schedules": {
"title": "Schedules", "title": "Schedules",

View File

@ -79,6 +79,8 @@ export const addDraft = (data) =>
const { drafts } = res.data; const { drafts } = res.data;
if (drafts) { if (drafts) {
resolve(drafts.pop()); resolve(drafts.pop());
} else {
reject(new Error('No drafts returned in response'));
} }
}) })
.catch((error) => { .catch((error) => {
@ -102,7 +104,11 @@ export const updateDraft = (data) =>
tags: data.tags, tags: data.tags,
}) })
.then((res) => { .then((res) => {
resolve(res.data); if (res.data) {
resolve(res.data);
} else {
reject(new Error('No data retuend in update response'));
}
}) })
.catch((error) => { .catch((error) => {
bugsnag.notify(error); bugsnag.notify(error);

View File

@ -118,19 +118,31 @@ export const removeAllSCAccounts = async () => {
} }
}; };
export const setDraftPost = async (fields, username) => { export const setDraftPost = async (fields, username, draftId) => {
try { try {
let draft = await getItemFromStorage(DRAFT_SCHEMA); let draft = await getItemFromStorage(DRAFT_SCHEMA);
let timestamp = new Date().getTime();
const data = { const data = {
username, username,
draftId,
timestamp,
title: fields.title, title: fields.title,
tags: fields.tags, tags: fields.tags,
body: fields.body, body: fields.body,
}; };
if (draft && draft.some((e) => e.username === username)) { if (draft && draft.some((e) => e.username === username)) {
draft = draft.map((item) => (item.username === username ? { ...item, ...data } : item)); //check if entry esist
const draftIndex = draft.findIndex(
(item) => draftId === undefined || item.draftId === draftId,
);
if (draftIndex < 0) {
draft.push(data);
} else {
draft[draftIndex] = data;
}
} else { } else {
draft = []; draft = [];
draft.push(data); draft.push(data);
@ -142,10 +154,13 @@ export const setDraftPost = async (fields, username) => {
} }
}; };
export const getDraftPost = async (username) => { export const getDraftPost = async (username, draftId) => {
try { try {
const draft = await getItemFromStorage(DRAFT_SCHEMA); const draft = await getItemFromStorage(DRAFT_SCHEMA);
const draftObj = draft.filter((item) => item.username === username); const draftObj = draft.filter(
(item) => item.username === username && (draftId === undefined || item.draftId === draftId),
);
return draftObj[0]; return draftObj[0];
} catch (error) { } catch (error) {
return error; return error;

View File

@ -22,7 +22,7 @@ const persistedReducer = persistReducer(persistConfig, reducer);
const middleware = [thunk]; const middleware = [thunk];
if (process.env.NODE_ENV === 'development') { if (process.env.NODE_ENV === 'development') {
middleware.push(logger); // middleware.push(logger);
} }
const store = createStore(persistedReducer, applyMiddleware(...middleware)); const store = createStore(persistedReducer, applyMiddleware(...middleware));

View File

@ -8,7 +8,13 @@ import AsyncStorage from '@react-native-community/async-storage';
// Services and Actions // Services and Actions
import { Buffer } from 'buffer'; import { Buffer } from 'buffer';
import { uploadImage, addDraft, updateDraft, schedule } from '../../../providers/ecency/ecency'; import {
uploadImage,
addDraft,
updateDraft,
schedule,
getDrafts,
} from '../../../providers/ecency/ecency';
import { toastNotification, setRcOffer } from '../../../redux/actions/uiAction'; import { toastNotification, setRcOffer } from '../../../redux/actions/uiAction';
import { import {
postContent, postContent,
@ -42,6 +48,8 @@ import EditorScreen from '../screen/editorScreen';
*/ */
class EditorContainer extends Component { class EditorContainer extends Component {
_isMounted = false;
constructor(props) { constructor(props) {
super(props); super(props);
this.state = { this.state = {
@ -63,7 +71,102 @@ class EditorContainer extends Component {
}; };
} }
_getDraft = async (username, isReply) => { // Component Life Cycle Functions
componentDidMount() {
this._isMounted = true;
const { currentAccount, navigation } = this.props;
const username = currentAccount && currentAccount.name ? currentAccount.name : '';
let isReply;
let isEdit;
let post;
let _draft;
if (navigation.state && navigation.state.params) {
const navigationParams = navigation.state.params;
if (navigationParams.draft) {
_draft = navigationParams.draft;
this.setState({
draftId: _draft._id,
isDraft: true,
});
this._getStorageDraft(username, isReply, _draft);
}
if (navigationParams.community) {
this.setState({
community: navigationParams.community,
});
}
if (navigationParams.upload) {
const { upload } = navigationParams;
upload.forEach((el) => {
if (el.filePath && el.fileName) {
this.setState({ isUploading: true });
const _media = {
path: el.filePath,
mime: el.mimeType,
filename: el.fileName || `img_${Math.random()}.jpg`,
};
this._uploadImage(_media);
} else if (el.text) {
this.setState({
draftPost: {
title: '',
body: el.text,
tags: [],
},
});
}
});
}
if (navigationParams.post) {
({ post } = navigationParams);
this.setState({
post,
});
}
if (navigationParams.isReply) {
({ isReply } = navigationParams);
this.setState({
isReply,
});
}
if (navigationParams.isEdit) {
({ isEdit } = navigationParams);
this.setState({
isEdit,
draftPost: {
title: get(post, 'title', ''),
body: get(post, 'markdownBody', ''),
tags: get(post, 'json_metadata.tags', []),
},
});
}
if (navigationParams.action) {
this._handleRoutingAction(navigationParams.action);
}
} else {
this.setState({
autoFocusText: true,
});
}
if (!isEdit && !_draft) {
this._fetchDraftsForComparison(isReply);
}
}
componentWillUnmount() {
this._isMounted = false;
}
_getStorageDraft = async (username, isReply, paramDraft) => {
if (isReply) { if (isReply) {
const draftReply = await AsyncStorage.getItem('temp-reply'); const draftReply = await AsyncStorage.getItem('temp-reply');
@ -75,20 +178,128 @@ class EditorContainer extends Component {
}); });
} }
} else { } else {
await getDraftPost(username).then((result) => { getDraftPost(username, paramDraft && paramDraft._id).then((result) => {
if (result) { //if result is return and param draft available, compare timestamp, use latest
//if no draft, use result anayways
if (result && (!paramDraft || paramDraft.timestamp < result.timestamp)) {
this.setState({ this.setState({
draftPost: { draftPost: {
body: get(result, 'body', ''), body: get(result, 'body', ''),
title: get(result, 'title', ''), title: get(result, 'title', ''),
tags: get(result, 'tags', '').split(','), tags: get(result, 'tags', '').split(','),
isDraft: paramDraft ? true : false,
draftId: paramDraft ? paramDraft._id : null,
}, },
}); });
} }
//if above fails with either no result returned or timestamp is old,
// and use draft form nav param if available.
else if (paramDraft) {
const _tags = paramDraft.tags.includes(' ')
? paramDraft.tags.split(' ')
: paramDraft.tags.split(',');
this.setState({
draftPost: {
title: paramDraft.title,
body: paramDraft.body,
tags: _tags,
},
isDraft: true,
draftId: paramDraft._id,
});
}
}); });
} }
}; };
/**
* this fucntion is run if editor is access used mid tab or reply section
* it fetches fresh drafts and run some comparions to load one of following
* empty editor, load non-remote draft or most recent remote draft based on timestamps
* prompts user as well
* @param isReply
**/
_fetchDraftsForComparison = async (isReply) => {
const { currentAccount, isLoggedIn, intl } = this.props;
const username = get(currentAccount, 'name', '');
//initilizes editor with reply or non remote id less draft
const _getStorageDraftGeneral = () => {
this._getStorageDraft(username, isReply);
};
//skip comparison if its a reply and run general function
if (isReply) {
_getStorageDraftGeneral();
return;
}
try {
//if not logged in use non remote draft
if (!isLoggedIn) {
_getStorageDraftGeneral();
return;
}
const drafts = await getDrafts(username);
const idLessDraft = await getDraftPost(username);
const loadRecentDraft = () => {
//if no draft available means local draft is recent
if (drafts.length == 0) {
_getStorageDraftGeneral();
return;
}
//sort darts based on timestamps
drafts.sort((d1, d2) =>
new Date(d1.modified).getTime() < new Date(d2.modified).getTime() ? 1 : -1,
);
const _draft = drafts[0];
//if unsaved local draft is more latest then remote draft, use that instead
//if editor was opened from draft screens, this code will be skipped anyways.
if (idLessDraft && new Date(_draft.modified).getTime() < idLessDraft.timestamp) {
_getStorageDraftGeneral();
return;
}
//initilize editor as draft
this.setState({
draftId: _draft._id,
isDraft: true,
});
this._getStorageDraft(username, isReply, _draft);
};
const leaveEmpty = () => {
console.log('Leaving editor empty');
};
if (drafts.length > 0 || (idLessDraft && idLessDraft.timestamp > 0)) {
Alert.alert(
intl.formatMessage({
id: 'editor.alert_init_title',
}),
intl.formatMessage({
id: 'editor.alert_init_body',
}),
[
{
text: intl.formatMessage({ id: 'editor.alert_btn_draft' }),
onPress: loadRecentDraft,
},
{ text: intl.formatMessage({ id: 'editor.alert_btn_new' }), onPress: leaveEmpty },
],
);
}
} catch (err) {
console.warn('Failed to compare drafts, load general', err);
_getStorageDraftGeneral();
}
};
_handleRoutingAction = (routingAction) => { _handleRoutingAction = (routingAction) => {
if (routingAction === 'camera') { if (routingAction === 'camera') {
this._handleOpenCamera(); this._handleOpenCamera();
@ -224,67 +435,122 @@ class EditorContainer extends Component {
} }
}; };
_saveDraftToDB = (fields) => { _saveDraftToDB = async (fields) => {
const { isDraftSaved, draftId } = this.state; const { isDraftSaved, draftId } = this.state;
const { currentAccount, dispatch, intl } = this.props;
if (!isDraftSaved) { try {
const { currentAccount } = this.props; if (!isDraftSaved) {
const username = get(currentAccount, 'name', ''); const username = get(currentAccount, 'name', '');
let draftField; let draftField;
this.setState({ if (this._isMounted) {
isDraftSaving: true, this.setState({
}); isDraftSaving: true,
if (fields) { });
draftField = { }
...fields,
tags: fields.tags.join(' '), if (fields) {
username, draftField = {
}; ...fields,
tags: fields.tags.join(' '),
username,
};
}
//update draft is draftId is present
if (draftId && draftField) {
await updateDraft({
...draftField,
draftId,
});
if (this._isMounted) {
this.setState({
isDraftSaved: true,
isDraftSaving: false,
});
}
}
//create new darft otherwise
else if (draftField) {
const response = await addDraft(draftField);
if (this._isMounted) {
this.setState({
isDraftSaved: true,
isDraftSaving: false,
draftId: response._id,
});
}
//clear local copy is darft save is successful
setDraftPost(
{
title: '',
body: '',
tags: '',
timestamp: 0,
},
username,
);
}
dispatch(
toastNotification(
intl.formatMessage({
id: 'editor.draft_save_success',
}),
),
);
//call fetch post to drafts screen
this._navigationBackFetchDrafts();
} }
} catch (err) {
if (draftId && draftField) { console.warn('Failed to save draft to DB: ', err);
updateDraft({ if (this._isMounted) {
...draftField, this.setState({
draftId, isDraftSaving: false,
}).then(() => { isDraftSaved: false,
this.setState({
isDraftSaved: true,
});
});
} else if (draftField) {
addDraft(draftField).then((response) => {
this.setState({
isDraftSaved: true,
draftId: response._id,
});
}); });
} }
this.setState({ dispatch(
isDraftSaving: false, toastNotification(
isDraftSaved, intl.formatMessage({
}); id: 'editor.draft_save_fail',
}),
),
);
} }
}; };
_saveCurrentDraft = async (fields) => { _saveCurrentDraft = async (fields) => {
const { draftId, isReply, isEdit, isPostSending } = this.state; const { draftId, isReply, isEdit, isPostSending } = this.state;
if (!draftId && !isEdit) { const { currentAccount } = this.props;
const { currentAccount } = this.props; const username = currentAccount && currentAccount.name ? currentAccount.name : '';
const username = currentAccount && currentAccount.name ? currentAccount.name : '';
const draftField = { const draftField = {
...fields, ...fields,
tags: fields.tags && fields.tags.length > 0 ? fields.tags.toString() : '', tags: fields.tags && fields.tags.length > 0 ? fields.tags.toString() : '',
}; };
if (!isPostSending) {
if (isReply && draftField.body !== null) { if (!isPostSending) {
await AsyncStorage.setItem('temp-reply', draftField.body); //save reply data
} else { if (isReply && draftField.body !== null) {
setDraftPost(draftField, username); await AsyncStorage.setItem('temp-reply', draftField.body);
}
//save existing draft data locally
} else if (draftId) {
setDraftPost(draftField, username, draftId);
}
//update editor data locally
else if (!isReply) {
setDraftPost(draftField, username);
} }
} }
}; };
@ -363,6 +629,7 @@ class EditorContainer extends Component {
title: '', title: '',
body: '', body: '',
tags: '', tags: '',
timestamp: 0,
}, },
currentAccount.name, currentAccount.name,
); );
@ -410,12 +677,7 @@ class EditorContainer extends Component {
const permlink = generateReplyPermlink(post.author); const permlink = generateReplyPermlink(post.author);
const author = currentAccount.name; const author = currentAccount.name;
const options = null; const options = null;
/*makeOptions({
author: author,
permlink: permlink,
operationType: rewardType,
beneficiaries: beneficiaries,
});*/
const parentAuthor = post.author; const parentAuthor = post.author;
const parentPermlink = post.permlink; const parentPermlink = post.permlink;
const voteWeight = null; const voteWeight = null;
@ -545,45 +807,68 @@ class EditorContainer extends Component {
}, 3000); }, 3000);
}; };
_handleOnBackPress = () => { _navigationBackFetchDrafts = () => {
const { navigation } = this.props; const { navigation } = this.props;
const { isDraft } = this.state; const { isDraft } = this.state;
if (isDraft) { if (isDraft && navigation.state.params) {
navigation.state.params.fetchPost(); navigation.state.params.fetchPost();
} }
}; };
_handleSubmit = (form) => { _handleSubmit = (form) => {
const { isReply, isEdit } = this.state; const { isReply, isEdit } = this.state;
const { intl } = this.props;
if (isReply && !isEdit) { if (isReply && !isEdit) {
this._submitReply(form.fields); this._submitReply(form.fields);
} else if (isEdit) { } else if (isEdit) {
Alert.alert( Alert.alert(
'Publishing edits', intl.formatMessage({
'Are you sure?', id: 'editor.alert_pub_edit_title',
}),
intl.formatMessage({
id: 'editor.alert_pub_body',
}),
[ [
{ {
text: 'No', text: intl.formatMessage({
id: 'editor.alert_btn_no',
}),
onPress: () => console.log('Cancel Pressed'), onPress: () => console.log('Cancel Pressed'),
style: 'cancel', style: 'cancel',
}, },
{ text: 'Yes', onPress: () => this._submitEdit(form.fields) }, {
text: intl.formatMessage({
id: 'editor.alert_btn_yes',
}),
onPress: () => this._submitEdit(form.fields),
},
], ],
{ cancelable: false }, { cancelable: false },
); );
} else { } else {
Alert.alert( Alert.alert(
'Publishing new post', intl.formatMessage({
'Are you sure?', id: 'editor.alert_pub_new_title',
}),
intl.formatMessage({
id: 'editor.alert_pub_body',
}),
[ [
{ {
text: 'No', text: intl.formatMessage({
id: 'editor.alert_btn_no',
}),
onPress: () => console.log('Cancel Pressed'), onPress: () => console.log('Cancel Pressed'),
style: 'cancel', style: 'cancel',
}, },
{ text: 'Yes', onPress: () => this._submitPost(form.fields) }, {
text: intl.formatMessage({
id: 'editor.alert_btn_yes',
}),
onPress: () => this._submitPost(form.fields),
},
], ],
{ cancelable: false }, { cancelable: false },
); );
@ -683,6 +968,7 @@ class EditorContainer extends Component {
title: '', title: '',
body: '', body: '',
tags: '', tags: '',
timestamp: 0,
}, },
currentAccount.name, currentAccount.name,
); );
@ -710,6 +996,7 @@ class EditorContainer extends Component {
title: '', title: '',
body: '', body: '',
tags: '', tags: '',
timestamp: 0,
}, },
name, name,
); );
@ -728,100 +1015,6 @@ class EditorContainer extends Component {
await AsyncStorage.setItem('temp-beneficiaries', JSON.stringify(value)); await AsyncStorage.setItem('temp-beneficiaries', JSON.stringify(value));
}; };
// Component Life Cycle Functions
componentDidMount() {
const { currentAccount, navigation } = this.props;
const username = currentAccount && currentAccount.name ? currentAccount.name : '';
let isReply;
let isEdit;
let post;
let _draft;
if (navigation.state && navigation.state.params) {
const navigationParams = navigation.state.params;
if (navigationParams.draft) {
_draft = navigationParams.draft;
const _tags = _draft.tags.includes(' ') ? _draft.tags.split(' ') : _draft.tags.split(',');
this.setState({
draftPost: {
title: _draft.title,
body: _draft.body,
tags: _tags,
},
draftId: _draft._id,
isDraft: true,
});
}
if (navigationParams.community) {
this.setState({
community: navigationParams.community,
});
}
if (navigationParams.upload) {
const { upload } = navigationParams;
upload.forEach((el) => {
if (el.filePath && el.fileName) {
this.setState({ isUploading: true });
const _media = {
path: el.filePath,
mime: el.mimeType,
filename: el.fileName || `img_${Math.random()}.jpg`,
};
this._uploadImage(_media);
} else if (el.text) {
this.setState({
draftPost: {
title: '',
body: el.text,
tags: [],
},
});
}
});
}
if (navigationParams.post) {
({ post } = navigationParams);
this.setState({
post,
});
}
if (navigationParams.isReply) {
({ isReply } = navigationParams);
this.setState({
isReply,
});
}
if (navigationParams.isEdit) {
({ isEdit } = navigationParams);
this.setState({
isEdit,
draftPost: {
title: get(post, 'title', ''),
body: get(post, 'markdownBody', ''),
tags: get(post, 'json_metadata.tags', []),
},
});
}
if (navigationParams.action) {
this._handleRoutingAction(navigationParams.action);
}
} else {
this.setState({
autoFocusText: true,
});
}
if (!isEdit && !_draft) {
this._getDraft(username, isReply);
}
}
render() { render() {
const { isLoggedIn, isDarkTheme, navigation, currentAccount } = this.props; const { isLoggedIn, isDarkTheme, navigation, currentAccount } = this.props;
const { const {
@ -850,7 +1043,7 @@ class EditorContainer extends Component {
handleBeneficiaries={this._handleBeneficiaries} handleBeneficiaries={this._handleBeneficiaries}
handleDatePickerChange={this._handleDatePickerChange} handleDatePickerChange={this._handleDatePickerChange}
handleFormChanged={this._handleFormChanged} handleFormChanged={this._handleFormChanged}
handleOnBackPress={this._handleOnBackPress} handleOnBackPress={() => {}}
handleOnImagePicker={this._handleRoutingAction} handleOnImagePicker={this._handleRoutingAction}
handleOnSubmit={this._handleSubmit} handleOnSubmit={this._handleSubmit}
initialEditor={this._initialEditor} initialEditor={this._initialEditor}

View File

@ -65,6 +65,10 @@ class EditorScreen extends Component {
} }
} }
componentWillUnmount() {
this._saveDraftToDB();
}
UNSAFE_componentWillReceiveProps = async (nextProps) => { UNSAFE_componentWillReceiveProps = async (nextProps) => {
const { draftPost, isUploading, community } = this.props; const { draftPost, isUploading, community } = this.props;
if (nextProps.draftPost && draftPost !== nextProps.draftPost) { if (nextProps.draftPost && draftPost !== nextProps.draftPost) {
@ -127,10 +131,7 @@ class EditorScreen extends Component {
}; };
_handleOnSaveButtonPress = () => { _handleOnSaveButtonPress = () => {
const { saveDraftToDB } = this.props; this._saveDraftToDB();
const { fields } = this.state;
saveDraftToDB(fields);
}; };
_saveCurrentDraft = (fields) => { _saveCurrentDraft = (fields) => {
@ -252,6 +253,16 @@ class EditorScreen extends Component {
}); });
}; };
_saveDraftToDB() {
const { saveDraftToDB } = this.props;
const { fields } = this.state;
//save draft only if any of field is valid
if (fields.body || fields.title) {
saveDraftToDB(fields);
}
}
render() { render() {
const { const {
fields, fields,

View File

@ -1583,24 +1583,24 @@ anymatch@^2.0.0:
micromatch "^3.1.4" micromatch "^3.1.4"
normalize-path "^2.1.1" normalize-path "^2.1.1"
appcenter-analytics@3.1.0: appcenter-analytics@^4.1.0:
version "3.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/appcenter-analytics/-/appcenter-analytics-3.1.0.tgz#ec51c79f43c58a6e6d6d5ce4c8bdb0ada3bda539" resolved "https://registry.yarnpkg.com/appcenter-analytics/-/appcenter-analytics-4.1.0.tgz#eb3270a6894bcf3d14e1772c4ccf21d7fb88fa85"
integrity sha512-zGJRBe39IigyT127/alNzNeOpDYSyRo8RX2RYq2AtL01LnCreOy/fpzoF4yOVPMedFMiinEN+OOqR9e7WydAwg== integrity sha512-pEsz08wer7J3+zjNV78eSB0FY1bjMxmFHukV6PimAoMpIm8E+X7saGP0QQw2cQTUFiexMujHRvZfM259ksg6hg==
dependencies: dependencies:
appcenter "3.1.0" appcenter "4.1.0"
appcenter-crashes@3.1.0: appcenter-crashes@^4.1.0:
version "3.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/appcenter-crashes/-/appcenter-crashes-3.1.0.tgz#6b0fb592bc5e69cbd83106b47f55c97bc33a3fa3" resolved "https://registry.yarnpkg.com/appcenter-crashes/-/appcenter-crashes-4.1.0.tgz#1d7a1a27c61f6a37d904f3d435de2f30ee0454e5"
integrity sha512-2dwy7aqhSKifWg5yZVPuZdNRiHMO/XTsaQSHvvHNDA47BJ2y/cwCsK516KNgoYvp97B3Pr3Xyim7ee/n/xxO4g== integrity sha512-erl7387yAPRKa7d8L7KxNd82OAZ+EQwThpsu7tZLQYn3iuIT4P98dNFCnJKO6y64li4dn4B9rCF3s0PN7tPb1A==
dependencies: dependencies:
appcenter "3.1.0" appcenter "4.1.0"
appcenter-link-scripts@3.1.0: appcenter-link-scripts@4.1.0:
version "3.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/appcenter-link-scripts/-/appcenter-link-scripts-3.1.0.tgz#5cc9d0303f9f16b7170d56a403fa3e69379cfd36" resolved "https://registry.yarnpkg.com/appcenter-link-scripts/-/appcenter-link-scripts-4.1.0.tgz#ff9d337fb7841c2cbf86cd5f34bd7310e945d0f5"
integrity sha512-0ECoQLjfIJhAO8EkvRQ4fO5gZELhzwD3eRhsCD4d27k7TDPXYt32/p5ylHXUWotR7pduTE1rZ8gtETTr4oZf9g== integrity sha512-sTd8H4H9wNwBkUKHasvDGNBln34+dHEFlaT/P6O0gvs6TWU3JxlY8uXpB/IqAi2lSWPs3TMgQ7NGXTjvC6oZig==
dependencies: dependencies:
debug "4.1.1" debug "4.1.1"
glob "5.0.15" glob "5.0.15"
@ -1610,12 +1610,12 @@ appcenter-link-scripts@3.1.0:
which "1.2.11" which "1.2.11"
xcode "2.0.0" xcode "2.0.0"
appcenter@3.1.0: appcenter@4.1.0, appcenter@^4.1.0:
version "3.1.0" version "4.1.0"
resolved "https://registry.yarnpkg.com/appcenter/-/appcenter-3.1.0.tgz#55fb01bfedc92e732e52ab97c8b344e062ba61a7" resolved "https://registry.yarnpkg.com/appcenter/-/appcenter-4.1.0.tgz#d4c9b43adcaac32a328dc8e9f9f0607e0a7d5691"
integrity sha512-SvEdrqeEqK5BJizdrRmWdp/NFwwb3FJ08U5LQkRdqPoFWXQZ7d+AC2cVnemORXsiYPcpwK9xqiNxyofzEzddFA== integrity sha512-JUwb/4sMw68CN2AlJEp1G5iVl/Rzv8fg8t9CzeRaEcnOku42h6+vlYbYe3P5YW18kAIA/hCH0uoDaa0kc9qfDA==
dependencies: dependencies:
appcenter-link-scripts "3.1.0" appcenter-link-scripts "4.1.0"
aproba@^1.0.3: aproba@^1.0.3:
version "1.2.0" version "1.2.0"