Merge branch 'development' into nt/comments-cache

This commit is contained in:
noumantahir 2022-02-04 12:23:42 +05:00
commit 2e47348c8f
9 changed files with 205 additions and 72 deletions

View File

@ -128,7 +128,7 @@
"react-native-vector-icons": "^6.6.0",
"react-native-version": "^4.0.0",
"react-native-version-number": "^0.3.5",
"react-native-webview": "^11.2.1",
"react-native-webview": "^11.17.1",
"react-native-youtube-iframe": "^2.1.1",
"react-navigation": "^4.0.10",
"react-navigation-drawer": "^2.3.3",

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react';
import React, { useEffect, useState } from 'react';
import { View, TouchableOpacity } from 'react-native';
import styles from './checkboxStyles';
@ -6,6 +6,10 @@ import styles from './checkboxStyles';
const CheckBoxView = ({ clicked, value, isChecked, style, locked }) => {
const [isCheck, setIsCheck] = useState(false);
useEffect(() => {
setIsCheck(isChecked);
}, [isChecked]);
const _checkClicked = () => {
setIsCheck(!isCheck);

View File

@ -0,0 +1,23 @@
import {replaceBetween } from './utils';
export default async ({ text, selection, setTextAndSelection, items }) => {
const imagePrefix = '!';
let newText = text;
let newSelection = selection;
items.forEach(item => {
if(item.url && item.text){
const formatedText = `\n${imagePrefix}[${item.text}](${item.url})\n`
newText = replaceBetween(newText, newSelection, formatedText);
const newIndex = newText && newText.indexOf(item.url, newSelection.start) + item.url.length + 2;
newSelection = {
start: newIndex,
end: newIndex
}
}
});
setTextAndSelection({ text: newText, selection: newSelection });
};

View File

@ -16,7 +16,7 @@ import { Icon } from '../../icon';
// Utils
import Formats from './formats/formats';
import applyImageLink from './formats/applyWebLinkFormat';
import applyMediaLink from './formats/applyMediaLink';
// Actions
import { toggleAccountsBottomSheet } from '../../../redux/actions/uiAction';
@ -147,12 +147,11 @@ const MarkdownEditorView = ({
useEffect(() => {
if (uploadedImage && uploadedImage.url) {
if (uploadedImage.shouldInsert) {
applyImageLink({
applyMediaLink({
text,
selection,
setTextAndSelection: _setTextAndSelection,
item: { url: uploadedImage.url, text: uploadedImage.hash },
isImage: !!uploadedImage,
items: [{ url: uploadedImage.url, text: uploadedImage.hash }],
});
} else {
uploadsGalleryModalRef.current.showModal();
@ -265,14 +264,18 @@ const MarkdownEditorView = ({
});
};
const _handleOnMediaSelect = (mediaInsert) => {
if (mediaInsert && mediaInsert.url) {
applyImageLink({
const _handleOnMediaSelect = (mediaArray) => {
const items = mediaArray.map((mediaInsert) => ({
url: mediaInsert.url,
text: mediaInsert.hash,
}));
if (items.length) {
applyMediaLink({
text,
selection,
setTextAndSelection: _setTextAndSelection,
item: { url: mediaInsert.url, text: mediaInsert.hash },
isImage: !!mediaInsert,
items,
});
}
};

View File

@ -7,6 +7,7 @@ import { AutoHeightImage } from '../autoHeightImage/autoHeightImage';
import { useHtmlIframeProps, iframeModel } from '@native-html/iframe-plugin';
import WebView from 'react-native-webview';
import { VideoPlayer } from '..';
import { Platform } from 'react-native';
interface PostHtmlRendererProps {
contentWidth: number;
@ -136,7 +137,10 @@ export const PostHtmlRenderer = memo(
//process video link
if(tnode.classes?.indexOf('markdown-video-link') >= 0){
if(isComment){
//TODO: remove android check when fix for react-native-weview scroll crash is available
//ref: https://github.com/react-native-webview/react-native-webview/issues/2364
if(isComment || Platform.OS === 'android'){
const imgElement = tnode.children.find((child) => {
return child.classes.indexOf('video-thumbnail') > 0 ? true : false;
});
@ -225,17 +229,30 @@ export const PostHtmlRenderer = memo(
const checkSrcRegex = /(.*?)\.(mp4|webm|ogg)$/gi;
const isVideoFormat = iframeProps.source.uri.match(checkSrcRegex);
//this hack help avoid autoplaying fullscreened iframe videos;
const src = isVideoFormat ?
{
html: `
<video width="100%" height="auto" controls>
<source src="${iframeProps.source.uri}" type="video/mp4">
</video>`,
}:{
uri: iframeProps.source.uri,
};
//this hack help avoid autoplaying fullscreened iframe videos;
const src = isVideoFormat ?
{
html: `
<video width="100%" height="auto" controls>
<source src="${iframeProps.source.uri}" type="video/mp4">
</video>`,
}:{
uri: iframeProps.source.uri,
};
//TODO: remove android check logic when fix for react-native-webiew scrollview crash is available
//ref: https://github.com/react-native-webview/react-native-webview/issues/2364
if(isComment || Platform.OS === 'android'){
const _onPress = () => {
console.log('iframe thumb Pressed:', iframeProps);
if (handleVideoPress) {
handleVideoPress(iframeProps.source.uri);
}
};
return (
<VideoThumb contentWidth={contentWidth} onPress={_onPress} />
)
}else{
return (
<VideoPlayer
mode='source'
@ -243,6 +260,8 @@ export const PostHtmlRenderer = memo(
contentWidth={contentWidth}
/>
);
}
};
return (

View File

@ -2,7 +2,7 @@ import React, { forwardRef, useEffect, useImperativeHandle, useState } from 'rea
import { useIntl } from 'react-intl';
import {Text, View, FlatList, RefreshControl, TouchableOpacity, Alert, Platform } from 'react-native';
import FastImage from 'react-native-fast-image';
import { IconButton } from '..';
import { CheckBox, MainButton, TextButton } from '..';
import { UploadedMedia } from '../../models';
import { addImage, deleteImage, getImages } from '../../providers/ecency/ecency';
import Modal from '../modal';
@ -21,7 +21,7 @@ interface MediaInsertData {
interface UploadsGalleryModalProps {
username:string;
handleOnSelect:(data:MediaInsertData)=>void;
handleOnSelect:(data:Array<MediaInsertData>)=>void;
uploadedImage:MediaInsertData;
}
@ -30,7 +30,8 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploa
const [mediaUploads, setMediaUploads] = useState([]);
const [isLoading, setIsLoading] = useState(false);
const [showModal, setShowModal] = useState(false);
const [showModal, setShowModal] = useState(false);
const [indices, setIndices] = useState<Map<number, boolean>>(new Map());
useImperativeHandle(ref, () => ({
@ -44,6 +45,12 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploa
_getMediaUploads();
}, []);
useEffect(()=>{
if(!showModal){
setIndices(new Map());
}
}, [showModal])
useEffect(() => {
if(uploadedImage){
_addUploadedImageToGallery();
@ -67,11 +74,14 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploa
// remove image data from user's gallery
const _deleteMediaItem = async (id:string) => {
const _deleteMedia = async () => {
try{
setIsLoading(true);
await deleteImage(id)
for (const index of indices.keys()) {
await deleteImage(mediaUploads[index]._id)
}
await _getMediaUploads();
setIndices(new Map());
setIsLoading(false);
} catch(err){
console.warn("failed to remove image from gallery", err)
@ -92,45 +102,107 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploa
setIsLoading(false);
}
}catch(err){
console.warn("Failed to get snippets")
console.warn("Failed to get images")
setIsLoading(false);
}
}
//render list item for snippet and handle actions;
const _renderItem = ({ item }:{item:UploadedMedia, index:number}) => {
const _onPress = () => {
//inserts media items in post body
const _insertMedia = async (selectedIndex?:number) => {
const map = selectedIndex ? new Map([[selectedIndex, true]]) : indices;
const data = {
url:item.url,
hash:item.url.split('/').pop()
}
const data = []
for (const index of map.keys()) {
console.log(index)
const item = mediaUploads[index]
data.push({
url:item.url,
hash:item.url.split('/').pop()
})
}
handleOnSelect(data)
setShowModal(false);
}
const _onRemovePress = async () => {
const _onConfirm = () => {
_deleteMediaItem(item._id)
//renders footer with add snipept button and shows new snippet modal
const _renderFloatingPanel = () => {
if(!indices.size){
return null
}
const _onRemovePress = async () => {
const _onConfirm = () => {
_deleteMedia()
}
Alert.alert(
intl.formatMessage({id:'alert.delete'}),
intl.formatMessage({id:'alert.remove_alert'}),
[{
text:intl.formatMessage({id:'alert.cancel'}),
style:'cancel'
},{
text:intl.formatMessage({id:'alert.confirm'}),
onPress:_onConfirm
}]
)
}
return (
<View style={styles.floatingContainer}>
<TextButton
style={styles.cancelButton}
onPress={_onRemovePress}
text={intl.formatMessage({
id: 'uploads_modal.btn_delete',
})}
/>
<MainButton
style={{ width: 136, marginLeft:12}}
onPress={_insertMedia}
iconName="plus"
iconType="MaterialCommunityIcons"
iconColor="white"
text={intl.formatMessage({
id: 'uploads_modal.btn_insert',
})}
/>
</View>
);
};
//render list item for snippet and handle actions;
const _renderItem = ({ item, index }:{item:UploadedMedia, index:number}) => {
const _onCheckPress = () => {
//update selection indices
if(indices.has(index)){
indices.delete(index);
}else {
indices.set(index, true);
}
Alert.alert(
intl.formatMessage({id:'alert.delete'}),
intl.formatMessage({id:'alert.remove_alert'}),
[{
text:intl.formatMessage({id:'alert.cancel'}),
style:'cancel'
},{
text:intl.formatMessage({id:'alert.confirm'}),
onPress:_onConfirm
}]
)
setIndices(new Map([...indices]));
}
const _onPress = () => {
if(indices.size){
_onCheckPress()
}else {
_insertMedia(index)
}
}
const thumbUrl = proxifyImageSrc(item.url, 600, 500, Platform.OS === 'ios' ? 'match' : 'webp');
return (
@ -139,14 +211,11 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploa
source={{uri:thumbUrl}}
style={styles.mediaItem}
/>
<View style={styles.removeItemContainer}>
<IconButton
iconStyle={styles.itemIcon}
style={styles.itemIconWrapper}
iconType="MaterialCommunityIcons"
name="delete"
onPress={_onRemovePress}
size={20}
<View style={styles.checkContainer}>
<CheckBox
isChecked={indices.has(index)}
clicked={_onCheckPress}
style={styles.checkStyle}
/>
</View>
@ -176,6 +245,7 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploa
keyExtractor={(item) => `item_${item.url}`}
renderItem={_renderItem}
ListEmptyComponent={_renderEmptyContent}
extraData={indices}
numColumns={2}
refreshControl={
<RefreshControl
@ -185,6 +255,7 @@ export const UploadsGalleryModal = forwardRef(({username, handleOnSelect, uploa
}
/>
</View>
{_renderFloatingPanel()}
</View>
)

View File

@ -22,11 +22,17 @@ export default EStyleSheet.create({
paddingHorizontal:16
},
floatingContainer:{
flexDirection:'row',
position:'absolute',
bottom:0,
right:20,
right:0,
left: 0,
justifyContent:'flex-end',
zIndex:10
alignItems:'center',
zIndex:10,
paddingVertical:8,
paddingHorizontal: 16,
backgroundColor:'$primaryBackgroundColor'
} as ViewStyle,
mediaItem:{
@ -95,9 +101,14 @@ export default EStyleSheet.create({
} as ViewStyle,
removeItemContainer:{
checkContainer:{
position:'absolute',
top:16,
right:16
} as ViewStyle
})
bottom:20,
right:20
} as ViewStyle,
checkStyle:{
backgroundColor:'$white',
} as ViewStyle,
})

View File

@ -363,6 +363,8 @@
"title":"Uploaded Images",
"title_remove_confirmation":"Delete image",
"btn_add":"Image",
"btn_insert":"INSERT",
"btn_delete":"DELETE",
"message_failed":"Failed to upload image"
},
"pincode": {

View File

@ -8856,10 +8856,10 @@ react-native-version@^4.0.0:
resolve-from "^5.0.0"
semver "^7.0.0"
react-native-webview@^11.2.1:
version "11.2.3"
resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-11.2.3.tgz#1b82685ab60645d4161f2e25e98286493cdffa5d"
integrity sha512-r/K+Lf/O5aij72gRndMX2qsyQ/WLtDPiO75SS57y6JjqSKxedGASVL9Jwl1TM7fCXqUq8dgiwik/LuBHbJXAEg==
react-native-webview@^11.17.1:
version "11.17.1"
resolved "https://registry.yarnpkg.com/react-native-webview/-/react-native-webview-11.17.1.tgz#a7c9d995d749539995a4fdad8aa6456bac77fc8f"
integrity sha512-gGdBavATj8Mya2VYZtWtB9cgOAgVJJGlgL5mo/EO8quBeI5L3IBy2ZQolsCyRRGFTUPCc3Ah0OwJal0PjijGqw==
dependencies:
escape-string-regexp "2.0.0"
invariant "2.2.4"