mirror of
https://github.com/balzack/databag.git
synced 2025-02-11 19:19:16 +00:00
adding video and image to add topic carousel
This commit is contained in:
parent
b6b18aaaaa
commit
769ce6805f
@ -246,6 +246,11 @@ PODS:
|
||||
- ReactCommon/turbomodule/core
|
||||
- react-native-sqlite-storage (6.0.1):
|
||||
- React-Core
|
||||
- react-native-video (5.2.1):
|
||||
- React-Core
|
||||
- react-native-video/Video (= 5.2.1)
|
||||
- react-native-video/Video (5.2.1):
|
||||
- React-Core
|
||||
- React-perflogger (0.69.5)
|
||||
- React-RCTActionSheet (0.69.5):
|
||||
- React-Core/RCTActionSheetHeaders (= 0.69.5)
|
||||
@ -384,6 +389,7 @@ DEPENDENCIES:
|
||||
- React-logger (from `../node_modules/react-native/ReactCommon/logger`)
|
||||
- react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`)
|
||||
- react-native-sqlite-storage (from `../node_modules/react-native-sqlite-storage`)
|
||||
- react-native-video (from `../node_modules/react-native-video`)
|
||||
- React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`)
|
||||
- React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`)
|
||||
- React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`)
|
||||
@ -465,6 +471,8 @@ EXTERNAL SOURCES:
|
||||
:path: "../node_modules/react-native-safe-area-context"
|
||||
react-native-sqlite-storage:
|
||||
:path: "../node_modules/react-native-sqlite-storage"
|
||||
react-native-video:
|
||||
:path: "../node_modules/react-native-video"
|
||||
React-perflogger:
|
||||
:path: "../node_modules/react-native/ReactCommon/reactperflogger"
|
||||
React-RCTActionSheet:
|
||||
@ -529,6 +537,7 @@ SPEC CHECKSUMS:
|
||||
React-logger: 15c734997c06fe9c9b88e528fb7757601e7a56df
|
||||
react-native-safe-area-context: b456e1c40ec86f5593d58b275bd0e9603169daca
|
||||
react-native-sqlite-storage: f6d515e1c446d1e6d026aa5352908a25d4de3261
|
||||
react-native-video: c26780b224543c62d5e1b2a7244a5cd1b50e8253
|
||||
React-perflogger: 367418425c5e4a9f0f80385ee1eaacd2a7348f8e
|
||||
React-RCTActionSheet: e4885e7136f98ded1137cd3daccc05eaed97d5a6
|
||||
React-RCTAnimation: 7c5a74f301c9b763343ba98a3dd776ed2676993f
|
||||
|
@ -27,6 +27,7 @@
|
||||
"react-native-safe-area-context": "^4.3.3",
|
||||
"react-native-safe-area-view": "^1.1.1",
|
||||
"react-native-sqlite-storage": "^6.0.1",
|
||||
"react-native-video": "^5.2.1",
|
||||
"react-native-web": "~0.18.7",
|
||||
"react-router-dom": "6",
|
||||
"react-router-native": "^6.3.0"
|
||||
|
@ -7,6 +7,8 @@ import MaterialIcons from '@expo/vector-icons/MaterialCommunityIcons';
|
||||
import Colors from 'constants/Colors';
|
||||
import { SafeAreaView } from 'react-native-safe-area-context';
|
||||
import ImagePicker from 'react-native-image-crop-picker'
|
||||
import { VideoFile } from './videoFile/VideoFile';
|
||||
import { ImageFile } from './imageFile/ImageFile';
|
||||
|
||||
export function AddTopic() {
|
||||
|
||||
@ -14,7 +16,7 @@ export function AddTopic() {
|
||||
|
||||
const addImage = async () => {
|
||||
try {
|
||||
const full = await ImagePicker.openPicker({ mediaType: 'photo', includeBase64: true });
|
||||
const full = await ImagePicker.openPicker({ mediaType: 'photo' });
|
||||
actions.addImage(full.path);
|
||||
}
|
||||
catch (err) {
|
||||
@ -22,6 +24,16 @@ export function AddTopic() {
|
||||
}
|
||||
}
|
||||
|
||||
const addVideo = async () => {
|
||||
try {
|
||||
const full = await ImagePicker.openPicker({ mediaType: 'video' });
|
||||
actions.addVideo(full.path);
|
||||
}
|
||||
catch (err) {
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
const remove = (item) => {
|
||||
Alert.alert(
|
||||
`Removing ${item.type} from message.`,
|
||||
@ -40,11 +52,17 @@ export function AddTopic() {
|
||||
const renderAsset = ({ item }) => {
|
||||
if (item.type === 'image') {
|
||||
return (
|
||||
<TouchableOpacity onPress={() => remove(item)}>
|
||||
<Image source={{ uri: item.data }} style={{ width: 92 * item.ratio, height: 92, marginRight: 16 }}resizeMode={'contain'} />
|
||||
</TouchableOpacity>
|
||||
<ImageFile path={item.data} remove={() => remove(item)} />
|
||||
);
|
||||
}
|
||||
if (item.type === 'video') {
|
||||
return (
|
||||
<VideoFile path={item.data}
|
||||
remove={() => remove(item)}
|
||||
setPosition={(position) => actions.setVideoPosition(item.key, position)}
|
||||
/>
|
||||
)
|
||||
}
|
||||
else {
|
||||
return (
|
||||
<View style={styles.asset}></View>
|
||||
@ -67,7 +85,7 @@ export function AddTopic() {
|
||||
<TouchableOpacity style={styles.addButton} onPress={addImage}>
|
||||
<AntIcons name="picture" size={20} color={Colors.text} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.addButton}>
|
||||
<TouchableOpacity style={styles.addButton} onPress={addVideo}>
|
||||
<MaterialIcons name="video-outline" size={24} color={Colors.text} />
|
||||
</TouchableOpacity>
|
||||
<TouchableOpacity style={styles.addButton}>
|
||||
|
@ -60,8 +60,8 @@ export const styles = StyleSheet.create({
|
||||
},
|
||||
carousel: {
|
||||
paddingTop: 8,
|
||||
paddingLeft: 16,
|
||||
paddingRight: 16,
|
||||
paddingLeft: 16,
|
||||
},
|
||||
})
|
||||
|
||||
|
@ -0,0 +1,24 @@
|
||||
import { useRef, useEffect } from 'react';
|
||||
import { TouchableOpacity, View, Image } from 'react-native';
|
||||
import { useImageFile } from './useImageFile.hook';
|
||||
import { styles } from './ImageFile.styled';
|
||||
import Icons from '@expo/vector-icons/AntDesign';
|
||||
import Colors from 'constants/Colors';
|
||||
|
||||
export function ImageFile({ path, setPosition, remove }) {
|
||||
|
||||
const { state, actions } = useImageFile();
|
||||
|
||||
useEffect(() => {
|
||||
Image.getSize(path, actions.setInfo);
|
||||
}, [path]);
|
||||
|
||||
return (
|
||||
<TouchableOpacity onLongPress={remove}>
|
||||
<Image source={{ uri: path }} style={{ width: 92 * state.ratio, height: 92, marginRight: 16 }} resizeMode={'contain'} />
|
||||
<View style={styles.overlay}>
|
||||
<Icons name="picture" size={20} color={Colors.grey} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { Colors } from 'constants/Colors';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
overlay: {
|
||||
marginRight: 16,
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
padding: 2,
|
||||
borderTopLeftRadius: 4,
|
||||
backgroundColor: Colors.white,
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.divider,
|
||||
},
|
||||
})
|
||||
|
@ -0,0 +1,22 @@
|
||||
import { useState, useRef, useEffect, useContext } from 'react';
|
||||
import { ConversationContext } from 'context/ConversationContext';
|
||||
|
||||
export function useImageFile() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
ratio: 1,
|
||||
});
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
const actions = {
|
||||
setInfo: (width, height) => {
|
||||
updateState({ ratio: width / height });
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -27,6 +27,38 @@ export function useAddTopic(cardId, channelId) {
|
||||
updateState({ assets: [ ...state.assets, asset ] });
|
||||
});
|
||||
},
|
||||
addVideo: (data) => {
|
||||
assetId.current++;
|
||||
const asset = { key: assetId.current, type: 'video', data: data, ratio: 1, duration: 0, position: 0, ref: null };
|
||||
updateState({ assets: [ ...state.assets, asset ] });
|
||||
},
|
||||
setVideoInfo: (key, width, height, duration) => {
|
||||
updateState({ assets: state.assets.map((item) => {
|
||||
if(item.key === key) {
|
||||
return { ...item, ratio: width / height, duration };
|
||||
}
|
||||
return item;
|
||||
})
|
||||
});
|
||||
},
|
||||
setVideoRef: (key, ref) => {
|
||||
updateState({ assets: state.assets.map((item) => {
|
||||
if(item.key === key) {
|
||||
return { ...item, ref };
|
||||
}
|
||||
return item;
|
||||
})
|
||||
});
|
||||
},
|
||||
setVideoPosition: (key, position) => {
|
||||
updateState({ assets: state.assets.map((item) => {
|
||||
if(item.key === key) {
|
||||
return { ...item, position };
|
||||
}
|
||||
return item;
|
||||
})
|
||||
});
|
||||
},
|
||||
removeAsset: (key) => {
|
||||
updateState({ assets: state.assets.filter(item => (item.key !== key))});
|
||||
},
|
||||
|
@ -0,0 +1,33 @@
|
||||
import { useRef, useEffect } from 'react';
|
||||
import { TouchableOpacity, View } from 'react-native';
|
||||
import Video from 'react-native-video';
|
||||
import { useVideoFile } from './useVideoFile.hook';
|
||||
import { styles } from './VideoFile.styled';
|
||||
import Icons from '@expo/vector-icons/MaterialCommunityIcons';
|
||||
import Colors from 'constants/Colors';
|
||||
|
||||
export function VideoFile({ path, setPosition, remove }) {
|
||||
|
||||
const { state, actions } = useVideoFile();
|
||||
|
||||
const video = useRef();
|
||||
|
||||
useEffect(() => {
|
||||
if (video.current) {
|
||||
video.current.seek(state.position);
|
||||
setPosition(state.position);
|
||||
}
|
||||
}, [state.position]);
|
||||
|
||||
return (
|
||||
<TouchableOpacity onPress={actions.setNextPosition} onLongPress={remove}>
|
||||
<Video source={{ uri: path }} style={{ width: 92 * state.ratio, height: 92, marginRight: 16 }} resizeMode={'cover'} paused={true}
|
||||
onLoad={({ naturalSize, duration }) => actions.setInfo(naturalSize.width, naturalSize.height, duration)}
|
||||
ref={(ref) => video.current = ref}
|
||||
/>
|
||||
<View style={styles.overlay}>
|
||||
<Icons name="video-outline" size={20} color={Colors.grey} />
|
||||
</View>
|
||||
</TouchableOpacity>
|
||||
);
|
||||
}
|
@ -0,0 +1,17 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
import { Colors } from 'constants/Colors';
|
||||
|
||||
export const styles = StyleSheet.create({
|
||||
overlay: {
|
||||
marginRight: 16,
|
||||
position: 'absolute',
|
||||
bottom: 0,
|
||||
right: 0,
|
||||
padding: 2,
|
||||
borderTopLeftRadius: 4,
|
||||
backgroundColor: Colors.white,
|
||||
borderWidth: 1,
|
||||
borderColor: Colors.divider,
|
||||
},
|
||||
})
|
||||
|
@ -0,0 +1,30 @@
|
||||
import { useState, useRef, useEffect, useContext } from 'react';
|
||||
import { ConversationContext } from 'context/ConversationContext';
|
||||
|
||||
export function useVideoFile() {
|
||||
|
||||
const [state, setState] = useState({
|
||||
duration: 0,
|
||||
position: 0,
|
||||
ratio: 1,
|
||||
});
|
||||
|
||||
const updateState = (value) => {
|
||||
setState((s) => ({ ...s, ...value }));
|
||||
}
|
||||
|
||||
const actions = {
|
||||
setInfo: (width, height, duration) => {
|
||||
updateState({ ratio: width / height, duration: Math.floor(duration) });
|
||||
},
|
||||
setNextPosition: () => {
|
||||
if (state.duration) {
|
||||
const position = (state.position + 1) % state.duration;
|
||||
updateState({ position });
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return { state, actions };
|
||||
}
|
||||
|
@ -1686,7 +1686,7 @@
|
||||
resolved "https://registry.npmjs.org/@react-native/assets/-/assets-1.0.0.tgz"
|
||||
integrity sha512-KrwSpS1tKI70wuKl68DwJZYEvXktDHdZMG0k2AXD/rJVSlB23/X2CB2cutVR0HwNMJIal9HOUOBB2rVfa6UGtQ==
|
||||
|
||||
"@react-native/normalize-color@2.0.0", "@react-native/normalize-color@^2.0.0":
|
||||
"@react-native/normalize-color@*", "@react-native/normalize-color@2.0.0", "@react-native/normalize-color@^2.0.0":
|
||||
version "2.0.0"
|
||||
resolved "https://registry.npmjs.org/@react-native/normalize-color/-/normalize-color-2.0.0.tgz"
|
||||
integrity sha512-Wip/xsc5lw8vsBlmY2MO/gFLp3MvuZ2baBZjDeTjjndMgM0h5sxz7AZR62RDPGgstp8Np7JzjvVqVT7tpFZqsw==
|
||||
@ -2911,6 +2911,15 @@ depd@~1.1.2:
|
||||
resolved "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz"
|
||||
integrity sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==
|
||||
|
||||
deprecated-react-native-prop-types@^2.2.0:
|
||||
version "2.3.0"
|
||||
resolved "https://registry.yarnpkg.com/deprecated-react-native-prop-types/-/deprecated-react-native-prop-types-2.3.0.tgz#c10c6ee75ff2b6de94bb127f142b814e6e08d9ab"
|
||||
integrity sha512-pWD0voFtNYxrVqvBMYf5gq3NA2GCpfodS1yNynTPc93AYA/KEMGeWDqqeUB6R2Z9ZofVhks2aeJXiuQqKNpesA==
|
||||
dependencies:
|
||||
"@react-native/normalize-color" "*"
|
||||
invariant "*"
|
||||
prop-types "*"
|
||||
|
||||
destroy@1.2.0:
|
||||
version "1.2.0"
|
||||
resolved "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz"
|
||||
@ -2933,6 +2942,11 @@ electron-to-chromium@^1.4.202:
|
||||
resolved "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.242.tgz"
|
||||
integrity sha512-nPdgMWtjjWGCtreW/2adkrB2jyHjClo9PtVhR6rW+oxa4E4Wom642Tn+5LslHP3XPL5MCpkn5/UEY60EXylNeQ==
|
||||
|
||||
eme-encryption-scheme-polyfill@^2.0.1:
|
||||
version "2.1.1"
|
||||
resolved "https://registry.yarnpkg.com/eme-encryption-scheme-polyfill/-/eme-encryption-scheme-polyfill-2.1.1.tgz#91c823ed584e8ec5a9f03a6a676def8f80c57a4c"
|
||||
integrity sha512-njD17wcUrbqCj0ArpLu5zWXtaiupHb/2fIUQGdInf83GlI+Q6mmqaPGLdrke4savKAu15J/z1Tg/ivDgl14g0g==
|
||||
|
||||
emoji-regex@^8.0.0:
|
||||
version "8.0.0"
|
||||
resolved "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz"
|
||||
@ -3783,7 +3797,7 @@ internal-ip@4.3.0:
|
||||
default-gateway "^4.2.0"
|
||||
ipaddr.js "^1.9.0"
|
||||
|
||||
invariant@^2.2.4:
|
||||
invariant@*, invariant@^2.2.4:
|
||||
version "2.2.4"
|
||||
resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz"
|
||||
integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA==
|
||||
@ -4252,6 +4266,11 @@ jsonfile@^6.0.1:
|
||||
optionalDependencies:
|
||||
graceful-fs "^4.1.6"
|
||||
|
||||
keymirror@^0.1.1:
|
||||
version "0.1.1"
|
||||
resolved "https://registry.yarnpkg.com/keymirror/-/keymirror-0.1.1.tgz#918889ea13f8d0a42e7c557250eee713adc95c35"
|
||||
integrity sha512-vIkZAFWoDijgQT/Nvl2AHCMmnegN2ehgTPYuyy2hWQkQSntI0S7ESYqdLkoSe1HyEBFHHkCgSIvVdSEiWwKvCg==
|
||||
|
||||
kind-of@^3.0.2, kind-of@^3.0.3, kind-of@^3.2.0:
|
||||
version "3.2.2"
|
||||
resolved "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz"
|
||||
@ -5383,7 +5402,7 @@ prompts@^2.3.2, prompts@^2.4.0:
|
||||
kleur "^3.0.3"
|
||||
sisteransi "^1.0.5"
|
||||
|
||||
prop-types@^15.7.2:
|
||||
prop-types@*, prop-types@^15.7.2:
|
||||
version "15.8.1"
|
||||
resolved "https://registry.yarnpkg.com/prop-types/-/prop-types-15.8.1.tgz#67d87bf1a694f48435cf332c24af10214a3140b5"
|
||||
integrity sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==
|
||||
@ -5552,6 +5571,16 @@ react-native-sqlite-storage@^6.0.1:
|
||||
resolved "https://registry.npmjs.org/react-native-sqlite-storage/-/react-native-sqlite-storage-6.0.1.tgz"
|
||||
integrity sha512-1tDFjrint6X6qSYKf3gDyz+XB+X79jfiL6xTugKHPRtF0WvqMtVgdLuNqZunIXjNEvNtNVEbXaeZ6MsguFu00A==
|
||||
|
||||
react-native-video@^5.2.1:
|
||||
version "5.2.1"
|
||||
resolved "https://registry.yarnpkg.com/react-native-video/-/react-native-video-5.2.1.tgz#a17e856759d7e17eee9cbd9df0d05ba22e88d457"
|
||||
integrity sha512-aJlr9MeTuQ0LpZ4n+EC9RvhoKeiPbLtI2Rxy8u7zo/wzGevbRpWHSBj9xZ5YDBXnAVXzuqyNIkGhdw7bfdIBZw==
|
||||
dependencies:
|
||||
deprecated-react-native-prop-types "^2.2.0"
|
||||
keymirror "^0.1.1"
|
||||
prop-types "^15.7.2"
|
||||
shaka-player "^2.5.9"
|
||||
|
||||
react-native-web@~0.18.7:
|
||||
version "0.18.9"
|
||||
resolved "https://registry.npmjs.org/react-native-web/-/react-native-web-0.18.9.tgz"
|
||||
@ -6024,6 +6053,13 @@ setprototypeof@1.2.0:
|
||||
resolved "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz"
|
||||
integrity sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==
|
||||
|
||||
shaka-player@^2.5.9:
|
||||
version "2.5.23"
|
||||
resolved "https://registry.yarnpkg.com/shaka-player/-/shaka-player-2.5.23.tgz#db92d1c6cf2314f0180a2cec11b0e2f2560336f5"
|
||||
integrity sha512-3MC9k0OXJGw8AZ4n/ZNCZS2yDxx+3as5KgH6Tx4Q5TRboTBBCu6dYPI5vp1DxKeyU12MBN1Zcbs7AKzXv2EnCg==
|
||||
dependencies:
|
||||
eme-encryption-scheme-polyfill "^2.0.1"
|
||||
|
||||
shallow-clone@^3.0.0:
|
||||
version "3.0.1"
|
||||
resolved "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz"
|
||||
|
Loading…
Reference in New Issue
Block a user