mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-18 19:01:38 +03:00
commit
f35ce3d27f
@ -67,6 +67,7 @@
|
||||
"react-native": "0.61.5",
|
||||
"react-native-actions-sheet": "^0.4.2",
|
||||
"react-native-actionsheet": "ecency/react-native-actionsheet",
|
||||
"react-native-animatable": "^1.3.3",
|
||||
"react-native-autoheight-webview": "^1.5.7",
|
||||
"react-native-config": "luggit/react-native-config#master",
|
||||
"react-native-dark-mode": "^0.2.2",
|
||||
|
@ -94,4 +94,18 @@ export default EStyleSheet.create({
|
||||
paddingTop: 32,
|
||||
paddingBottom: 16,
|
||||
},
|
||||
floatingContainer: Platform.select({
|
||||
//absolute positioning makes button hide behind keyboard on ios
|
||||
ios: {
|
||||
alignItems: 'flex-end',
|
||||
margin: 16,
|
||||
marginBottom: 24,
|
||||
},
|
||||
//on android the appearing of button was causing momentary glitch with ios variant style
|
||||
android: {
|
||||
position: 'absolute',
|
||||
right: 16,
|
||||
bottom: 56,
|
||||
},
|
||||
}),
|
||||
});
|
||||
|
@ -11,6 +11,8 @@ import {
|
||||
import ActionSheet from 'react-native-actionsheet';
|
||||
import { renderPostBody } from '@ecency/render-helper';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { View as AnimatedView } from 'react-native-animatable';
|
||||
import { get } from 'lodash';
|
||||
import { Icon } from '../../icon';
|
||||
|
||||
// Utils
|
||||
@ -42,6 +44,7 @@ import { ThemeContainer } from '../../../containers';
|
||||
// Styles
|
||||
import styles from './markdownEditorStyles';
|
||||
import applySnippet from './formats/applySnippet';
|
||||
import { MainButton } from '../../mainButton';
|
||||
|
||||
const MIN_BODY_INPUT_HEIGHT = 300;
|
||||
|
||||
@ -68,12 +71,15 @@ const MarkdownEditorView = ({
|
||||
getCommunity,
|
||||
currentAccount,
|
||||
autoFocusText,
|
||||
sharedSnippetText,
|
||||
onLoadDraftPress,
|
||||
}) => {
|
||||
const [text, setText] = useState(draftBody || '');
|
||||
const [selection, setSelection] = useState({ start: 0, end: 0 });
|
||||
const [editable, setEditable] = useState(true);
|
||||
const [bodyInputHeight, setBodyInputHeight] = useState(MIN_BODY_INPUT_HEIGHT);
|
||||
const [isSnippetsOpen, setIsSnippetsOpen] = useState(false);
|
||||
const [showDraftLoadButton, setShowDraftLoadButton] = useState(false);
|
||||
|
||||
const inputRef = useRef(null);
|
||||
const galleryRef = useRef(null);
|
||||
@ -91,12 +97,38 @@ const MarkdownEditorView = ({
|
||||
}
|
||||
}, [isPreviewActive]);
|
||||
|
||||
useEffect(() => {
|
||||
if (onLoadDraftPress) {
|
||||
setShowDraftLoadButton(true);
|
||||
}
|
||||
}, [onLoadDraftPress]);
|
||||
|
||||
useEffect(() => {
|
||||
if (text === '' && draftBody !== '') {
|
||||
_setTextAndSelection({ selection: { start: 0, end: 0 }, text: draftBody });
|
||||
}
|
||||
}, [draftBody]);
|
||||
|
||||
useEffect(() => {
|
||||
//hide draft button if fields changes and button was visible
|
||||
if (showDraftLoadButton) {
|
||||
let isCreating =
|
||||
get(fields, 'title', '') !== '' ||
|
||||
get(fields, 'body', '') !== '' ||
|
||||
get(fields, 'tags', []) !== [];
|
||||
|
||||
if (isCreating) {
|
||||
setShowDraftLoadButton(false);
|
||||
}
|
||||
}
|
||||
}, [fields]);
|
||||
|
||||
useEffect(() => {
|
||||
if (sharedSnippetText) {
|
||||
_handleOnSnippetReceived(sharedSnippetText);
|
||||
}
|
||||
}, [sharedSnippetText]);
|
||||
|
||||
useEffect(() => {
|
||||
if (editable === null) {
|
||||
// workaround for android context menu issue
|
||||
@ -110,14 +142,18 @@ const MarkdownEditorView = ({
|
||||
}, [isLoading]);
|
||||
|
||||
useEffect(() => {
|
||||
if (uploadedImage && uploadedImage.url && uploadedImage.shouldInsert) {
|
||||
applyImageLink({
|
||||
text,
|
||||
selection,
|
||||
setTextAndSelection: _setTextAndSelection,
|
||||
item: { url: uploadedImage.url, text: uploadedImage.hash },
|
||||
isImage: !!uploadedImage,
|
||||
});
|
||||
if (uploadedImage && uploadedImage.url) {
|
||||
if (uploadedImage.shouldInsert) {
|
||||
applyImageLink({
|
||||
text,
|
||||
selection,
|
||||
setTextAndSelection: _setTextAndSelection,
|
||||
item: { url: uploadedImage.url, text: uploadedImage.hash },
|
||||
isImage: !!uploadedImage,
|
||||
});
|
||||
} else {
|
||||
uploadsGalleryModalRef.current.showModal();
|
||||
}
|
||||
}
|
||||
}, [uploadedImage]);
|
||||
|
||||
@ -208,7 +244,7 @@ const MarkdownEditorView = ({
|
||||
</ScrollView>
|
||||
);
|
||||
|
||||
const _handleOnSnippetSelect = (snippetText) => {
|
||||
const _handleOnSnippetReceived = (snippetText) => {
|
||||
applySnippet({
|
||||
text,
|
||||
selection,
|
||||
@ -244,6 +280,28 @@ const MarkdownEditorView = ({
|
||||
</View>
|
||||
);
|
||||
|
||||
const _renderFloatingDraftButton = () => {
|
||||
if (showDraftLoadButton) {
|
||||
const _onPress = () => {
|
||||
setShowDraftLoadButton(false);
|
||||
onLoadDraftPress();
|
||||
};
|
||||
return (
|
||||
<AnimatedView style={styles.floatingContainer} animation="bounceInRight">
|
||||
<MainButton
|
||||
style={{ width: isLoading ? null : 120 }}
|
||||
onPress={_onPress}
|
||||
iconName="square-edit-outline"
|
||||
iconType="MaterialCommunityIcons"
|
||||
iconColor="white"
|
||||
text="DRAFT"
|
||||
isLoading={isLoading}
|
||||
/>
|
||||
</AnimatedView>
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
const _renderEditorButtons = () => (
|
||||
<StickyBar>
|
||||
<View style={styles.leftButtonsWrapper}>
|
||||
@ -275,8 +333,7 @@ const MarkdownEditorView = ({
|
||||
/>
|
||||
<IconButton
|
||||
onPress={() => {
|
||||
// galleryRef.current.show()}
|
||||
uploadsGalleryModalRef.current.showModal();
|
||||
galleryRef.current.show();
|
||||
}}
|
||||
style={styles.rightIcons}
|
||||
size={20}
|
||||
@ -386,7 +443,10 @@ const MarkdownEditorView = ({
|
||||
_renderPreview()
|
||||
)}
|
||||
</ScrollView>
|
||||
|
||||
{_renderFloatingDraftButton()}
|
||||
{!isPreviewActive && _renderEditorButtons()}
|
||||
|
||||
<Modal
|
||||
isOpen={isSnippetsOpen}
|
||||
handleOnModalClose={() => setIsSnippetsOpen(false)}
|
||||
@ -398,17 +458,16 @@ const MarkdownEditorView = ({
|
||||
animationType="slide"
|
||||
style={styles.modalStyle}
|
||||
>
|
||||
<SnippetsModal username={currentAccount.username} handleOnSelect={_handleOnSnippetSelect} />
|
||||
<SnippetsModal
|
||||
username={currentAccount.username}
|
||||
handleOnSelect={_handleOnSnippetReceived}
|
||||
/>
|
||||
</Modal>
|
||||
|
||||
<UploadsGalleryModal
|
||||
ref={uploadsGalleryModalRef}
|
||||
username={currentAccount.username}
|
||||
handleOnSelect={_handleOnMediaSelect}
|
||||
handleOnUploadPress={() => {
|
||||
galleryRef.current.show();
|
||||
}}
|
||||
isUploading={isUploading}
|
||||
uploadedImage={uploadedImage}
|
||||
/>
|
||||
|
||||
@ -421,13 +480,21 @@ const MarkdownEditorView = ({
|
||||
intl.formatMessage({
|
||||
id: 'editor.capture_photo',
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: 'editor.uploaded_images',
|
||||
}),
|
||||
|
||||
intl.formatMessage({
|
||||
id: 'alert.cancel',
|
||||
}),
|
||||
]}
|
||||
cancelButtonIndex={2}
|
||||
cancelButtonIndex={3}
|
||||
onPress={(index) => {
|
||||
handleOpenImagePicker(index === 0 ? 'image' : index === 1 && 'camera');
|
||||
if (index == 2) {
|
||||
uploadsGalleryModalRef.current.showModal();
|
||||
} else {
|
||||
handleOpenImagePicker(index === 0 ? 'image' : index === 1 && 'camera');
|
||||
}
|
||||
}}
|
||||
/>
|
||||
<ActionSheet
|
||||
|
@ -21,13 +21,11 @@ interface MediaInsertData {
|
||||
|
||||
interface UploadsGalleryModalProps {
|
||||
username:string;
|
||||
isUploading:boolean;
|
||||
handleOnSelect:(data:MediaInsertData)=>void;
|
||||
handleOnUploadPress:()=>void;
|
||||
uploadedImage:MediaInsertData;
|
||||
}
|
||||
|
||||
export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, handleOnUploadPress, isUploading, uploadedImage}: UploadsGalleryModalProps, ref) => {
|
||||
export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploadedImage}: UploadsGalleryModalProps, ref) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [mediaUploads, setMediaUploads] = useState([]);
|
||||
@ -167,28 +165,7 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, handl
|
||||
};
|
||||
|
||||
|
||||
//renders footer with add snipept button and shows new snippet modal
|
||||
const _renderFloatingButton = () => {
|
||||
const _onPress = () => {
|
||||
if(handleOnUploadPress){
|
||||
handleOnUploadPress();
|
||||
}
|
||||
|
||||
}
|
||||
return (
|
||||
<View style={styles.floatingContainer}>
|
||||
<MainButton
|
||||
style={{ width: isUploading?null:130}}
|
||||
onPress={_onPress}
|
||||
iconName="plus"
|
||||
iconType="MaterialCommunityIcons"
|
||||
iconColor="white"
|
||||
text={intl.formatMessage({id:'uploads_modal.btn_add'})}
|
||||
isLoading={isUploading}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
const _renderContent = (
|
||||
@ -207,7 +184,6 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, handl
|
||||
/>
|
||||
}
|
||||
/>
|
||||
{_renderFloatingButton()}
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
|
@ -281,6 +281,7 @@
|
||||
"reply": "Reply",
|
||||
"open_gallery": "Open Gallery",
|
||||
"capture_photo": "Capture a photo",
|
||||
"uploaded_images": "Uploaded Images",
|
||||
"limited_tags": "Only 10 tags allowed, remove some",
|
||||
"limited_length": "Maximum length of each tag should be 24",
|
||||
"limited_dash": "Use one dash in each tag",
|
||||
|
@ -22,7 +22,7 @@ const persistedReducer = persistReducer(persistConfig, reducer);
|
||||
|
||||
const middleware = [thunk];
|
||||
if (process.env.NODE_ENV === 'development') {
|
||||
middleware.push(logger);
|
||||
// middleware.push(logger);
|
||||
}
|
||||
|
||||
const store = createStore(persistedReducer, applyMiddleware(...middleware));
|
||||
|
@ -158,10 +158,10 @@ class ApplicationContainer extends Component {
|
||||
});
|
||||
|
||||
ReceiveSharingIntent.getReceivedFiles(
|
||||
(files) => {
|
||||
() => {
|
||||
navigate({
|
||||
routeName: ROUTES.SCREENS.EDITOR,
|
||||
params: { upload: files },
|
||||
params: { hasSharedIntent: true },
|
||||
});
|
||||
// files returns as JSON Array example
|
||||
//[{ filePath: null, text: null, weblink: null, mimeType: null, contentUri: null, fileName: null, extension: null }]
|
||||
|
@ -8,6 +8,7 @@ import AsyncStorage from '@react-native-community/async-storage';
|
||||
|
||||
// Services and Actions
|
||||
import { Buffer } from 'buffer';
|
||||
import ReceiveSharingIntent from 'react-native-receive-sharing-intent';
|
||||
import {
|
||||
uploadImage,
|
||||
addDraft,
|
||||
@ -15,7 +16,7 @@ import {
|
||||
schedule,
|
||||
getDrafts,
|
||||
} from '../../../providers/ecency/ecency';
|
||||
import { toastNotification, setRcOffer, showActionModal } from '../../../redux/actions/uiAction';
|
||||
import { toastNotification, setRcOffer } from '../../../redux/actions/uiAction';
|
||||
import {
|
||||
postContent,
|
||||
getPurePost,
|
||||
@ -40,7 +41,6 @@ import {
|
||||
// import { generateSignature } from '../../../utils/image';
|
||||
// Component
|
||||
import EditorScreen from '../screen/editorScreen';
|
||||
import ImageAssets from '../../../assets/ImageAssets';
|
||||
|
||||
/*
|
||||
* Props Name Description Value
|
||||
@ -69,6 +69,8 @@ class EditorContainer extends Component {
|
||||
community: [],
|
||||
rewardType: 'default',
|
||||
beneficiaries: [],
|
||||
sharedSnippetText: null,
|
||||
onLoadDraftPress: false,
|
||||
};
|
||||
}
|
||||
|
||||
@ -81,9 +83,11 @@ class EditorContainer extends Component {
|
||||
let isEdit;
|
||||
let post;
|
||||
let _draft;
|
||||
let hasSharedIntent = false;
|
||||
|
||||
if (navigation.state && navigation.state.params) {
|
||||
const navigationParams = navigation.state.params;
|
||||
hasSharedIntent = navigationParams.hasSharedIntent;
|
||||
|
||||
if (navigationParams.draft) {
|
||||
_draft = navigationParams.draft;
|
||||
@ -98,30 +102,6 @@ class EditorContainer extends Component {
|
||||
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, { shouldInsert: true });
|
||||
} else if (el.text) {
|
||||
this.setState({
|
||||
draftPost: {
|
||||
title: '',
|
||||
body: el.text,
|
||||
tags: [],
|
||||
},
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (navigationParams.post) {
|
||||
({ post } = navigationParams);
|
||||
@ -154,11 +134,35 @@ class EditorContainer extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
if (!isEdit && !_draft) {
|
||||
if (!isEdit && !_draft && !hasSharedIntent) {
|
||||
this._fetchDraftsForComparison(isReply);
|
||||
} else {
|
||||
this._requestKeyboardFocus();
|
||||
}
|
||||
this._requestKeyboardFocus();
|
||||
|
||||
ReceiveSharingIntent.getReceivedFiles(
|
||||
(files) => {
|
||||
files.forEach((el) => {
|
||||
if (el.filePath && el.fileName) {
|
||||
const _media = {
|
||||
path: el.filePath,
|
||||
mime: el.mimeType,
|
||||
filename: el.fileName || `img_${Math.random()}.jpg`,
|
||||
};
|
||||
|
||||
this._uploadImage(_media, { shouldInsert: true });
|
||||
} else if (el.text) {
|
||||
this.setState({
|
||||
sharedSnippetText: el.text,
|
||||
});
|
||||
}
|
||||
});
|
||||
// To clear Intents
|
||||
ReceiveSharingIntent.clearReceivedFiles();
|
||||
},
|
||||
(error) => {
|
||||
console.log('error :>> ', error);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
componentWillUnmount() {
|
||||
@ -285,30 +289,10 @@ class EditorContainer extends Component {
|
||||
this._getStorageDraft(username, isReply, _draft);
|
||||
};
|
||||
|
||||
const leaveEmpty = () => {
|
||||
console.log('Leaving editor empty');
|
||||
};
|
||||
|
||||
if (drafts.length > 0 || (idLessDraft && idLessDraft.timestamp > 0)) {
|
||||
dispatch(
|
||||
showActionModal(
|
||||
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 },
|
||||
],
|
||||
ImageAssets.writerMascot,
|
||||
this._requestKeyboardFocus,
|
||||
),
|
||||
);
|
||||
this.setState({
|
||||
onLoadDraftPress: loadRecentDraft,
|
||||
});
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Failed to compare drafts, load general', err);
|
||||
@ -433,57 +417,6 @@ class EditorContainer extends Component {
|
||||
isUploading: false,
|
||||
});
|
||||
}
|
||||
|
||||
// uploadImage(media, currentAccount.name, sign).then((res) => {
|
||||
// if (res.data && res.data.url) {
|
||||
// res.data.hash = res.data.url.split('/').pop();
|
||||
// this.setState({
|
||||
// uploadedImage: res.data,
|
||||
// isUploading: false,
|
||||
// });
|
||||
// }
|
||||
// })
|
||||
// .catch((error) => {
|
||||
// console.log(error, error.message);
|
||||
// if (error.toString().includes('code 413')) {
|
||||
// Alert.alert(
|
||||
// intl.formatMessage({
|
||||
// id: 'alert.fail',
|
||||
// }),
|
||||
// intl.formatMessage({
|
||||
// id: 'alert.payloadTooLarge',
|
||||
// }),
|
||||
// );
|
||||
// } else if (error.toString().includes('code 429')) {
|
||||
// Alert.alert(
|
||||
// intl.formatMessage({
|
||||
// id: 'alert.fail',
|
||||
// }),
|
||||
// intl.formatMessage({
|
||||
// id: 'alert.quotaExceeded',
|
||||
// }),
|
||||
// );
|
||||
// } else if (error.toString().includes('code 400')) {
|
||||
// Alert.alert(
|
||||
// intl.formatMessage({
|
||||
// id: 'alert.fail',
|
||||
// }),
|
||||
// intl.formatMessage({
|
||||
// id: 'alert.invalidImage',
|
||||
// }),
|
||||
// );
|
||||
// } else {
|
||||
// Alert.alert(
|
||||
// intl.formatMessage({
|
||||
// id: 'alert.fail',
|
||||
// }),
|
||||
// error.message || error.toString(),
|
||||
// );
|
||||
// }
|
||||
// this.setState({
|
||||
// isUploading: false,
|
||||
// });
|
||||
// });
|
||||
};
|
||||
|
||||
_handleMediaOnSelectFailure = (error) => {
|
||||
@ -1100,6 +1033,8 @@ class EditorContainer extends Component {
|
||||
uploadedImage,
|
||||
community,
|
||||
isDraft,
|
||||
sharedSnippetText,
|
||||
onLoadDraftPress,
|
||||
} = this.state;
|
||||
|
||||
const tags = navigation.state.params && navigation.state.params.tags;
|
||||
@ -1133,6 +1068,8 @@ class EditorContainer extends Component {
|
||||
community={community}
|
||||
currentAccount={currentAccount}
|
||||
isDraft={isDraft}
|
||||
sharedSnippetText={sharedSnippetText}
|
||||
onLoadDraftPress={onLoadDraftPress}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
@ -19,6 +19,7 @@ import {
|
||||
SelectCommunityModalContainer,
|
||||
Modal,
|
||||
UserAvatar,
|
||||
MainButton,
|
||||
} from '../../../components';
|
||||
|
||||
// dhive
|
||||
@ -320,6 +321,8 @@ class EditorScreen extends Component {
|
||||
handleBeneficiaries,
|
||||
currentAccount,
|
||||
autoFocusText,
|
||||
sharedSnippetText,
|
||||
onLoadDraftPress,
|
||||
} = this.props;
|
||||
const rightButtonText = intl.formatMessage({
|
||||
id: isEdit ? 'basic_header.update' : isReply ? 'basic_header.reply' : 'basic_header.publish',
|
||||
@ -396,6 +399,8 @@ class EditorScreen extends Component {
|
||||
onTitleChanged={this._handleChangeTitle}
|
||||
getCommunity={this._getCommunity}
|
||||
autoFocusText={autoFocusText}
|
||||
sharedSnippetText={sharedSnippetText}
|
||||
onLoadDraftPress={onLoadDraftPress}
|
||||
/>
|
||||
</PostForm>
|
||||
</View>
|
||||
|
@ -7398,7 +7398,7 @@ react-native-actionsheet@ecency/react-native-actionsheet:
|
||||
version "2.4.2"
|
||||
resolved "https://codeload.github.com/ecency/react-native-actionsheet/tar.gz/c74540db08a4c2049ee9c8a8077b5c476b536e2c"
|
||||
|
||||
react-native-animatable@1.3.3:
|
||||
react-native-animatable@1.3.3, react-native-animatable@^1.3.3:
|
||||
version "1.3.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-animatable/-/react-native-animatable-1.3.3.tgz#a13a4af8258e3bb14d0a9d839917e9bb9274ec8a"
|
||||
integrity sha512-2ckIxZQAsvWn25Ho+DK3d1mXIgj7tITkrS4pYDvx96WyOttSvzzFeQnM2od0+FUMzILbdHDsDEqZvnz1DYNQ1w==
|
||||
|
Loading…
Reference in New Issue
Block a user