mirror of
https://github.com/ecency/ecency-mobile.git
synced 2025-01-04 03:56:54 +03:00
Merge pull request #2497 from ecency/nt/media-use-query
Nt/media use query
This commit is contained in:
commit
6e203a73b1
@ -182,6 +182,7 @@ export const EditorToolbar = ({
|
||||
paramFiles={paramFiles}
|
||||
isEditing={isEditing}
|
||||
username={currentAccount.username}
|
||||
hideToolbarExtension={_hideExtension}
|
||||
handleMediaInsert={handleMediaInsert}
|
||||
setIsUploading={setIsUploading} />
|
||||
</View>
|
||||
|
@ -1,7 +1,15 @@
|
||||
import { proxifyImageSrc } from '@ecency/render-helper';
|
||||
import React, { useEffect, useRef, useState } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { ActivityIndicator, Alert, Keyboard, Platform, Text, TouchableOpacity, View } from 'react-native';
|
||||
import {
|
||||
ActivityIndicator,
|
||||
Alert,
|
||||
Keyboard,
|
||||
Platform,
|
||||
Text,
|
||||
TouchableOpacity,
|
||||
View,
|
||||
} from 'react-native';
|
||||
import { View as AnimatedView } from 'react-native-animatable';
|
||||
import Animated, { Easing } from 'react-native-reanimated';
|
||||
import EStyleSheet from 'react-native-extended-stylesheet';
|
||||
@ -9,22 +17,25 @@ import FastImage from 'react-native-fast-image';
|
||||
import { FlatList } from 'react-native-gesture-handler';
|
||||
import { Icon, IconButton } from '../..';
|
||||
import { UploadedMedia } from '../../../models';
|
||||
import styles, { COMPACT_HEIGHT, EXPANDED_HEIGHT, MAX_HORIZONTAL_THUMBS } from '../children/uploadsGalleryModalStyles';
|
||||
import styles, {
|
||||
COMPACT_HEIGHT,
|
||||
EXPANDED_HEIGHT,
|
||||
MAX_HORIZONTAL_THUMBS,
|
||||
} from './uploadsGalleryModalStyles';
|
||||
import { useMediaDeleteMutation } from '../../../providers/queries';
|
||||
|
||||
type Props = {
|
||||
insertedMediaUrls: string[],
|
||||
mediaUploads: any[],
|
||||
indices: Map<number, boolean>
|
||||
isLoading: boolean,
|
||||
isAddingToUploads: boolean,
|
||||
getMediaUploads: () => void,
|
||||
deleteMedia: (ids: string) => Promise<boolean>,
|
||||
insertMedia: (map: Map<number, boolean>) => void
|
||||
handleOpenGallery: (addToUploads?: boolean) => void,
|
||||
handleOpenCamera: () => void,
|
||||
handleOpenForUpload: () => void,
|
||||
}
|
||||
|
||||
insertedMediaUrls: string[];
|
||||
mediaUploads: any[];
|
||||
indices: Map<number, boolean>;
|
||||
isAddingToUploads: boolean;
|
||||
getMediaUploads: () => void;
|
||||
deleteMedia: (ids: string) => Promise<boolean>;
|
||||
insertMedia: (map: Map<number, boolean>) => void;
|
||||
handleOpenGallery: (addToUploads?: boolean) => void;
|
||||
handleOpenCamera: () => void;
|
||||
handleOpenForUpload: () => void;
|
||||
};
|
||||
|
||||
const UploadsGalleryContent = ({
|
||||
insertedMediaUrls,
|
||||
@ -36,75 +47,66 @@ const UploadsGalleryContent = ({
|
||||
handleOpenGallery,
|
||||
handleOpenCamera,
|
||||
}: Props) => {
|
||||
const intl = useIntl();
|
||||
|
||||
const intl = useIntl()
|
||||
const deleteMediaMutation = useMediaDeleteMutation();
|
||||
|
||||
const [deleteIds, setDeleteIds] = useState<string[]>([]);
|
||||
const [isDeleting, setIsDeleting] = useState(false);
|
||||
const [isDeleteMode, setIsDeleteMode] = useState(false);
|
||||
const [isExpandedMode, setIsExpandedMode] = useState(false);
|
||||
|
||||
const animatedHeightRef = useRef(new Animated.Value(COMPACT_HEIGHT));
|
||||
|
||||
const isDeleting = deleteMediaMutation.isLoading
|
||||
|
||||
useEffect(() => {
|
||||
if (isExpandedMode) {
|
||||
Keyboard.dismiss()
|
||||
Keyboard.dismiss();
|
||||
}
|
||||
}, [isExpandedMode])
|
||||
|
||||
}, [isExpandedMode]);
|
||||
|
||||
|
||||
const _deleteMedia = async () => {
|
||||
|
||||
setIsDeleting(true)
|
||||
try {
|
||||
for (const i in deleteIds) {
|
||||
await deleteMedia(deleteIds[i])
|
||||
deleteMediaMutation.mutate(deleteIds, {
|
||||
onSettled: () => {
|
||||
setIsDeleteMode(false);
|
||||
setDeleteIds([]);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("Failed to delete media items")
|
||||
}
|
||||
getMediaUploads();
|
||||
setIsDeleting(false);
|
||||
setIsDeleteMode(false);
|
||||
setDeleteIds([]);
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
};
|
||||
|
||||
const _onDeletePress = async () => {
|
||||
if (isDeleteMode && deleteIds.length > 0) {
|
||||
|
||||
const _onCancelPress = () => {
|
||||
setIsDeleteMode(false);
|
||||
setDeleteIds([])
|
||||
}
|
||||
setDeleteIds([]);
|
||||
};
|
||||
|
||||
Alert.alert(
|
||||
intl.formatMessage({ id: 'alert.delete' }),
|
||||
intl.formatMessage({ id: 'uploads_modal.confirm_delete' }),
|
||||
[{
|
||||
text: intl.formatMessage({ id: 'alert.cancel' }),
|
||||
style: 'cancel',
|
||||
onPress: _onCancelPress
|
||||
}, {
|
||||
text: intl.formatMessage({ id: 'alert.confirm' }),
|
||||
onPress: () => _deleteMedia()
|
||||
}]
|
||||
)
|
||||
[
|
||||
{
|
||||
text: intl.formatMessage({ id: 'alert.cancel' }),
|
||||
style: 'cancel',
|
||||
onPress: _onCancelPress,
|
||||
},
|
||||
{
|
||||
text: intl.formatMessage({ id: 'alert.confirm' }),
|
||||
onPress: () => _deleteMedia(),
|
||||
},
|
||||
],
|
||||
);
|
||||
} else {
|
||||
setIsDeleteMode(!isDeleteMode);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//render list item for snippet and handle actions;
|
||||
const _renderItem = ({ item, index }: { item: UploadedMedia, index: number }) => {
|
||||
|
||||
const _renderItem = ({ item, index }: { item: UploadedMedia; index: number }) => {
|
||||
const _onPress = () => {
|
||||
if (isDeleteMode) {
|
||||
const idIndex = deleteIds.indexOf(item._id)
|
||||
const idIndex = deleteIds.indexOf(item._id);
|
||||
if (idIndex >= 0) {
|
||||
deleteIds.splice(idIndex, 1);
|
||||
} else {
|
||||
@ -112,46 +114,37 @@ const UploadsGalleryContent = ({
|
||||
}
|
||||
setDeleteIds([...deleteIds]);
|
||||
} else {
|
||||
insertMedia(new Map([[index, true]]))
|
||||
insertMedia(new Map([[index, true]]));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const thumbUrl = proxifyImageSrc(item.url, 600, 500, Platform.OS === 'ios' ? 'match' : 'webp');
|
||||
let isInsertedTimes = 0;
|
||||
insertedMediaUrls.forEach(url => isInsertedTimes += url === item.url ? 1 : 0);
|
||||
insertedMediaUrls.forEach((url) => (isInsertedTimes += url === item.url ? 1 : 0));
|
||||
const isToBeDeleted = deleteIds.indexOf(item._id) >= 0;
|
||||
const transformStyle = {
|
||||
transform: isToBeDeleted ?
|
||||
[{ scaleX: 0.7 }, { scaleY: 0.7 }] : []
|
||||
}
|
||||
transform: isToBeDeleted ? [{ scaleX: 0.7 }, { scaleY: 0.7 }] : [],
|
||||
};
|
||||
|
||||
const _renderMinus = () => (
|
||||
const _renderMinus = () =>
|
||||
isDeleteMode && (
|
||||
<AnimatedView
|
||||
animation='zoomIn'
|
||||
duration={300}
|
||||
style={styles.minusContainer}>
|
||||
<AnimatedView animation="zoomIn" duration={300} style={styles.minusContainer}>
|
||||
<Icon
|
||||
color={EStyleSheet.value('$pureWhite')}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name={'minus'}
|
||||
name="minus"
|
||||
size={20}
|
||||
/>
|
||||
</AnimatedView>
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
|
||||
const _renderCounter = () => (
|
||||
isInsertedTimes > 0 && !isDeleteMode && (
|
||||
<AnimatedView
|
||||
animation='zoomIn'
|
||||
duration={300}
|
||||
style={styles.counterContainer}>
|
||||
const _renderCounter = () =>
|
||||
isInsertedTimes > 0 &&
|
||||
!isDeleteMode && (
|
||||
<AnimatedView animation="zoomIn" duration={300} style={styles.counterContainer}>
|
||||
<Text style={styles.counterText}>{isInsertedTimes}</Text>
|
||||
</AnimatedView>
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={_onPress} disabled={isDeleting}>
|
||||
@ -164,20 +157,22 @@ const UploadsGalleryContent = ({
|
||||
{_renderMinus()}
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
const _renderSelectButton = (iconName: string, text: string, onPress: () => void) => {
|
||||
return (
|
||||
<TouchableOpacity onPress={() => { onPress && onPress() }}>
|
||||
<TouchableOpacity
|
||||
onPress={() => {
|
||||
onPress && onPress();
|
||||
}}
|
||||
>
|
||||
<View style={styles.selectButton}>
|
||||
|
||||
<View style={styles.selectBtnPlus}>
|
||||
<Icon
|
||||
color={EStyleSheet.value('$primaryBackgroundColor')}
|
||||
iconType="FontAwesome5"
|
||||
name={'plus-circle'}
|
||||
name="plus-circle"
|
||||
size={12}
|
||||
/>
|
||||
</View>
|
||||
@ -192,37 +187,39 @@ const UploadsGalleryContent = ({
|
||||
<Text style={styles.selectButtonLabel}>{text}</Text>
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
)
|
||||
}
|
||||
|
||||
);
|
||||
};
|
||||
|
||||
const _renderHeaderContent = () => (
|
||||
<View style={{ ...styles.buttonsContainer, paddingVertical: isExpandedMode ? 8 : 0 }}>
|
||||
{<View style={styles.selectButtonsContainer} >
|
||||
<View style={styles.selectButtonsContainer}>
|
||||
{_renderSelectButton('image', 'Gallery', handleOpenGallery)}
|
||||
{_renderSelectButton('camera', 'Camera', handleOpenCamera)}
|
||||
</View>}
|
||||
</View>
|
||||
<View style={styles.pillBtnContainer}>
|
||||
<IconButton
|
||||
style={styles.uploadsActionBtn}
|
||||
color={EStyleSheet.value('$primaryBlack')}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name={'plus'}
|
||||
name="plus"
|
||||
size={28}
|
||||
onPress={() => { handleOpenGallery(true) }}
|
||||
onPress={() => {
|
||||
handleOpenGallery(true);
|
||||
}}
|
||||
/>
|
||||
<IconButton
|
||||
style={{
|
||||
...styles.uploadsActionBtn,
|
||||
backgroundColor: isDeleteMode ?
|
||||
EStyleSheet.value('$iconColor')
|
||||
: 'transparent'
|
||||
backgroundColor: isDeleteMode ? EStyleSheet.value('$iconColor') : 'transparent',
|
||||
}}
|
||||
color={EStyleSheet.value('$primaryBlack')}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name={'minus'}
|
||||
name="minus"
|
||||
size={28}
|
||||
onPress={() => { setIsDeleteMode(!isDeleteMode); setDeleteIds([]) }}
|
||||
onPress={() => {
|
||||
setIsDeleteMode(!isDeleteMode);
|
||||
setDeleteIds([]);
|
||||
}}
|
||||
/>
|
||||
</View>
|
||||
|
||||
@ -232,18 +229,18 @@ const UploadsGalleryContent = ({
|
||||
</View>
|
||||
)}
|
||||
|
||||
|
||||
{isExpandedMode && _renderExpansionButton()}
|
||||
{isExpandedMode && _renderDeleteButton()}
|
||||
</View>
|
||||
|
||||
)
|
||||
);
|
||||
|
||||
//render empty list placeholder
|
||||
const _renderEmptyContent = () => {
|
||||
return (
|
||||
<>
|
||||
<Text style={styles.emptyText}>{intl.formatMessage({ id: 'uploads_modal.label_no_images' })}</Text>
|
||||
<Text style={styles.emptyText}>
|
||||
{intl.formatMessage({ id: 'uploads_modal.label_no_images' })}
|
||||
</Text>
|
||||
</>
|
||||
);
|
||||
};
|
||||
@ -259,82 +256,74 @@ const UploadsGalleryContent = ({
|
||||
Animated.timing(animatedHeightRef.current, {
|
||||
toValue: isExpandedMode ? COMPACT_HEIGHT : EXPANDED_HEIGHT,
|
||||
duration: 300,
|
||||
easing: Easing.inOut(Easing.cubic)
|
||||
easing: Easing.inOut(Easing.cubic),
|
||||
}).start(() => {
|
||||
setIsExpandedMode(!isExpandedMode)
|
||||
})
|
||||
setIsExpandedMode(!isExpandedMode);
|
||||
});
|
||||
}}
|
||||
/>
|
||||
)
|
||||
|
||||
);
|
||||
|
||||
const _renderDeleteButton = () => {
|
||||
if (deleteIds.length > 0) {
|
||||
return (
|
||||
isExpandedMode ? (
|
||||
|
||||
|
||||
return isExpandedMode ? (
|
||||
<IconButton
|
||||
style={{
|
||||
...styles.pillBtnContainer,
|
||||
backgroundColor: EStyleSheet.value('$primaryRed'),
|
||||
}}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name="delete-outline"
|
||||
color={EStyleSheet.value(deleteIds.length > 0 ? '$primaryBlack' : '$primaryBlack')}
|
||||
size={32}
|
||||
onPress={_onDeletePress}
|
||||
isLoading={isDeleting}
|
||||
/>
|
||||
) : (
|
||||
<AnimatedView
|
||||
animation={deleteIds.length > 0 ? 'slideInRight' : 'slideOutRight'}
|
||||
duration={300}
|
||||
style={styles.deleteButtonContainer}
|
||||
>
|
||||
<IconButton
|
||||
style={{
|
||||
...styles.pillBtnContainer,
|
||||
backgroundColor: EStyleSheet.value('$primaryRed')
|
||||
}}
|
||||
style={styles.deleteButton}
|
||||
color={EStyleSheet.value('$primaryBlack')}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name={'delete-outline'}
|
||||
color={EStyleSheet.value(deleteIds.length > 0 ? '$primaryBlack' : '$primaryBlack')}
|
||||
size={32}
|
||||
name="delete-outline"
|
||||
disabled={isDeleting}
|
||||
size={28}
|
||||
onPress={_onDeletePress}
|
||||
isLoading={isDeleting}
|
||||
/>
|
||||
|
||||
|
||||
) : (
|
||||
<AnimatedView
|
||||
animation={deleteIds.length > 0 ? 'slideInRight' : 'slideOutRight'
|
||||
}
|
||||
duration={300}
|
||||
style={styles.deleteButtonContainer}
|
||||
>
|
||||
<IconButton
|
||||
style={styles.deleteButton}
|
||||
color={EStyleSheet.value('$primaryBlack')}
|
||||
iconType="MaterialCommunityIcons"
|
||||
name={'delete-outline'}
|
||||
disabled={isDeleting}
|
||||
size={28}
|
||||
onPress={_onDeletePress}
|
||||
isLoading={isDeleting} />
|
||||
</AnimatedView >
|
||||
)
|
||||
)
|
||||
</AnimatedView>
|
||||
);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
};
|
||||
|
||||
return (
|
||||
<Animated.View style={{ ...styles.container, height: animatedHeightRef.current }}>
|
||||
<FlatList
|
||||
key={isExpandedMode ? 'vertical_grid' : 'horizontal_list'}
|
||||
data={mediaUploads.slice(0, !isExpandedMode ? MAX_HORIZONTAL_THUMBS:undefined)}
|
||||
data={mediaUploads.slice(0, !isExpandedMode ? MAX_HORIZONTAL_THUMBS : undefined)}
|
||||
keyExtractor={(item) => `item_${item.url}`}
|
||||
renderItem={_renderItem}
|
||||
style={{ flex: 1 }}
|
||||
contentContainerStyle={isExpandedMode ? styles.gridContentContainer : styles.listContentContainer}
|
||||
contentContainerStyle={
|
||||
isExpandedMode ? styles.gridContentContainer : styles.listContentContainer
|
||||
}
|
||||
ListHeaderComponent={_renderHeaderContent}
|
||||
ListEmptyComponent={_renderEmptyContent}
|
||||
ListFooterComponent={!isExpandedMode && mediaUploads.length > 0 && _renderExpansionButton}
|
||||
extraData={deleteIds}
|
||||
horizontal={!isExpandedMode}
|
||||
numColumns={isExpandedMode ? 2 : 1}
|
||||
keyboardShouldPersistTaps='always'
|
||||
keyboardShouldPersistTaps="always"
|
||||
/>
|
||||
|
||||
{!isExpandedMode && _renderDeleteButton()}
|
||||
|
||||
</Animated.View>
|
||||
)
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
export default UploadsGalleryContent
|
||||
export default UploadsGalleryContent;
|
||||
|
@ -1,17 +1,15 @@
|
||||
import React, { forwardRef, useEffect, useImperativeHandle, useRef, useState } from 'react';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { Alert } from 'react-native';
|
||||
import ImagePicker, { Image } from 'react-native-image-crop-picker';
|
||||
import bugsnapInstance from '../../../config/bugsnag';
|
||||
import { addImage, deleteImage, getImages, uploadImage } from '../../../providers/ecency/ecency';
|
||||
import { getImages } from '../../../providers/ecency/ecency';
|
||||
import UploadsGalleryContent from '../children/uploadsGalleryContent';
|
||||
import ImagePicker from 'react-native-image-crop-picker';
|
||||
import { signImage } from '../../../providers/hive/dhive';
|
||||
|
||||
import { useAppDispatch, useAppSelector } from '../../../hooks';
|
||||
import { delay, extractFilenameFromPath } from '../../../utils/editor';
|
||||
import { toastNotification } from '../../../redux/actions/uiAction';
|
||||
import showLoginAlert from '../../../utils/showLoginAlert';
|
||||
|
||||
|
||||
import { useMediaQuery, useMediaUploadMutation } from '../../../providers/queries';
|
||||
|
||||
export interface UploadsGalleryModalRef {
|
||||
showModal: () => void;
|
||||
@ -20,257 +18,268 @@ export interface UploadsGalleryModalRef {
|
||||
export enum MediaInsertStatus {
|
||||
UPLOADING = 'UPLOADING',
|
||||
READY = 'READY',
|
||||
FAILED = 'FAILED'
|
||||
FAILED = 'FAILED',
|
||||
}
|
||||
|
||||
export interface MediaInsertData {
|
||||
url: string,
|
||||
filename?: string,
|
||||
text: string,
|
||||
status: MediaInsertStatus
|
||||
url: string;
|
||||
filename?: string;
|
||||
text: string;
|
||||
status: MediaInsertStatus;
|
||||
}
|
||||
|
||||
interface UploadsGalleryModalProps {
|
||||
insertedMediaUrls: string[],
|
||||
insertedMediaUrls: string[];
|
||||
paramFiles: any[];
|
||||
username: string;
|
||||
isEditing: boolean;
|
||||
isPreviewActive: boolean;
|
||||
hideToolbarExtension: () => void;
|
||||
handleMediaInsert: (data: Array<MediaInsertData>) => void;
|
||||
setIsUploading: (status: boolean) => void;
|
||||
}
|
||||
|
||||
export const UploadsGalleryModal = forwardRef(({
|
||||
insertedMediaUrls,
|
||||
paramFiles,
|
||||
username,
|
||||
isEditing,
|
||||
isPreviewActive,
|
||||
handleMediaInsert,
|
||||
setIsUploading
|
||||
}: UploadsGalleryModalProps, ref) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
export const UploadsGalleryModal = forwardRef(
|
||||
(
|
||||
{
|
||||
insertedMediaUrls,
|
||||
paramFiles,
|
||||
username,
|
||||
isEditing,
|
||||
isPreviewActive,
|
||||
hideToolbarExtension,
|
||||
handleMediaInsert,
|
||||
setIsUploading,
|
||||
}: UploadsGalleryModalProps,
|
||||
ref,
|
||||
) => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const pendingInserts = useRef<MediaInsertData[]>([]);
|
||||
const mediaQuery = useMediaQuery();
|
||||
const mediaUploadMutation = useMediaUploadMutation();
|
||||
|
||||
const [mediaUploads, setMediaUploads] = useState([]);
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [isAddingToUploads, setIsAddingToUploads] = useState(false);
|
||||
const pendingInserts = useRef<MediaInsertData[]>([]);
|
||||
|
||||
const [mediaUploads, setMediaUploads] = useState([]);
|
||||
const [showModal, setShowModal] = useState(false);
|
||||
const [isAddingToUploads, setIsAddingToUploads] = useState(false);
|
||||
|
||||
const isLoggedIn = useAppSelector(state => state.application.isLoggedIn);
|
||||
const pinCode = useAppSelector(state => state.application.pin);
|
||||
const currentAccount = useAppSelector(state => state.account.currentAccount);
|
||||
const isLoggedIn = useAppSelector((state) => state.application.isLoggedIn);
|
||||
const pinCode = useAppSelector((state) => state.application.pin);
|
||||
const currentAccount = useAppSelector((state) => state.account.currentAccount);
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
toggleModal: (value: boolean) => {
|
||||
if (!isLoggedIn) {
|
||||
showLoginAlert({ intl });
|
||||
return;
|
||||
}
|
||||
|
||||
useImperativeHandle(ref, () => ({
|
||||
toggleModal: (value:boolean) => {
|
||||
if (!isLoggedIn) {
|
||||
showLoginAlert({ intl });
|
||||
return;
|
||||
}
|
||||
if (value === showModal) {
|
||||
return;
|
||||
}
|
||||
|
||||
if(value === showModal){
|
||||
return;
|
||||
}
|
||||
|
||||
if (value) {
|
||||
_getMediaUploads();
|
||||
}
|
||||
setShowModal(value);
|
||||
},
|
||||
}));
|
||||
if (value) {
|
||||
_getMediaUploads();
|
||||
}
|
||||
setShowModal(value);
|
||||
},
|
||||
}));
|
||||
|
||||
useEffect(() => {
|
||||
if (paramFiles) {
|
||||
console.log('files : ', paramFiles);
|
||||
useEffect(() => {
|
||||
if (paramFiles) {
|
||||
console.log('files : ', paramFiles);
|
||||
|
||||
//delay is a workaround to let editor ready before initiating uploads on mount
|
||||
delay(500).then(() => {
|
||||
const _mediaItems = paramFiles.map((el) => {
|
||||
if (el.filePath && el.fileName) {
|
||||
const _media = {
|
||||
path: el.filePath,
|
||||
mime: el.mimeType,
|
||||
filename: el.fileName,
|
||||
};
|
||||
//delay is a workaround to let editor ready before initiating uploads on mount
|
||||
delay(500).then(() => {
|
||||
const _mediaItems = paramFiles.map((el) => {
|
||||
if (el.filePath && el.fileName) {
|
||||
const _media = {
|
||||
path: el.filePath,
|
||||
mime: el.mimeType,
|
||||
filename: el.fileName,
|
||||
};
|
||||
|
||||
return _media;
|
||||
}
|
||||
return null
|
||||
return _media;
|
||||
}
|
||||
return null;
|
||||
});
|
||||
|
||||
_handleMediaOnSelected(_mediaItems, true);
|
||||
});
|
||||
|
||||
_handleMediaOnSelected(_mediaItems, true)
|
||||
})
|
||||
}
|
||||
|
||||
}, [paramFiles])
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
_getMediaUploads();
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isEditing && pendingInserts.current.length) {
|
||||
handleMediaInsert(pendingInserts.current);
|
||||
pendingInserts.current = []
|
||||
}
|
||||
}, [isEditing])
|
||||
|
||||
|
||||
const _handleOpenImagePicker = (addToUploads?: boolean) => {
|
||||
ImagePicker.openPicker({
|
||||
includeBase64: true,
|
||||
multiple: true,
|
||||
mediaType: 'photo',
|
||||
smartAlbums: ['UserLibrary', 'Favorites', 'PhotoStream', 'Panoramas', 'Bursts'],
|
||||
})
|
||||
.then((images) => {
|
||||
if (images && !Array.isArray(images)) {
|
||||
images = [images];
|
||||
}
|
||||
_handleMediaOnSelected(images, !addToUploads);
|
||||
|
||||
})
|
||||
.catch((e) => {
|
||||
_handleMediaOnSelectFailure(e);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
const _handleOpenCamera = () => {
|
||||
ImagePicker.openCamera({
|
||||
includeBase64: true,
|
||||
mediaType: 'photo',
|
||||
})
|
||||
.then((image) => {
|
||||
_handleMediaOnSelected([image], true);
|
||||
})
|
||||
.catch((e) => {
|
||||
_handleMediaOnSelectFailure(e);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
const _handleMediaOnSelected = async (media: any[], shouldInsert: boolean) => {
|
||||
|
||||
try {
|
||||
if (!media || media.length == 0) {
|
||||
throw new Error("New media items returned")
|
||||
}
|
||||
}, [paramFiles]);
|
||||
|
||||
if (shouldInsert) {
|
||||
setShowModal(false);
|
||||
media.forEach((element, index) => {
|
||||
if (element) {
|
||||
media[index].filename = element.filename || extractFilenameFromPath({ path: element.path, mimeType: element.mime });
|
||||
handleMediaInsert([{
|
||||
filename: element.filename,
|
||||
url: '',
|
||||
text: '',
|
||||
status: MediaInsertStatus.UPLOADING
|
||||
}])
|
||||
useEffect(() => {
|
||||
if (!isEditing && pendingInserts.current.length) {
|
||||
handleMediaInsert(pendingInserts.current);
|
||||
pendingInserts.current = [];
|
||||
}
|
||||
}, [isEditing]);
|
||||
|
||||
const _handleOpenImagePicker = (addToUploads?: boolean) => {
|
||||
ImagePicker.openPicker({
|
||||
includeBase64: true,
|
||||
multiple: true,
|
||||
mediaType: 'photo',
|
||||
smartAlbums: ['UserLibrary', 'Favorites', 'PhotoStream', 'Panoramas', 'Bursts'],
|
||||
})
|
||||
.then((images) => {
|
||||
if (images && !Array.isArray(images)) {
|
||||
images = [images];
|
||||
}
|
||||
_handleMediaOnSelected(images, !addToUploads);
|
||||
})
|
||||
}
|
||||
.catch((e) => {
|
||||
_handleMediaOnSelectFailure(e);
|
||||
});
|
||||
};
|
||||
|
||||
for (let index = 0; index < media.length; index++) {
|
||||
const element = media[index];
|
||||
if (element) {
|
||||
await _uploadImage(element, { shouldInsert });
|
||||
const _handleOpenCamera = () => {
|
||||
ImagePicker.openCamera({
|
||||
includeBase64: true,
|
||||
mediaType: 'photo',
|
||||
})
|
||||
.then((image) => {
|
||||
_handleMediaOnSelected([image], true);
|
||||
})
|
||||
.catch((e) => {
|
||||
_handleMediaOnSelectFailure(e);
|
||||
});
|
||||
};
|
||||
|
||||
const _handleMediaOnSelected = async (media: Image[], shouldInsert: boolean) => {
|
||||
try {
|
||||
if (!media || media.length == 0) {
|
||||
throw new Error('New media items returned');
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error) {
|
||||
console.log("Failed to upload image", error);
|
||||
|
||||
bugsnapInstance.notify(error);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
const _uploadImage = async (media, { shouldInsert } = { shouldInsert: false }) => {
|
||||
|
||||
if (!isLoggedIn) return;
|
||||
try {
|
||||
setIsLoading(true);
|
||||
if (setIsUploading) {
|
||||
setIsUploading(true)
|
||||
}
|
||||
if (!shouldInsert) {
|
||||
setIsAddingToUploads(true);
|
||||
}
|
||||
|
||||
let sign = await signImage(media, currentAccount, pinCode);
|
||||
|
||||
let MAX_RETRY = 2;
|
||||
|
||||
let res: any = null;
|
||||
|
||||
for (var i = 0; i < MAX_RETRY; i++) {
|
||||
res = await uploadImage(media, currentAccount.name, sign);
|
||||
if (res && res.data) {
|
||||
break;
|
||||
if (shouldInsert) {
|
||||
setShowModal(false);
|
||||
hideToolbarExtension();
|
||||
media.forEach((element, index) => {
|
||||
if (element) {
|
||||
media[index].filename =
|
||||
element.filename ||
|
||||
extractFilenameFromPath({ path: element.path, mimeType: element.mime });
|
||||
handleMediaInsert([
|
||||
{
|
||||
filename: element.filename,
|
||||
url: '',
|
||||
text: '',
|
||||
status: MediaInsertStatus.UPLOADING,
|
||||
},
|
||||
]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (res.data && res.data.url) {
|
||||
for (let index = 0; index < media.length; index++) {
|
||||
const element = media[index];
|
||||
if (element) {
|
||||
await _uploadImage(element, { shouldInsert });
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
console.log('Failed to upload image', error);
|
||||
|
||||
bugsnapInstance.notify(error);
|
||||
}
|
||||
};
|
||||
|
||||
const _uploadImage = async (media, { shouldInsert } = { shouldInsert: false }) => {
|
||||
if (!isLoggedIn) return;
|
||||
try {
|
||||
if (setIsUploading) {
|
||||
setIsUploading(true);
|
||||
}
|
||||
if (!shouldInsert) {
|
||||
setIsAddingToUploads(true);
|
||||
}
|
||||
|
||||
await mediaUploadMutation.mutateAsync({
|
||||
media,
|
||||
addToUploads: !shouldInsert
|
||||
}, {
|
||||
onSuccess: (data) => {
|
||||
console.log('upload successfully', data, media, shouldInsert)
|
||||
if (data && data.url && shouldInsert) {
|
||||
_handleMediaInsertion({
|
||||
filename: media.filename,
|
||||
url: data.url,
|
||||
text: '',
|
||||
status: MediaInsertStatus.READY,
|
||||
});
|
||||
}
|
||||
},
|
||||
onSettled: () => {
|
||||
if (setIsUploading) {
|
||||
setIsUploading(false);
|
||||
}
|
||||
setIsAddingToUploads(false);
|
||||
},
|
||||
onError: (err) => { throw err },
|
||||
})
|
||||
|
||||
} catch (error) {
|
||||
console.log('error while uploading image : ', error);
|
||||
|
||||
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(),
|
||||
);
|
||||
}
|
||||
|
||||
if (shouldInsert) {
|
||||
_handleMediaInsertion({
|
||||
filename: media.filename,
|
||||
url: res.data.url,
|
||||
url: '',
|
||||
text: '',
|
||||
status: MediaInsertStatus.READY
|
||||
})
|
||||
} else {
|
||||
_addUploadedImageToGallery(res.data.url)
|
||||
status: MediaInsertStatus.FAILED,
|
||||
});
|
||||
}
|
||||
|
||||
setIsLoading(false);
|
||||
if (setIsUploading) {
|
||||
setIsUploading(false)
|
||||
}
|
||||
|
||||
|
||||
} else if (res.error) {
|
||||
throw res.error
|
||||
}
|
||||
};
|
||||
|
||||
} catch (error) {
|
||||
console.log('error while uploading image : ', error);
|
||||
|
||||
if (error.toString().includes('code 413')) {
|
||||
const _handleMediaOnSelectFailure = (error) => {
|
||||
if (error.code === 'E_PERMISSION_MISSING') {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
id: 'alert.permission_denied',
|
||||
}),
|
||||
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',
|
||||
id: 'alert.permission_text',
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
@ -278,141 +287,64 @@ export const UploadsGalleryModal = forwardRef(({
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
}),
|
||||
error.message || error.toString(),
|
||||
error.message || JSON.stringify(error),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if (shouldInsert) {
|
||||
_handleMediaInsertion({
|
||||
filename: media.filename,
|
||||
url: '',
|
||||
const _handleMediaInsertion = (data: MediaInsertData) => {
|
||||
if (isEditing) {
|
||||
pendingInserts.current.push(data);
|
||||
} else if (handleMediaInsert) {
|
||||
handleMediaInsert([data]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
//fetch images from server
|
||||
const _getMediaUploads = async () => {
|
||||
try {
|
||||
if (username) {
|
||||
console.log('getting images for: ' + username);
|
||||
const images = await getImages();
|
||||
console.log('images received', images);
|
||||
setMediaUploads(images || []);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn('Failed to get images');
|
||||
}
|
||||
setIsAddingToUploads(false);
|
||||
};
|
||||
|
||||
//inserts media items in post body
|
||||
const _insertMedia = async (map: Map<number, boolean>) => {
|
||||
const data: MediaInsertData[] = [];
|
||||
for (const index of map.keys()) {
|
||||
console.log(index);
|
||||
const item = mediaUploads[index];
|
||||
data.push({
|
||||
url: item.url,
|
||||
text: '',
|
||||
status: MediaInsertStatus.FAILED
|
||||
})
|
||||
status: MediaInsertStatus.READY,
|
||||
});
|
||||
}
|
||||
handleMediaInsert(data);
|
||||
};
|
||||
|
||||
setIsLoading(false);
|
||||
if (setIsUploading) {
|
||||
setIsUploading(false)
|
||||
}
|
||||
setIsAddingToUploads(false);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
|
||||
const _handleMediaOnSelectFailure = (error) => {
|
||||
|
||||
if (error.code === 'E_PERMISSION_MISSING') {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.permission_denied',
|
||||
}),
|
||||
intl.formatMessage({
|
||||
id: 'alert.permission_text',
|
||||
}),
|
||||
);
|
||||
} else {
|
||||
Alert.alert(
|
||||
intl.formatMessage({
|
||||
id: 'alert.fail',
|
||||
}),
|
||||
error.message || JSON.stringify(error),
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
const _handleMediaInsertion = (data: MediaInsertData) => {
|
||||
if (isEditing) {
|
||||
pendingInserts.current.push(data);
|
||||
} else if (handleMediaInsert) {
|
||||
handleMediaInsert([data]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//save image to user gallery
|
||||
const _addUploadedImageToGallery = async (url: string) => {
|
||||
try {
|
||||
console.log("adding image to gallery", username, url)
|
||||
setIsLoading(true);
|
||||
await addImage(url);
|
||||
await _getMediaUploads();
|
||||
setIsLoading(false);
|
||||
} catch (err) {
|
||||
console.warn("Failed to add image to gallery, could possibly a duplicate image", err)
|
||||
setIsLoading(false);
|
||||
setIsAddingToUploads(false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
// remove image data from user's gallery
|
||||
const _deleteMedia = async (id: string) => {
|
||||
try {
|
||||
await deleteImage(id)
|
||||
return true
|
||||
} catch (err) {
|
||||
console.warn("failed to remove image from gallery", err)
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'uploads_modal.delete_failed' })))
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//fetch images from server
|
||||
const _getMediaUploads = async () => {
|
||||
try {
|
||||
if (username) {
|
||||
setIsLoading(true);
|
||||
console.log("getting images for: " + username)
|
||||
const images = await getImages()
|
||||
console.log("images received", images)
|
||||
setMediaUploads(images || []);
|
||||
setIsLoading(false);
|
||||
}
|
||||
} catch (err) {
|
||||
console.warn("Failed to get images")
|
||||
setIsLoading(false);
|
||||
}
|
||||
setIsAddingToUploads(false);
|
||||
}
|
||||
|
||||
//inserts media items in post body
|
||||
const _insertMedia = async (map: Map<number, boolean>) => {
|
||||
|
||||
const data: MediaInsertData[] = []
|
||||
for (const index of map.keys()) {
|
||||
console.log(index)
|
||||
const item = mediaUploads[index]
|
||||
data.push({
|
||||
url: item.url,
|
||||
text: "",
|
||||
status: MediaInsertStatus.READY
|
||||
})
|
||||
|
||||
}
|
||||
handleMediaInsert(data)
|
||||
}
|
||||
|
||||
return (
|
||||
!isPreviewActive && showModal && (
|
||||
<UploadsGalleryContent
|
||||
insertedMediaUrls={insertedMediaUrls}
|
||||
mediaUploads={mediaUploads}
|
||||
isLoading={isLoading}
|
||||
isAddingToUploads={isAddingToUploads}
|
||||
getMediaUploads={_getMediaUploads}
|
||||
deleteMedia={_deleteMedia}
|
||||
insertMedia={_insertMedia}
|
||||
handleOpenCamera={_handleOpenCamera}
|
||||
handleOpenGallery={_handleOpenImagePicker}
|
||||
|
||||
/>
|
||||
)
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
return (
|
||||
!isPreviewActive &&
|
||||
showModal && (
|
||||
<UploadsGalleryContent
|
||||
insertedMediaUrls={insertedMediaUrls}
|
||||
mediaUploads={mediaQuery.data.slice()}
|
||||
isAddingToUploads={isAddingToUploads}
|
||||
getMediaUploads={_getMediaUploads}
|
||||
insertMedia={_insertMedia}
|
||||
handleOpenCamera={_handleOpenCamera}
|
||||
handleOpenGallery={_handleOpenImagePicker}
|
||||
/>
|
||||
)
|
||||
);
|
||||
},
|
||||
);
|
||||
|
@ -15,6 +15,7 @@ import {
|
||||
import {
|
||||
CommentHistoryItem,
|
||||
LatestMarketPrices,
|
||||
MediaItem,
|
||||
NotificationFilters,
|
||||
ReceivedVestingShare,
|
||||
Referral,
|
||||
@ -672,7 +673,7 @@ export const addImage = async (url: string) => {
|
||||
try {
|
||||
const data = { url };
|
||||
const response = await ecencyApi.post('/private-api/images-add', data);
|
||||
return response.data;
|
||||
return response.data as MediaItem[];
|
||||
} catch (error) {
|
||||
console.warn('Failed to add image', error);
|
||||
bugsnagInstance.notify(error);
|
||||
@ -708,10 +709,10 @@ export const uploadImage = async (media, username, sign, uploadProgress = null)
|
||||
if (!res || !res.data) {
|
||||
throw new Error('Returning response missing media data');
|
||||
}
|
||||
return res;
|
||||
return res.data;
|
||||
} catch (error) {
|
||||
console.warn('Image upload failed', error);
|
||||
return { error };
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -7,6 +7,13 @@ export interface ReceivedVestingShare {
|
||||
timestamp: string;
|
||||
}
|
||||
|
||||
export interface MediaItem {
|
||||
_id: string;
|
||||
url: string;
|
||||
created: string;
|
||||
timestamp: number;
|
||||
}
|
||||
|
||||
export interface Snippet {
|
||||
id: string;
|
||||
title: string;
|
||||
@ -59,20 +66,20 @@ export interface CommentHistoryItem {
|
||||
}
|
||||
|
||||
export enum ScheduledPostStatus {
|
||||
PENDING = 1,
|
||||
POSTPONED = 2,
|
||||
PUBLISHED = 3,
|
||||
ERROR = 4,
|
||||
PENDING = 1,
|
||||
POSTPONED = 2,
|
||||
PUBLISHED = 3,
|
||||
ERROR = 4,
|
||||
}
|
||||
|
||||
export enum NotificationFilters {
|
||||
ACTIVITIES = "activities",
|
||||
RVOTES = "rvotes",
|
||||
MENTIONS = "mentions",
|
||||
FOLLOWS = "follows",
|
||||
REPLIES = "replies",
|
||||
REBLOGS = "reblogs",
|
||||
TRANFERS = "transfers",
|
||||
DELEGATIONS = "delegations",
|
||||
FAVOURITES = "nfavorites"
|
||||
ACTIVITIES = "activities",
|
||||
RVOTES = "rvotes",
|
||||
MENTIONS = "mentions",
|
||||
FOLLOWS = "follows",
|
||||
REPLIES = "replies",
|
||||
REBLOGS = "reblogs",
|
||||
TRANFERS = "transfers",
|
||||
DELEGATIONS = "delegations",
|
||||
FAVOURITES = "nfavorites"
|
||||
}
|
||||
|
@ -1,90 +1,212 @@
|
||||
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
|
||||
import { useIntl } from 'react-intl';
|
||||
import { useAppDispatch } from '../../hooks';
|
||||
import { Image } from 'react-native-image-crop-picker';
|
||||
import { useAppDispatch, useAppSelector } from '../../hooks';
|
||||
import { toastNotification } from '../../redux/actions/uiAction';
|
||||
import { addFragment, deleteFragment, getFragments, updateFragment } from '../ecency/ecency';
|
||||
import { Snippet } from '../ecency/ecency.types';
|
||||
import {
|
||||
addFragment,
|
||||
addImage,
|
||||
deleteFragment,
|
||||
deleteImage,
|
||||
getFragments,
|
||||
getImages,
|
||||
updateFragment,
|
||||
uploadImage,
|
||||
} from '../ecency/ecency';
|
||||
import { MediaItem, Snippet } from '../ecency/ecency.types';
|
||||
import { signImage } from '../hive/dhive';
|
||||
import QUERIES from './queryKeys';
|
||||
|
||||
interface SnippetMutationVars {
|
||||
id: string | null;
|
||||
title: string;
|
||||
body: string;
|
||||
id: string | null;
|
||||
title: string;
|
||||
body: string;
|
||||
}
|
||||
|
||||
export const useSnippetsQuery = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
return useQuery<Snippet[]>([QUERIES.SNIPPETS.GET], getFragments, {
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
interface MediaUploadVars {
|
||||
media: Image;
|
||||
addToUploads: boolean;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/** GET QUERIES **/
|
||||
|
||||
export const useMediaQuery = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
return useQuery<MediaItem[]>([QUERIES.MEDIA.GET], getImages, {
|
||||
initialData: [],
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
export const useSnippetsQuery = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
return useQuery<Snippet[]>([QUERIES.SNIPPETS.GET], getFragments, {
|
||||
initialData: [],
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
/** ADD UPDATE MUTATIONS **/
|
||||
|
||||
|
||||
export const useAddToUploadsMutation = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<any[], Error, string>(addImage, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
queryClient.setQueryData([QUERIES.MEDIA.GET], data);
|
||||
},
|
||||
onError: (error) => {
|
||||
if (error.toString().includes('code 409')) {
|
||||
//means image ware already preset, refresh to get updated order
|
||||
queryClient.invalidateQueries([QUERIES.MEDIA.GET]);
|
||||
} else {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
export const useMediaUploadMutation = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
const addToUploadsMutation = useAddToUploadsMutation();
|
||||
|
||||
const currentAccount = useAppSelector(state => state.account.currentAccount);
|
||||
const pinCode = useAppSelector(state => state.application.pin);
|
||||
|
||||
return useMutation<Image, undefined, MediaUploadVars>(
|
||||
async ({ media }) => {
|
||||
console.log('uploading media', media);
|
||||
let sign = await signImage(media, currentAccount, pinCode);
|
||||
return await uploadImage(media, currentAccount.name, sign);
|
||||
},
|
||||
{
|
||||
retry: 3,
|
||||
onSuccess: (response, { addToUploads }) => {
|
||||
if (addToUploads && response && response.url) {
|
||||
console.log('adding image to gallery', response.url);
|
||||
addToUploadsMutation.mutate(response.url);
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
export const useSnippetsMutation = () => {
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const queryClient = useQueryClient();
|
||||
const intl = useIntl();
|
||||
const dispatch = useAppDispatch();
|
||||
const queryClient = useQueryClient();
|
||||
|
||||
return useMutation<Snippet[], undefined, SnippetMutationVars>(
|
||||
async (vars) => {
|
||||
console.log('going to add/update snippet', vars);
|
||||
if (vars.id) {
|
||||
const response = await updateFragment(vars.id, vars.title, vars.body);
|
||||
return response;
|
||||
} else {
|
||||
const response = await addFragment(vars.title, vars.body);
|
||||
return response;
|
||||
}
|
||||
},
|
||||
{
|
||||
onMutate: (vars) => {
|
||||
console.log('mutate snippets for add/update', vars);
|
||||
return useMutation<Snippet[], undefined, SnippetMutationVars>(
|
||||
async (vars) => {
|
||||
console.log('going to add/update snippet', vars);
|
||||
if (vars.id) {
|
||||
const response = await updateFragment(vars.id, vars.title, vars.body);
|
||||
return response;
|
||||
} else {
|
||||
const response = await addFragment(vars.title, vars.body);
|
||||
return response;
|
||||
}
|
||||
},
|
||||
{
|
||||
onMutate: (vars) => {
|
||||
console.log('mutate snippets for add/update', vars);
|
||||
|
||||
const _newItem = {
|
||||
id: vars.id,
|
||||
title: vars.title,
|
||||
body: vars.body,
|
||||
created: new Date().toDateString(),
|
||||
modified: new Date().toDateString(),
|
||||
} as Snippet;
|
||||
const _newItem = {
|
||||
id: vars.id,
|
||||
title: vars.title,
|
||||
body: vars.body,
|
||||
created: new Date().toDateString(),
|
||||
modified: new Date().toDateString(),
|
||||
} as Snippet;
|
||||
|
||||
const data = queryClient.getQueryData<Snippet[]>([QUERIES.SNIPPETS.GET]);
|
||||
const data = queryClient.getQueryData<Snippet[]>([QUERIES.SNIPPETS.GET]);
|
||||
|
||||
let _newData: Snippet[] = data ? [...data] : [];
|
||||
if (vars.id) {
|
||||
const snipIndex = _newData.findIndex((item) => vars.id === item.id);
|
||||
_newData[snipIndex] = _newItem;
|
||||
} else {
|
||||
_newData = [_newItem, ..._newData];
|
||||
}
|
||||
let _newData: Snippet[] = data ? [...data] : [];
|
||||
if (vars.id) {
|
||||
const snipIndex = _newData.findIndex((item) => vars.id === item.id);
|
||||
_newData[snipIndex] = _newItem;
|
||||
} else {
|
||||
_newData = [_newItem, ..._newData];
|
||||
}
|
||||
|
||||
queryClient.setQueryData([QUERIES.SNIPPETS.GET], _newData);
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
console.log('added/updated snippet', data);
|
||||
queryClient.invalidateQueries([QUERIES.SNIPPETS.GET]);
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'snippets.message_failed' })));
|
||||
},
|
||||
},
|
||||
);
|
||||
queryClient.setQueryData([QUERIES.SNIPPETS.GET], _newData);
|
||||
},
|
||||
onSuccess: (data) => {
|
||||
console.log('added/updated snippet', data);
|
||||
queryClient.invalidateQueries([QUERIES.SNIPPETS.GET]);
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'snippets.message_failed' })));
|
||||
},
|
||||
},
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** DELETE MUTATIONS **/
|
||||
|
||||
export const useMediaDeleteMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation<string[], undefined, string[]>(async (deleteIds) => {
|
||||
for (const i in deleteIds) {
|
||||
await deleteImage(deleteIds[i]);
|
||||
}
|
||||
return deleteIds;
|
||||
}, {
|
||||
retry: 3,
|
||||
onSuccess: (deleteIds) => {
|
||||
console.log('Success media deletion delete', deleteIds);
|
||||
const data: MediaItem[] | undefined = queryClient.getQueryData([QUERIES.MEDIA.GET]);
|
||||
if (data) {
|
||||
const _newData = data.filter((item) => (!deleteIds.includes(item._id)))
|
||||
queryClient.setQueryData([QUERIES.MEDIA.GET], _newData);
|
||||
}
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'uploads_modal.delete_failed' })));
|
||||
queryClient.invalidateQueries([QUERIES.MEDIA.GET]);
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
export const useSnippetDeleteMutation = () => {
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation<Snippet[], undefined, string>(deleteFragment, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log('Success scheduled post delete', data);
|
||||
queryClient.setQueryData([QUERIES.SNIPPETS.GET], data);
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
const queryClient = useQueryClient();
|
||||
const dispatch = useAppDispatch();
|
||||
const intl = useIntl();
|
||||
return useMutation<Snippet[], undefined, string>(deleteFragment, {
|
||||
retry: 3,
|
||||
onSuccess: (data) => {
|
||||
console.log('Success scheduled post delete', data);
|
||||
queryClient.setQueryData([QUERIES.SNIPPETS.GET], data);
|
||||
},
|
||||
onError: () => {
|
||||
dispatch(toastNotification(intl.formatMessage({ id: 'alert.fail' })));
|
||||
},
|
||||
});
|
||||
};
|
||||
|
@ -5,12 +5,15 @@ const QUERIES = {
|
||||
SCHEDULES: {
|
||||
GET: 'QUERY_GET_SCHEDULES',
|
||||
},
|
||||
NOTIFICATIONS:{
|
||||
GET: 'QERUY_GET_NOTIFICATIONS'
|
||||
NOTIFICATIONS: {
|
||||
GET: 'QERUY_GET_NOTIFICATIONS',
|
||||
},
|
||||
SNIPPETS: {
|
||||
GET: 'QUERY_GET_SNIPPETS',
|
||||
}
|
||||
},
|
||||
MEDIA: {
|
||||
GET: 'QUERY_GET_UPLOADS',
|
||||
},
|
||||
};
|
||||
|
||||
export default QUERIES;
|
||||
|
Loading…
Reference in New Issue
Block a user