mirror of
https://github.com/ecency/ecency-mobile.git
synced 2024-12-16 18:03:14 +03:00
Merge branch 'development' into fav-notif
This commit is contained in:
commit
cf896cd049
@ -107,7 +107,6 @@
|
||||
"react-native-highlight-words": "^1.0.1",
|
||||
"react-native-iap": "^7.5.6",
|
||||
"react-native-image-crop-picker": "^0.35.2",
|
||||
"react-native-image-size": "^1.1.3",
|
||||
"react-native-image-zoom-viewer": "^2.2.27",
|
||||
"react-native-iphone-x-helper": "^1.3.1",
|
||||
"react-native-keyboard-aware-scroll-view": "^0.9.1",
|
||||
|
@ -14,16 +14,9 @@ export default EStyleSheet.create({
|
||||
body: {
|
||||
marginHorizontal: 9,
|
||||
},
|
||||
image: {
|
||||
margin: 0,
|
||||
alignItems: 'center',
|
||||
alignSelf: 'center',
|
||||
//height: 200,
|
||||
//width: '$deviceWidth - 16',
|
||||
borderRadius: 8,
|
||||
backgroundColor: '$primaryLightGray',
|
||||
// paddingVertical: 10,
|
||||
marginVertical: 5,
|
||||
thumbnail: {
|
||||
width: '$deviceWidth - 16',
|
||||
height: 300
|
||||
},
|
||||
postDescripton: {
|
||||
flexDirection: 'column',
|
||||
|
@ -1,7 +1,6 @@
|
||||
import React, { useRef, useState, useEffect, Fragment } from 'react';
|
||||
import { View, Text, TouchableOpacity } from 'react-native';
|
||||
import { injectIntl } from 'react-intl';
|
||||
import ImageSize from 'react-native-image-size';
|
||||
|
||||
// Utils
|
||||
import { getTimeFromNow } from '../../../utils/time';
|
||||
@ -9,20 +8,14 @@ import { getTimeFromNow } from '../../../utils/time';
|
||||
// Components
|
||||
import { PostHeaderDescription } from '../../postElements';
|
||||
import { IconButton } from '../../iconButton';
|
||||
import ProgressiveImage from '../../progressiveImage';
|
||||
import { OptionsModal } from '../../atoms';
|
||||
|
||||
// Styles
|
||||
import styles from './draftListItemStyles';
|
||||
import { ScheduledPostStatus } from '../../../providers/ecency/ecency.types';
|
||||
import { PopoverWrapper } from '../../popoverWrapper/popoverWrapperView';
|
||||
import getWindowDimensions from '../../../utils/getWindowDimensions';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
|
||||
// Defaults
|
||||
const DEFAULT_IMAGE =
|
||||
'https://images.ecency.com/DQmT8R33geccEjJfzZEdsRHpP3VE8pu3peRCnQa1qukU4KR/no_image_3x.png';
|
||||
|
||||
const dim = getWindowDimensions();
|
||||
|
||||
const DraftListItemView = ({
|
||||
title,
|
||||
@ -45,32 +38,13 @@ const DraftListItemView = ({
|
||||
}) => {
|
||||
const actionSheet = useRef(null);
|
||||
const moveActionSheet = useRef(null);
|
||||
|
||||
const [calcImgHeight, setCalcImgHeight] = useState(300);
|
||||
|
||||
const [deleteRequested, setIsDeleteRequested] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
if (deleteRequested && !isDeleting) {
|
||||
setIsDeleteRequested(false);
|
||||
}
|
||||
}, [isDeleting]);
|
||||
|
||||
// Component Life Cycles
|
||||
useEffect(() => {
|
||||
let _isMounted = false;
|
||||
if (image) {
|
||||
if (!_isMounted) {
|
||||
ImageSize.getSize(thumbnail.uri).then((size) => {
|
||||
setCalcImgHeight(Math.floor((size.height / size.width) * dim.width));
|
||||
});
|
||||
}
|
||||
}
|
||||
return () => {
|
||||
_isMounted = true;
|
||||
};
|
||||
}, []);
|
||||
|
||||
const _onItemPress = () => {
|
||||
if (isSchedules) {
|
||||
moveActionSheet.current.show();
|
||||
@ -85,24 +59,24 @@ const DraftListItemView = ({
|
||||
status === ScheduledPostStatus.PENDING
|
||||
? intl.formatMessage({ id: 'schedules.pending' })
|
||||
: status === ScheduledPostStatus.POSTPONED
|
||||
? intl.formatMessage({ id: 'schedules.postponed' })
|
||||
: status === ScheduledPostStatus.PUBLISHED
|
||||
? intl.formatMessage({ id: 'schedules.published' })
|
||||
: intl.formatMessage({ id: 'schedules.error' });
|
||||
? intl.formatMessage({ id: 'schedules.postponed' })
|
||||
: status === ScheduledPostStatus.PUBLISHED
|
||||
? intl.formatMessage({ id: 'schedules.published' })
|
||||
: intl.formatMessage({ id: 'schedules.error' });
|
||||
const statusIcon =
|
||||
status === ScheduledPostStatus.PENDING
|
||||
? 'timer'
|
||||
: status === ScheduledPostStatus.POSTPONED
|
||||
? 'schedule'
|
||||
: status === ScheduledPostStatus.PUBLISHED
|
||||
? 'check-circle'
|
||||
: 'error';
|
||||
? 'schedule'
|
||||
: status === ScheduledPostStatus.PUBLISHED
|
||||
? 'check-circle'
|
||||
: 'error';
|
||||
const statusIconColor =
|
||||
status === ScheduledPostStatus.PUBLISHED
|
||||
? '#4FD688'
|
||||
: status === ScheduledPostStatus.ERROR
|
||||
? '#e63535'
|
||||
: '#c1c5c7';
|
||||
? '#e63535'
|
||||
: '#c1c5c7';
|
||||
|
||||
return (
|
||||
<Fragment>
|
||||
@ -145,13 +119,10 @@ const DraftListItemView = ({
|
||||
<View style={styles.body}>
|
||||
<TouchableOpacity onPress={_onItemPress}>
|
||||
{image !== null && (
|
||||
<ProgressiveImage
|
||||
<FastImage
|
||||
source={image}
|
||||
thumbnailSource={thumbnail}
|
||||
style={[
|
||||
styles.thumbnail,
|
||||
{ width: dim.width - 16, height: Math.min(calcImgHeight, dim.height) },
|
||||
]}
|
||||
style={styles.thumbnail}
|
||||
resizeMode={FastImage.resizeMode.cover}
|
||||
/>
|
||||
)}
|
||||
<View style={[styles.postDescripton]}>
|
@ -2,105 +2,105 @@ import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useAppDispatch } from '../../hooks';
|
||||
import { toastNotification } from '../../redux/actions/uiAction';
|
||||
import { deleteDraft, deleteScheduledPost, getDrafts, getSchedules, moveScheduledToDraft } from '../ecency/ecency';
|
||||
import {
|
||||
deleteDraft,
|
||||
deleteScheduledPost,
|
||||
getDrafts,
|
||||
getSchedules,
|
||||
moveScheduledToDraft,
|
||||
} from '../ecency/ecency';
|
||||
import QUERIES from './queryKeys';
|
||||
|
||||
|
||||
/** hook used to return user drafts */
|
||||
export const useGetDraftsQuery = () => {
|
||||
return useQuery([QUERIES.DRAFTS.GET], _getDrafts);
|
||||
return useQuery([QUERIES.DRAFTS.GET], _getDrafts);
|
||||
};
|
||||
|
||||
/** used to return user schedules */
|
||||
export const useGetSchedulesQuery = () => {
|
||||
return useQuery([QUERIES.SCHEDULES.GET], _getSchedules);
|
||||
return useQuery([QUERIES.SCHEDULES.GET], _getSchedules);
|
||||
};
|
||||
|
||||
|
||||
export const useDraftDeleteMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation(deleteDraft, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log("Success draft delete", data);
|
||||
queryClient.setQueryData([QUERIES.DRAFTS.GET], _sortData(data));
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
}
|
||||
})
|
||||
}
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation(deleteDraft, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log('Success draft delete', data);
|
||||
queryClient.setQueryData([QUERIES.DRAFTS.GET], _sortData(data));
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useScheduleDeleteMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation(deleteScheduledPost, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log("Success scheduled post delete", data);
|
||||
queryClient.setQueryData([QUERIES.SCHEDULES.GET], _sortData(data));
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
}
|
||||
})
|
||||
}
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation(deleteScheduledPost, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log('Success scheduled post delete', data);
|
||||
queryClient.setQueryData([QUERIES.SCHEDULES.GET], _sortData(data));
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useMoveScheduleToDraftsMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation(moveScheduledToDraft, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log("Moved to drafts data", data);
|
||||
queryClient.setQueryData([QUERIES.SCHEDULES.GET], _sortData(data))
|
||||
queryClient.invalidateQueries([
|
||||
QUERIES.DRAFTS.GET,
|
||||
])
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.success_moved' })))
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation(moveScheduledToDraft, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log('Moved to drafts data', data);
|
||||
queryClient.setQueryData([QUERIES.SCHEDULES.GET], _sortData(data));
|
||||
queryClient.invalidateQueries([QUERIES.DRAFTS.GET]);
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.success_moved' })));
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
const _getDrafts = async () => {
|
||||
try {
|
||||
const data = await getDrafts();
|
||||
return _sortData(data || []);
|
||||
} catch (err) {
|
||||
throw new Error('draft.load_error');
|
||||
}
|
||||
try {
|
||||
const data = await getDrafts();
|
||||
return _sortData(data || []);
|
||||
} catch (err) {
|
||||
throw new Error('draft.load_error');
|
||||
}
|
||||
};
|
||||
|
||||
const _getSchedules = async () => {
|
||||
try {
|
||||
const data = await getSchedules();
|
||||
return _sortDataS(data);
|
||||
} catch (err) {
|
||||
throw new Error('drafts.load_error');
|
||||
}
|
||||
try {
|
||||
const data = await getSchedules();
|
||||
return _sortDataS(data);
|
||||
} catch (err) {
|
||||
throw new Error('drafts.load_error');
|
||||
}
|
||||
};
|
||||
|
||||
const _sortDataS = (data) =>
|
||||
data.sort((a, b) => {
|
||||
const dateA = new Date(a.schedule).getTime();
|
||||
const dateB = new Date(b.schedule).getTime();
|
||||
data.sort((a, b) => {
|
||||
const dateA = new Date(a.schedule).getTime();
|
||||
const dateB = new Date(b.schedule).getTime();
|
||||
|
||||
return dateB > dateA ? 1 : -1;
|
||||
});
|
||||
return dateB > dateA ? 1 : -1;
|
||||
});
|
||||
|
||||
const _sortData = (data) =>
|
||||
data.sort((a, b) => {
|
||||
const dateA = new Date(a.created).getTime();
|
||||
const dateB = new Date(b.created).getTime();
|
||||
data.sort((a, b) => {
|
||||
const dateA = new Date(a.created).getTime();
|
||||
const dateB = new Date(b.created).getTime();
|
||||
|
||||
return dateB > dateA ? 1 : -1;
|
||||
});
|
||||
return dateB > dateA ? 1 : -1;
|
||||
});
|
||||
|
@ -2,63 +2,70 @@ import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'rea
|
||||
import { useIntl } from 'react-intl';
|
||||
import { View } from 'react-native';
|
||||
|
||||
import { BeneficiarySelectionContent, DateTimePicker, MainButton, Modal, SettingsItem } from '../../../components';
|
||||
import { View as AnimatedView } from 'react-native-animatable';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
import {
|
||||
BeneficiarySelectionContent,
|
||||
DateTimePicker,
|
||||
MainButton,
|
||||
Modal,
|
||||
SettingsItem,
|
||||
} from '../../../components';
|
||||
import styles from './postOptionsModalStyles';
|
||||
import ThumbSelectionContent from './thumbSelectionContent';
|
||||
import {View as AnimatedView} from 'react-native-animatable';
|
||||
import { KeyboardAwareScrollView } from 'react-native-keyboard-aware-scroll-view';
|
||||
|
||||
const REWARD_TYPES = [
|
||||
{
|
||||
key:'default',
|
||||
intlId:'editor.reward_default'
|
||||
key: 'default',
|
||||
intlId: 'editor.reward_default',
|
||||
},
|
||||
{
|
||||
key:'sp',
|
||||
intlId:'editor.reward_power_up'
|
||||
key: 'sp',
|
||||
intlId: 'editor.reward_power_up',
|
||||
},
|
||||
{
|
||||
key:'dp',
|
||||
intlId:'editor.reward_decline'
|
||||
key: 'dp',
|
||||
intlId: 'editor.reward_decline',
|
||||
},
|
||||
]
|
||||
|
||||
|
||||
];
|
||||
|
||||
export interface PostOptionsModalRef {
|
||||
showModal:()=>void;
|
||||
showModal: () => void;
|
||||
}
|
||||
|
||||
|
||||
interface PostOptionsModalProps {
|
||||
body:string;
|
||||
draftId:string;
|
||||
thumbUrl:string,
|
||||
isEdit:boolean;
|
||||
isCommunityPost:boolean;
|
||||
body: string;
|
||||
draftId: string;
|
||||
thumbUrl: string;
|
||||
isEdit: boolean;
|
||||
isCommunityPost: boolean;
|
||||
rewardType: string;
|
||||
isUploading: boolean;
|
||||
handleRewardChange:(rewardType:string)=>void;
|
||||
handleThumbSelection:(url:string)=>void;
|
||||
handleScheduleChange:(datetime:string|null)=>void;
|
||||
handleShouldReblogChange:(shouldReblog:boolean)=>void;
|
||||
handleFormUpdate:()=>void;
|
||||
handleRewardChange: (rewardType: string) => void;
|
||||
handleThumbSelection: (url: string) => void;
|
||||
handleScheduleChange: (datetime: string | null) => void;
|
||||
handleShouldReblogChange: (shouldReblog: boolean) => void;
|
||||
handleFormUpdate: () => void;
|
||||
}
|
||||
|
||||
const PostOptionsModal = forwardRef(({
|
||||
body,
|
||||
draftId,
|
||||
thumbUrl,
|
||||
isEdit,
|
||||
isCommunityPost,
|
||||
rewardType,
|
||||
isUploading,
|
||||
handleRewardChange,
|
||||
handleThumbSelection,
|
||||
handleScheduleChange,
|
||||
handleShouldReblogChange,
|
||||
handleFormUpdate
|
||||
}: PostOptionsModalProps, ref) => {
|
||||
const PostOptionsModal = forwardRef(
|
||||
(
|
||||
{
|
||||
body,
|
||||
draftId,
|
||||
thumbUrl,
|
||||
isEdit,
|
||||
isCommunityPost,
|
||||
rewardType,
|
||||
isUploading,
|
||||
handleRewardChange,
|
||||
handleThumbSelection,
|
||||
handleScheduleChange,
|
||||
handleShouldReblogChange,
|
||||
handleFormUpdate,
|
||||
}: PostOptionsModalProps,
|
||||
ref,
|
||||
) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
@ -70,84 +77,83 @@ const PostOptionsModal = forwardRef(({
|
||||
|
||||
// removed the useeffect causing index reset bug
|
||||
|
||||
useEffect(()=>{
|
||||
if(!scheduleLater){
|
||||
handleScheduleChange(null)
|
||||
}else if(scheduledFor) {
|
||||
handleScheduleChange(scheduledFor)
|
||||
}
|
||||
}, [scheduleLater, scheduledFor])
|
||||
|
||||
useEffect(() => {
|
||||
handleShouldReblogChange(shouldReblog)
|
||||
}, [shouldReblog])
|
||||
if (!scheduleLater) {
|
||||
handleScheduleChange(null);
|
||||
} else if (scheduledFor) {
|
||||
handleScheduleChange(scheduledFor);
|
||||
}
|
||||
}, [scheduleLater, scheduledFor]);
|
||||
|
||||
useEffect(() => {
|
||||
if(!isCommunityPost && shouldReblog){
|
||||
handleShouldReblogChange(shouldReblog);
|
||||
}, [shouldReblog]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isCommunityPost && shouldReblog) {
|
||||
setShouldReblog(false);
|
||||
}
|
||||
}, [isCommunityPost])
|
||||
}, [isCommunityPost]);
|
||||
|
||||
// load rewardtype from props if it is already saved in drafts
|
||||
useEffect(() => {
|
||||
if(rewardType){
|
||||
let rewardTypeKey = REWARD_TYPES.findIndex((item) => item.key === rewardType)
|
||||
if (rewardType) {
|
||||
let rewardTypeKey = REWARD_TYPES.findIndex((item) => item.key === rewardType);
|
||||
setRewardTypeIndex(rewardTypeKey);
|
||||
}
|
||||
},[rewardType])
|
||||
}, [rewardType]);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
show: () => {
|
||||
setShowModal(true);
|
||||
},
|
||||
}));
|
||||
show: () => {
|
||||
setShowModal(true);
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
const _handleRewardChange = (index:number) => {
|
||||
setRewardTypeIndex(index)
|
||||
const rewardTypeKey = REWARD_TYPES[index].key
|
||||
const _handleRewardChange = (index: number) => {
|
||||
setRewardTypeIndex(index);
|
||||
const rewardTypeKey = REWARD_TYPES[index].key;
|
||||
if (handleRewardChange) {
|
||||
handleRewardChange(rewardTypeKey);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const _handleDatePickerChange = (date:string) => {
|
||||
const _handleDatePickerChange = (date: string) => {
|
||||
setScheduledFor(date);
|
||||
}
|
||||
};
|
||||
|
||||
const _onDonePress = () => {
|
||||
setShowModal(false);
|
||||
handleFormUpdate();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
// handle index change here instead of useeffetc
|
||||
const _handleThumbIndexSelection = (url:string) => {
|
||||
handleThumbSelection(url)
|
||||
}
|
||||
const _handleThumbIndexSelection = (url: string) => {
|
||||
handleThumbSelection(url);
|
||||
};
|
||||
|
||||
const _renderContent = () => (
|
||||
<View style={styles.fillSpace}>
|
||||
<KeyboardAwareScrollView style={styles.fillSpace} >
|
||||
<KeyboardAwareScrollView style={styles.fillSpace}>
|
||||
<View style={styles.container}>
|
||||
{!isEdit && (
|
||||
<>
|
||||
<SettingsItem
|
||||
title={intl.formatMessage({id:'editor.scheduled_for'}) }
|
||||
title={intl.formatMessage({ id: 'editor.scheduled_for' })}
|
||||
type="dropdown"
|
||||
actionType="reward"
|
||||
options={[
|
||||
intl.formatMessage({id:"editor.scheduled_immediate"}),
|
||||
intl.formatMessage({id:"editor.scheduled_later"}),
|
||||
intl.formatMessage({ id: 'editor.scheduled_immediate' }),
|
||||
intl.formatMessage({ id: 'editor.scheduled_later' }),
|
||||
]}
|
||||
selectedOptionIndex={scheduleLater ? 1 : 0}
|
||||
handleOnChange={(index)=> {
|
||||
handleOnChange={(index) => {
|
||||
setScheduleLater(index === 1);
|
||||
if (index !== 1) {
|
||||
handleScheduleChange(null);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
|
||||
|
||||
{scheduleLater && (
|
||||
<AnimatedView animation="flipInX" duration={700}>
|
||||
<DateTimePicker
|
||||
@ -156,23 +162,19 @@ const PostOptionsModal = forwardRef(({
|
||||
disabled={true}
|
||||
/>
|
||||
</AnimatedView>
|
||||
|
||||
)}
|
||||
|
||||
|
||||
<SettingsItem
|
||||
title={intl.formatMessage({
|
||||
id: 'editor.setting_reward',
|
||||
})}
|
||||
type="dropdown"
|
||||
actionType="reward"
|
||||
options={
|
||||
REWARD_TYPES.map((type)=>intl.formatMessage({ id: type.intlId}))
|
||||
}
|
||||
options={REWARD_TYPES.map((type) => intl.formatMessage({ id: type.intlId }))}
|
||||
selectedOptionIndex={rewardTypeIndex}
|
||||
handleOnChange={_handleRewardChange}
|
||||
/>
|
||||
|
||||
|
||||
|
||||
{isCommunityPost && (
|
||||
<SettingsItem
|
||||
title={intl.formatMessage({
|
||||
@ -184,42 +186,33 @@ const PostOptionsModal = forwardRef(({
|
||||
handleOnChange={setShouldReblog}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
</>
|
||||
)}
|
||||
|
||||
|
||||
<ThumbSelectionContent
|
||||
|
||||
<ThumbSelectionContent
|
||||
body={body}
|
||||
thumbUrl={thumbUrl}
|
||||
isUploading={isUploading}
|
||||
onThumbSelection={_handleThumbIndexSelection}
|
||||
/>
|
||||
|
||||
|
||||
{!isEdit && (
|
||||
<BeneficiarySelectionContent
|
||||
draftId={draftId}
|
||||
setDisableDone={setDisableDone}
|
||||
/>
|
||||
<BeneficiarySelectionContent draftId={draftId} setDisableDone={setDisableDone} />
|
||||
)}
|
||||
|
||||
|
||||
</View>
|
||||
</KeyboardAwareScrollView>
|
||||
|
||||
<MainButton
|
||||
style={{...styles.saveButton }}
|
||||
style={{ ...styles.saveButton }}
|
||||
isDisable={disableDone}
|
||||
onPress={_onDonePress}
|
||||
text={intl.formatMessage({id:"editor.done"})}
|
||||
/>
|
||||
text={intl.formatMessage({ id: 'editor.done' })}
|
||||
/>
|
||||
</View>
|
||||
|
||||
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
return (
|
||||
<Modal
|
||||
return (
|
||||
<Modal
|
||||
isOpen={showModal}
|
||||
handleOnModalClose={() => {
|
||||
setShowModal(false);
|
||||
@ -228,14 +221,14 @@ const PostOptionsModal = forwardRef(({
|
||||
isFullScreen
|
||||
isCloseButton
|
||||
presentationStyle="formSheet"
|
||||
title={intl.formatMessage({id:"editor.settings_title"})}
|
||||
title={intl.formatMessage({ id: 'editor.settings_title' })}
|
||||
animationType="slide"
|
||||
style={styles.modalStyle}
|
||||
>
|
||||
{_renderContent()}
|
||||
</Modal>
|
||||
|
||||
);
|
||||
});
|
||||
{_renderContent()}
|
||||
</Modal>
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
export default PostOptionsModal
|
||||
export default PostOptionsModal;
|
||||
|
@ -2,60 +2,59 @@ import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
import { getBottomSpace } from 'react-native-iphone-x-helper';
|
||||
|
||||
export default EStyleSheet.create({
|
||||
|
||||
sheetContent: {
|
||||
backgroundColor: '$primaryBackgroundColor',
|
||||
position:'absolute',
|
||||
bottom:0,
|
||||
left:0,
|
||||
right:0,
|
||||
zIndex:999
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
left: 0,
|
||||
right: 0,
|
||||
zIndex: 999,
|
||||
},
|
||||
thumbStyle: {
|
||||
width: 72,
|
||||
height: 72,
|
||||
marginVertical: 8,
|
||||
marginRight: 8,
|
||||
borderRadius: 12,
|
||||
backgroundColor: '$primaryLightGray',
|
||||
},
|
||||
checkContainer: {
|
||||
position: 'absolute',
|
||||
top: 12,
|
||||
left: 6,
|
||||
backgroundColor: '$pureWhite',
|
||||
borderRadius: 12,
|
||||
},
|
||||
settingLabel: {
|
||||
color: '$primaryDarkGray',
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
flexGrow: 1,
|
||||
textAlign: 'left',
|
||||
},
|
||||
listContainer: {
|
||||
paddingBottom: getBottomSpace() + 16,
|
||||
},
|
||||
container: {
|
||||
paddingVertical: 16,
|
||||
},
|
||||
bodyWrapper: { flex: 1, paddingTop: 20, paddingBottom: 20 },
|
||||
inputWrapper: { flexDirection: 'row', alignItems: 'center' },
|
||||
contentLabel: { color: '$iconColor', marginTop: 4, textAlign: 'left' },
|
||||
weightInput: { width: 80 },
|
||||
weightFormInput: { flex: 1, color: '$primaryBlack', paddingLeft: 12 },
|
||||
weightFormInputWrapper: { marginTop: 8 },
|
||||
usernameInput: { flex: 1, color: '$primaryBlack', marginLeft: 16 },
|
||||
usernameFormInputWrapper: { marginTop: 8, marginRight: 12 },
|
||||
footerWrapper: { paddingTop: 16 },
|
||||
saveButton: {
|
||||
width: 140,
|
||||
height: 44,
|
||||
alignSelf: 'flex-end',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
doneButton: { borderRadius: 16, backgroundColor: '$primaryBlue' },
|
||||
thumbSelectContainer: {
|
||||
marginTop: 12,
|
||||
},
|
||||
thumbStyle:{
|
||||
width:72,
|
||||
height:72,
|
||||
marginVertical:8,
|
||||
marginRight:8,
|
||||
borderRadius:12,
|
||||
backgroundColor:'$primaryLightGray'
|
||||
},
|
||||
checkContainer:{
|
||||
position: 'absolute',
|
||||
top: 12,
|
||||
left: 6,
|
||||
backgroundColor: '$pureWhite',
|
||||
borderRadius: 12
|
||||
},
|
||||
settingLabel:{
|
||||
color: '$primaryDarkGray',
|
||||
fontSize: 14,
|
||||
fontWeight: 'bold',
|
||||
flexGrow: 1,
|
||||
textAlign:'left',
|
||||
},
|
||||
listContainer:{
|
||||
paddingBottom:getBottomSpace() + 16,
|
||||
},
|
||||
container:{
|
||||
paddingVertical:16
|
||||
},
|
||||
bodyWrapper: { flex: 1, paddingTop: 20, paddingBottom:20},
|
||||
inputWrapper: { flexDirection: 'row', alignItems: 'center'},
|
||||
contentLabel: { color: '$iconColor', marginTop:4, textAlign:'left' },
|
||||
weightInput: {width:80},
|
||||
weightFormInput: { flex:1, color: '$primaryBlack', paddingLeft: 12 },
|
||||
weightFormInputWrapper: { marginTop: 8 },
|
||||
usernameInput: { flex:1, color: '$primaryBlack', marginLeft: 16 },
|
||||
usernameFormInputWrapper: { marginTop: 8, marginRight: 12 },
|
||||
footerWrapper: { paddingTop:16 },
|
||||
saveButton: {
|
||||
width: 140,
|
||||
height: 44,
|
||||
alignSelf: 'flex-end',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
doneButton:{borderRadius:16, backgroundColor:'$primaryBlue'},
|
||||
thumbSelectContainer:{
|
||||
marginTop:12,
|
||||
}
|
||||
});
|
||||
|
@ -3,115 +3,107 @@ import { useIntl } from 'react-intl';
|
||||
import { ActivityIndicator, Alert, Text, TouchableOpacity, View } from 'react-native';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { FlatList } from 'react-native-gesture-handler';
|
||||
import { extractImageUrls } from '../../../utils/editor';
|
||||
import styles from './styles';
|
||||
import ESStyleSheet from 'react-native-extended-stylesheet';
|
||||
import { Icon } from '../../../components';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
import { View as AnimatedView } from 'react-native-animatable';
|
||||
import { extractImageUrls } from '../../../utils/editor';
|
||||
import styles from './styles';
|
||||
import { Icon } from '../../../components';
|
||||
|
||||
interface ThumbSelectionContentProps {
|
||||
body: string;
|
||||
thumbUrl: string;
|
||||
isUploading: boolean;
|
||||
onThumbSelection: (url: string) => void;
|
||||
body: string;
|
||||
thumbUrl: string;
|
||||
isUploading: boolean;
|
||||
onThumbSelection: (url: string) => void;
|
||||
}
|
||||
|
||||
const ThumbSelectionContent = ({ body, thumbUrl, onThumbSelection, isUploading }: ThumbSelectionContentProps) => {
|
||||
const intl = useIntl();
|
||||
const ThumbSelectionContent = ({
|
||||
body,
|
||||
thumbUrl,
|
||||
onThumbSelection,
|
||||
isUploading,
|
||||
}: ThumbSelectionContentProps) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [imageUrls, setImageUrls] = useState<string[]>([]);
|
||||
const [needMore, setNeedMore] = useState(true);
|
||||
const [thumbIndex, setThumbIndex] = useState(0);
|
||||
const [imageUrls, setImageUrls] = useState<string[]>([]);
|
||||
const [needMore, setNeedMore] = useState(true);
|
||||
const [thumbIndex, setThumbIndex] = useState(0);
|
||||
|
||||
useEffect(() => {
|
||||
const urls = extractImageUrls({ body });
|
||||
|
||||
useEffect(() => {
|
||||
const urls = extractImageUrls({ body });
|
||||
|
||||
if (urls.length < 2) {
|
||||
setNeedMore(true);
|
||||
onThumbSelection(urls[0] || '');
|
||||
setThumbIndex(0);
|
||||
setImageUrls([])
|
||||
} else {
|
||||
setNeedMore(false);
|
||||
setImageUrls(urls)
|
||||
}
|
||||
|
||||
const _urlIndex = urls.indexOf(thumbUrl)
|
||||
if (_urlIndex < 0) {
|
||||
onThumbSelection(urls[0] || '');
|
||||
setThumbIndex(0);
|
||||
} else {
|
||||
setThumbIndex(_urlIndex)
|
||||
}
|
||||
|
||||
}, [body])
|
||||
|
||||
|
||||
//VIEW_RENDERERS
|
||||
const _renderImageItem = ({ item, index }: { item: string, index: number }) => {
|
||||
const _onPress = () => {
|
||||
onThumbSelection(item);
|
||||
setThumbIndex(index);
|
||||
}
|
||||
|
||||
const isSelected = item === thumbUrl && index === thumbIndex;
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={() => _onPress()} >
|
||||
<FastImage
|
||||
source={{ uri: item }}
|
||||
style={styles.thumbStyle}
|
||||
resizeMode='cover'
|
||||
/>
|
||||
{isSelected && (
|
||||
|
||||
<AnimatedView duration={300} animation='zoomIn' style={styles.checkContainer}>
|
||||
<Icon
|
||||
color={EStyleSheet.value('$primaryBlue')}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name={'checkbox-marked-circle'}
|
||||
size={20}
|
||||
/>
|
||||
</AnimatedView>
|
||||
)}
|
||||
|
||||
|
||||
|
||||
</TouchableOpacity>
|
||||
)
|
||||
if (urls.length < 2) {
|
||||
setNeedMore(true);
|
||||
onThumbSelection(urls[0] || '');
|
||||
setThumbIndex(0);
|
||||
setImageUrls([]);
|
||||
} else {
|
||||
setNeedMore(false);
|
||||
setImageUrls(urls);
|
||||
}
|
||||
|
||||
const _renderHeader = () => (
|
||||
isUploading &&
|
||||
<View style={{ flex: 1, justifyContent: 'center', marginRight: 16 }}>
|
||||
<ActivityIndicator color={ESStyleSheet.value('$primaryBlack')} />
|
||||
</View>
|
||||
const _urlIndex = urls.indexOf(thumbUrl);
|
||||
if (_urlIndex < 0) {
|
||||
onThumbSelection(urls[0] || '');
|
||||
setThumbIndex(0);
|
||||
} else {
|
||||
setThumbIndex(_urlIndex);
|
||||
}
|
||||
}, [body]);
|
||||
|
||||
)
|
||||
//VIEW_RENDERERS
|
||||
const _renderImageItem = ({ item, index }: { item: string; index: number }) => {
|
||||
const _onPress = () => {
|
||||
onThumbSelection(item);
|
||||
setThumbIndex(index);
|
||||
};
|
||||
|
||||
const isSelected = item === thumbUrl && index === thumbIndex;
|
||||
|
||||
return (
|
||||
<View style={styles.thumbSelectContainer}>
|
||||
<Text style={styles.settingLabel}>{intl.formatMessage({ id: 'editor.select_thumb' })}</Text>
|
||||
{
|
||||
needMore ? (
|
||||
<Text style={styles.contentLabel}>{intl.formatMessage({ id: 'editor.add_more_imgs' })}</Text>
|
||||
) : (
|
||||
<FlatList
|
||||
data={imageUrls}
|
||||
renderItem={_renderImageItem}
|
||||
ListHeaderComponent={_renderHeader}
|
||||
keyExtractor={(item, index) => `${item}-${index}`}
|
||||
horizontal={true}
|
||||
contentContainerStyle={styles.listContainer}
|
||||
showsHorizontalScrollIndicator={false} />
|
||||
)
|
||||
}
|
||||
|
||||
</View>
|
||||
<TouchableOpacity onPress={() => _onPress()}>
|
||||
<FastImage source={{ uri: item }} style={styles.thumbStyle} resizeMode="cover" />
|
||||
{isSelected && (
|
||||
<AnimatedView duration={300} animation="zoomIn" style={styles.checkContainer}>
|
||||
<Icon
|
||||
color={EStyleSheet.value('$primaryBlue')}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="checkbox-marked-circle"
|
||||
size={20}
|
||||
/>
|
||||
</AnimatedView>
|
||||
)}
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const _renderHeader = () =>
|
||||
isUploading && (
|
||||
<View style={{ flex: 1, justifyContent: 'center', marginRight: 16 }}>
|
||||
<ActivityIndicator color={ESStyleSheet.value('$primaryBlack')} />
|
||||
</View>
|
||||
);
|
||||
|
||||
return (
|
||||
<View style={styles.thumbSelectContainer}>
|
||||
<Text style={styles.settingLabel}>{intl.formatMessage({ id: 'editor.select_thumb' })}</Text>
|
||||
{needMore ? (
|
||||
<Text style={styles.contentLabel}>
|
||||
{intl.formatMessage({ id: 'editor.add_more_imgs' })}
|
||||
</Text>
|
||||
) : (
|
||||
<FlatList
|
||||
data={imageUrls}
|
||||
renderItem={_renderImageItem}
|
||||
ListHeaderComponent={_renderHeader}
|
||||
keyExtractor={(item, index) => `${item}-${index}`}
|
||||
horizontal={true}
|
||||
contentContainerStyle={styles.listContainer}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
/>
|
||||
)}
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
export default ThumbSelectionContent;
|
||||
|
@ -1,22 +1,20 @@
|
||||
import React, { useImperativeHandle, useRef, useState } from 'react';
|
||||
import React, { useImperativeHandle, useRef, useState, forwardRef } from 'react';
|
||||
import { FlatList } from 'react-native-gesture-handler';
|
||||
import ActionSheet from 'react-native-actions-sheet';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
import styles from './styles';
|
||||
import { extractImageUrls } from '../../../utils/editor';
|
||||
import FastImage from 'react-native-fast-image';
|
||||
import { forwardRef } from 'react';
|
||||
|
||||
import { View, Text, Alert, TouchableOpacity } from 'react-native';
|
||||
import { useIntl } from 'react-intl';
|
||||
|
||||
import { extractImageUrls } from '../../../utils/editor';
|
||||
import styles from './styles';
|
||||
|
||||
export interface ThumbSelectionModalProps {
|
||||
thumbUrl:string;
|
||||
onThumbSelection:(index:number)=>void;
|
||||
thumbUrl: string;
|
||||
onThumbSelection: (index: number) => void;
|
||||
}
|
||||
|
||||
|
||||
const ThumbSelectionModal = ({ onThumbSelection, thumbUrl }:ThumbSelectionModalProps, ref) => {
|
||||
const ThumbSelectionModal = ({ onThumbSelection, thumbUrl }: ThumbSelectionModalProps, ref) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const [imageUrls, setImageUrls] = useState<string[]>([]);
|
||||
@ -24,82 +22,74 @@ const ThumbSelectionModal = ({ onThumbSelection, thumbUrl }:ThumbSelectionModalP
|
||||
|
||||
//CALLBACK_METHODS
|
||||
useImperativeHandle(ref, () => ({
|
||||
show: (postBody:string) => {
|
||||
console.log("Showing action modal")
|
||||
show: (postBody: string) => {
|
||||
console.log('Showing action modal');
|
||||
|
||||
const urls = extractImageUrls({body:postBody});
|
||||
const urls = extractImageUrls({ body: postBody });
|
||||
|
||||
if(urls.length < 2){
|
||||
console.log("Skipping modal show as post images are less than 2");
|
||||
Alert.alert(
|
||||
intl.formatMessage({id:'editor.two_thumbs_required'})
|
||||
)
|
||||
onThumbSelection(0);
|
||||
return;
|
||||
}
|
||||
|
||||
setImageUrls(urls);
|
||||
sheetModalRef.current?.setModalVisible(true);
|
||||
if (urls.length < 2) {
|
||||
console.log('Skipping modal show as post images are less than 2');
|
||||
Alert.alert(intl.formatMessage({ id: 'editor.two_thumbs_required' }));
|
||||
onThumbSelection(0);
|
||||
return;
|
||||
}
|
||||
|
||||
setImageUrls(urls);
|
||||
sheetModalRef.current?.setModalVisible(true);
|
||||
},
|
||||
}));
|
||||
|
||||
|
||||
const _onSelection = (index:number) => {
|
||||
const _onSelection = (index: number) => {
|
||||
onThumbSelection(index);
|
||||
sheetModalRef.current?.setModalVisible(false);
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
//VIEW_RENDERERS
|
||||
const _renderImageItem = ({item, index}:{item:string, index:number}) => {
|
||||
const _onPress = () => {
|
||||
_onSelection(index);
|
||||
}
|
||||
const _renderImageItem = ({ item, index }: { item: string; index: number }) => {
|
||||
const _onPress = () => {
|
||||
_onSelection(index);
|
||||
};
|
||||
|
||||
const selectedStyle = item === thumbUrl ? styles.selectedStyle : null
|
||||
const selectedStyle = item === thumbUrl ? styles.selectedStyle : null;
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={() => _onPress()} >
|
||||
<FastImage
|
||||
source={{uri:item}}
|
||||
style={{...styles.thumbStyle, ...selectedStyle}}
|
||||
resizeMode='cover'
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
<TouchableOpacity onPress={() => _onPress()}>
|
||||
<FastImage
|
||||
source={{ uri: item }}
|
||||
style={{ ...styles.thumbStyle, ...selectedStyle }}
|
||||
resizeMode="cover"
|
||||
/>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
};
|
||||
|
||||
const _renderContent = () => {
|
||||
return (
|
||||
<View style={{alignItems:'center'}} >
|
||||
<Text style={styles.title}>{intl.formatMessage({id:'editor.select_thumb'})}</Text>
|
||||
<FlatList
|
||||
data={imageUrls}
|
||||
renderItem={_renderImageItem}
|
||||
keyExtractor={(item, index)=>`${item}-${index}`}
|
||||
horizontal={true}
|
||||
contentContainerStyle={styles.listContainer}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
/>
|
||||
</View>
|
||||
|
||||
)
|
||||
}
|
||||
|
||||
return (
|
||||
<View style={{ alignItems: 'center' }}>
|
||||
<Text style={styles.title}>{intl.formatMessage({ id: 'editor.select_thumb' })}</Text>
|
||||
<FlatList
|
||||
data={imageUrls}
|
||||
renderItem={_renderImageItem}
|
||||
keyExtractor={(item, index) => `${item}-${index}`}
|
||||
horizontal={true}
|
||||
contentContainerStyle={styles.listContainer}
|
||||
showsHorizontalScrollIndicator={false}
|
||||
/>
|
||||
</View>
|
||||
);
|
||||
};
|
||||
|
||||
return (
|
||||
<ActionSheet
|
||||
ref={sheetModalRef}
|
||||
gestureEnabled={false}
|
||||
hideUnderlay
|
||||
containerStyle={styles.sheetContent}
|
||||
indicatorColor={EStyleSheet.value('$primaryWhiteLightBackground')}
|
||||
>
|
||||
{_renderContent()}
|
||||
</ActionSheet>
|
||||
<ActionSheet
|
||||
ref={sheetModalRef}
|
||||
gestureEnabled={false}
|
||||
hideUnderlay
|
||||
containerStyle={styles.sheetContent}
|
||||
indicatorColor={EStyleSheet.value('$primaryWhiteLightBackground')}
|
||||
>
|
||||
{_renderContent()}
|
||||
</ActionSheet>
|
||||
);
|
||||
};
|
||||
|
||||
export default forwardRef(ThumbSelectionModal);
|
||||
export default forwardRef(ThumbSelectionModal);
|
||||
|
@ -172,12 +172,10 @@ class EditorContainer extends Component<any, any> {
|
||||
this._fetchDraftsForComparison(isReply);
|
||||
}
|
||||
this._requestKeyboardFocus();
|
||||
|
||||
|
||||
AppState.addEventListener('change', this._handleAppStateChange);
|
||||
}
|
||||
|
||||
|
||||
|
||||
componentDidUpdate(prevProps: Readonly<any>, prevState: Readonly<any>): void {
|
||||
if (
|
||||
prevState.rewardType !== this.state.rewardType ||
|
||||
@ -193,12 +191,12 @@ class EditorContainer extends Component<any, any> {
|
||||
this._isMounted = false;
|
||||
}
|
||||
|
||||
_handleAppStateChange = (nextAppState:AppStateStatus) => {
|
||||
_handleAppStateChange = (nextAppState: AppStateStatus) => {
|
||||
if (this._appState.match(/active|forground/) && nextAppState === 'inactive') {
|
||||
this._saveCurrentDraft(this._updatedDraftFields);
|
||||
}
|
||||
this._appState = nextAppState;
|
||||
}
|
||||
};
|
||||
|
||||
_getStorageDraft = async (username, isReply, paramDraft) => {
|
||||
const { drafts } = this.props;
|
||||
|
@ -143,23 +143,23 @@ class EditorScreen extends Component {
|
||||
};
|
||||
|
||||
_handleOnSaveButtonPress = () => {
|
||||
const {draftId, intl} = this.props;
|
||||
if(draftId){
|
||||
Alert.alert(
|
||||
intl.formatMessage({id:'editor.draft_save_title'}),
|
||||
"",
|
||||
[{
|
||||
text:intl.formatMessage({id:'editor.draft_update'}),
|
||||
onPress:()=>this._saveDraftToDB(),
|
||||
},{
|
||||
text:intl.formatMessage({id:'editor.draft_save_new'}),
|
||||
onPress:()=>this._saveDraftToDB(true)
|
||||
},{
|
||||
text:intl.formatMessage({id:'alert.cancel'}),
|
||||
onPress:()=>{},
|
||||
style:'cancel'
|
||||
}]
|
||||
)
|
||||
const { draftId, intl } = this.props;
|
||||
if (draftId) {
|
||||
Alert.alert(intl.formatMessage({ id: 'editor.draft_save_title' }), '', [
|
||||
{
|
||||
text: intl.formatMessage({ id: 'editor.draft_update' }),
|
||||
onPress: () => this._saveDraftToDB(),
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage({ id: 'editor.draft_save_new' }),
|
||||
onPress: () => this._saveDraftToDB(true),
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage({ id: 'alert.cancel' }),
|
||||
onPress: () => {},
|
||||
style: 'cancel',
|
||||
},
|
||||
]);
|
||||
return;
|
||||
}
|
||||
this._saveDraftToDB();
|
||||
@ -174,7 +174,7 @@ class EditorScreen extends Component {
|
||||
|
||||
this.changeTimer = setTimeout(() => {
|
||||
// saveCurrentDraft(fields);
|
||||
updateDraftFields(fields)
|
||||
updateDraftFields(fields);
|
||||
}, 300);
|
||||
};
|
||||
|
||||
@ -182,7 +182,7 @@ class EditorScreen extends Component {
|
||||
const { handleOnSubmit, handleSchedulePress } = this.props;
|
||||
const { fields, scheduledFor } = this.state;
|
||||
|
||||
if(scheduledFor && handleSchedulePress){
|
||||
if (scheduledFor && handleSchedulePress) {
|
||||
handleSchedulePress(scheduledFor, fields);
|
||||
return;
|
||||
}
|
||||
@ -192,29 +192,28 @@ class EditorScreen extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
_handleOnThumbSelection = (url:string) => {
|
||||
_handleOnThumbSelection = (url: string) => {
|
||||
const { setThumbUrl } = this.props;
|
||||
if (setThumbUrl) {
|
||||
setThumbUrl(url);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
_handleScheduleChange = (datetime:string|null) => {
|
||||
_handleScheduleChange = (datetime: string | null) => {
|
||||
this.setState({
|
||||
scheduledFor:datetime,
|
||||
})
|
||||
}
|
||||
scheduledFor: datetime,
|
||||
});
|
||||
};
|
||||
|
||||
_handleRewardChange = (value) => {
|
||||
const { handleRewardChange } = this.props;
|
||||
handleRewardChange(value);
|
||||
}
|
||||
};
|
||||
_handleSettingsPress = () => {
|
||||
if(this.postOptionsModalRef){
|
||||
if (this.postOptionsModalRef) {
|
||||
this.postOptionsModalRef.show();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
_handleIsFormValid = (bodyText) => {
|
||||
const { fields } = this.state;
|
||||
@ -255,7 +254,7 @@ class EditorScreen extends Component {
|
||||
});
|
||||
const jsonMeta = makeJsonMetadata(meta, fields.tags);
|
||||
fields.meta = jsonMeta;
|
||||
|
||||
|
||||
if (
|
||||
get(fields, 'body', '').trim() !== get(_fields, 'body', '').trim() ||
|
||||
get(fields, 'title', '').trim() !== get(_fields, 'title', '').trim() ||
|
||||
@ -264,7 +263,7 @@ class EditorScreen extends Component {
|
||||
) {
|
||||
console.log('jsonMeta : ', jsonMeta);
|
||||
handleFormChanged();
|
||||
|
||||
|
||||
this._saveCurrentDraft(fields);
|
||||
}
|
||||
|
||||
@ -338,7 +337,7 @@ class EditorScreen extends Component {
|
||||
});
|
||||
};
|
||||
|
||||
_saveDraftToDB(saveAsNew?:boolean) {
|
||||
_saveDraftToDB(saveAsNew?: boolean) {
|
||||
const { saveDraftToDB } = this.props;
|
||||
const { fields } = this.state;
|
||||
|
||||
@ -388,10 +387,15 @@ class EditorScreen extends Component {
|
||||
} = this.props;
|
||||
|
||||
const rightButtonText = intl.formatMessage({
|
||||
id: isEdit ? 'basic_header.update' : isReply ? 'basic_header.reply' : scheduledFor ? 'basic_header.schedule' : 'basic_header.publish',
|
||||
id: isEdit
|
||||
? 'basic_header.update'
|
||||
: isReply
|
||||
? 'basic_header.reply'
|
||||
: scheduledFor
|
||||
? 'basic_header.schedule'
|
||||
: 'basic_header.publish',
|
||||
});
|
||||
|
||||
|
||||
const _renderCommunityModal = () => {
|
||||
return (
|
||||
<Modal
|
||||
|
@ -45,8 +45,7 @@ export const generatePermlink = (title, random = false) => {
|
||||
return perm;
|
||||
};
|
||||
|
||||
;export const extractWordAtIndex = (text:string, index:number) => {
|
||||
|
||||
export const extractWordAtIndex = (text: string, index: number) => {
|
||||
const RANGE = 50;
|
||||
|
||||
const _start = index - RANGE;
|
||||
@ -55,32 +54,30 @@ export const generatePermlink = (title, random = false) => {
|
||||
const _length = text.length;
|
||||
|
||||
const textChunk = text.substring(_start > 0 ? _start : 0, _end < _length ? _end : _length);
|
||||
const indexChunk = index < 50 ? index : (
|
||||
_length - index < 50 ? textChunk.length - (_length - index) :
|
||||
RANGE
|
||||
);
|
||||
const indexChunk =
|
||||
index < 50 ? index : _length - index < 50 ? textChunk.length - (_length - index) : RANGE;
|
||||
|
||||
console.log('char at index: ', textChunk[indexChunk]);
|
||||
|
||||
const END_REGEX = /[\s,]/
|
||||
const END_REGEX = /[\s,]/;
|
||||
let word = '';
|
||||
for(let i = indexChunk; i >= 0 && (!END_REGEX.test(textChunk[i]) || i === indexChunk); i--){
|
||||
if(textChunk[i]){
|
||||
for (let i = indexChunk; i >= 0 && (!END_REGEX.test(textChunk[i]) || i === indexChunk); i--) {
|
||||
if (textChunk[i]) {
|
||||
word += textChunk[i];
|
||||
}
|
||||
}
|
||||
word = word.split('').reverse().join('');
|
||||
|
||||
if(!END_REGEX.test(textChunk[indexChunk])){
|
||||
for(let i = indexChunk + 1; i < textChunk.length && !END_REGEX.test(textChunk[i]); i++){
|
||||
if(textChunk[i]){
|
||||
|
||||
if (!END_REGEX.test(textChunk[indexChunk])) {
|
||||
for (let i = indexChunk + 1; i < textChunk.length && !END_REGEX.test(textChunk[i]); i++) {
|
||||
if (textChunk[i]) {
|
||||
word += textChunk[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return word;
|
||||
}
|
||||
};
|
||||
|
||||
export const generateReplyPermlink = (toAuthor) => {
|
||||
if (!toAuthor) {
|
||||
@ -168,52 +165,55 @@ export const makeJsonMetadataForUpdate = (oldJson, meta, tags) => {
|
||||
return Object.assign({}, oldJson, mergedMeta, { tags });
|
||||
};
|
||||
|
||||
|
||||
const extractUrls = (body:string) => {
|
||||
const extractUrls = (body: string) => {
|
||||
const urlReg = /(\b(https?|ftp):\/\/[A-Z0-9+&@#/%?=~_|!:,.;-]*[-A-Z0-9+&@#/%=~_|])/gim;
|
||||
const mUrls = body && body.match(urlReg);
|
||||
return mUrls || [];
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
export const extractImageUrls = ({body, urls}:{body?:string, urls?:string[]}) => {
|
||||
export const extractImageUrls = ({ body, urls }: { body?: string; urls?: string[] }) => {
|
||||
const imgReg = /(https?:\/\/.*\.(?:png|jpg|jpeg|gif|heic|webp))/gim;
|
||||
|
||||
let imgUrls = [];
|
||||
const mUrls = urls || extractUrls(body);
|
||||
|
||||
mUrls.forEach((url)=>{
|
||||
mUrls.forEach((url) => {
|
||||
const isImage = url.match(imgReg);
|
||||
if (isImage) {
|
||||
imgUrls.push(url);
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
return imgUrls;
|
||||
}
|
||||
};
|
||||
|
||||
export const extractFilenameFromPath = ({path, mimeType}:{path:string, mimeType?:string}) => {
|
||||
try{
|
||||
if(!path){
|
||||
throw new Error("path not provided");
|
||||
export const extractFilenameFromPath = ({
|
||||
path,
|
||||
mimeType,
|
||||
}: {
|
||||
path: string;
|
||||
mimeType?: string;
|
||||
}) => {
|
||||
try {
|
||||
if (!path) {
|
||||
throw new Error('path not provided');
|
||||
}
|
||||
const filenameIndex = path.lastIndexOf('/') + 1;
|
||||
const extensionIndex = path.lastIndexOf('.');
|
||||
if(filenameIndex < 0 || extensionIndex <= filenameIndex){
|
||||
throw new Error("file name not present with extension");
|
||||
if (filenameIndex < 0 || extensionIndex <= filenameIndex) {
|
||||
throw new Error('file name not present with extension');
|
||||
}
|
||||
return path.substring(path.lastIndexOf('/') + 1);
|
||||
|
||||
}catch(err){
|
||||
} catch (err) {
|
||||
let _ext = 'jpg';
|
||||
if(mimeType){
|
||||
_ext = MimeTypes.extension(mimeType)
|
||||
if (mimeType) {
|
||||
_ext = MimeTypes.extension(mimeType);
|
||||
}
|
||||
return `${generateRndStr()}.${_ext}`;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export const extractMetadata = (body:string, thumbUrl?:string) => {
|
||||
export const extractMetadata = (body: string, thumbUrl?: string) => {
|
||||
const userReg = /(^|\s)(@[a-z][-.a-z\d]+[a-z\d])/gim;
|
||||
|
||||
const out = {};
|
||||
@ -221,16 +221,16 @@ export const extractMetadata = (body:string, thumbUrl?:string) => {
|
||||
const mUrls = extractUrls(body);
|
||||
const mUsers = body && body.match(userReg);
|
||||
|
||||
const matchedImages = extractImageUrls({urls:mUrls});
|
||||
const matchedImages = extractImageUrls({ urls: mUrls });
|
||||
const matchedLinks = [];
|
||||
const matchedUsers = [];
|
||||
|
||||
if (mUrls) {
|
||||
mUrls.forEach((url)=>{
|
||||
if(matchedImages.indexOf(url) < 0){
|
||||
mUrls.forEach((url) => {
|
||||
if (matchedImages.indexOf(url) < 0) {
|
||||
matchedLinks.push(url);
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
if (matchedLinks.length) {
|
||||
@ -238,10 +238,10 @@ export const extractMetadata = (body:string, thumbUrl?:string) => {
|
||||
}
|
||||
|
||||
if (matchedImages.length) {
|
||||
if(thumbUrl){
|
||||
matchedImages.sort((item)=>item === thumbUrl ? -1 : 1);
|
||||
if (thumbUrl) {
|
||||
matchedImages.sort((item) => (item === thumbUrl ? -1 : 1));
|
||||
}
|
||||
|
||||
|
||||
out.image = matchedImages;
|
||||
}
|
||||
|
||||
@ -270,4 +270,4 @@ export const createPatch = (text1, text2) => {
|
||||
return patch;
|
||||
};
|
||||
|
||||
export const delay = ms => new Promise(res => setTimeout(res, ms));
|
||||
export const delay = (ms) => new Promise((res) => setTimeout(res, ms));
|
||||
|
@ -8926,11 +8926,6 @@ react-native-image-pan-zoom@^2.1.9:
|
||||
resolved "https://registry.yarnpkg.com/react-native-image-pan-zoom/-/react-native-image-pan-zoom-2.1.12.tgz#eb98bf56fb5610379bdbfdb63219cc1baca98fd2"
|
||||
integrity sha512-BF66XeP6dzuANsPmmFsJshM2Jyh/Mo1t8FsGc1L9Q9/sVP8MJULDabB1hms+eAoqgtyhMr5BuXV3E1hJ5U5H6Q==
|
||||
|
||||
react-native-image-size@^1.1.3:
|
||||
version "1.1.3"
|
||||
resolved "https://registry.yarnpkg.com/react-native-image-size/-/react-native-image-size-1.1.3.tgz#7d69c2cd4e1d1632947867e47643ed8cabb9de27"
|
||||
integrity sha512-jJvN6CjXVAm69LAVZNV7m7r50Qk9vuPZwLyrbs/k31/3Xs8bZyVCdvfP44FuBisITn/yFsiOo6i8NPrFBPH20w==
|
||||
|
||||
react-native-image-zoom-viewer@^2.2.27:
|
||||
version "2.2.27"
|
||||
resolved "https://registry.yarnpkg.com/react-native-image-zoom-viewer/-/react-native-image-zoom-viewer-2.2.27.tgz#fb3314c5dc86ac33da48cb31bf4920d97eecb6eb"
|
||||
|
Loading…
Reference in New Issue
Block a user