playing audio

This commit is contained in:
balzack 2024-12-31 19:24:20 -08:00
parent 4eee3568ce
commit f5cc6ca9e7
5 changed files with 119 additions and 10 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

@ -2,4 +2,59 @@ import {StyleSheet} from 'react-native';
import {Colors} from '../constants/Colors';
export const styles = StyleSheet.create({
modal: {
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
button: {
position: 'absolute',
borderRadius: 4,
backgroundColor: '#444444',
},
container: {
position: 'relative',
width: 92,
height: 92,
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
},
blur: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
},
audio: {
position: 'relative',
},
thumb: {
borderRadius: 4,
width: 92,
height: 92,
},
full: {
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
},
close: {
position: 'absolute',
top: 0,
right: 0,
},
closeIcon: {
backgroundColor: 'transparent',
},
progress: {
position: 'absolute',
bottom: '10%',
width: '50%',
},
});

View File

@ -1,11 +1,62 @@
import React, { useState, useEffect } from 'react';
import { Text } from 'react-native-paper'
import React, { useState, useEffect, useRef } from 'react';
import { SafeAreaView, Modal, Pressable, View, Image } from 'react-native'
import { Icon, ProgressBar, IconButton } from 'react-native-paper'
import { useAudioAsset } from './useAudioAsset.hook';
import { MediaAsset } from '../../conversation/Conversation';
import { styles } from './AudioAsset.styled'
import {BlurView} from '@react-native-community/blur';
import Video from 'react-native-video'
import thumb from '../../images/audio.png';
export function AudioAsset({ topicId, asset }: { topicId: string, asset: MediaAsset }) {
const { state, actions } = useAudioAsset(topicId, asset);
const [modal, setModal] = useState(false);
return (<Text>AUDIO</Text>);
const showAudio = () => {
setModal(true);
actions.loadAudio();
};
const hideAudio = () => {
setModal(false);
actions.cancelLoad();
}
return (
<View style={styles.audio}>
<Pressable style={styles.container} onPress={showAudio}>
<Image
style={styles.thumb}
resizeMode="contain"
source={thumb}
/>
<View style={styles.button}>
<Icon size={28} source="play-box-outline" />
</View>
</Pressable>
<Modal animationType="fade" transparent={true} supportedOrientations={['portrait', 'landscape']} visible={modal} onRequestClose={hideAudio}>
<View style={styles.modal}>
<BlurView style={styles.blur} blurType="dark" blurAmount={16} reducedTransparencyFallbackColor="dark" />
<Image
style={styles.full}
resizeMode="contain"
source={thumb}
/>
{ state.dataUrl && (
<Video source={{ uri: state.dataUrl }} style={styles.full}
controls={false} resizeMode="contain" />
)}
{ state.loading && (
<View style={styles.progress}>
<ProgressBar progress={state.loadPercent / 100} />
</View>
)}
<SafeAreaView style={styles.close}>
<IconButton style={styles.closeIcon} icon="close" compact="true" mode="contained" size={28} onPress={hideAudio} />
</SafeAreaView>
</View>
</Modal>
</View>
);
}

View File

@ -1,4 +1,4 @@
import { useState, useContext, useEffect } from 'react'
import { useState, useContext, useEffect, useRef } from 'react'
import { AppContext } from '../../context/AppContext'
import { Focus } from 'databag-client-sdk'
import { ContextType } from '../../context/ContextType'
@ -9,8 +9,10 @@ export function useAudioAsset(topicId: string, asset: MediaAsset) {
const [state, setState] = useState({
dataUrl: null,
loading: false,
loaded: false,
loadPercent: 0,
})
const cancelled = useRef(false);
// eslint-disable-next-line @typescript-eslint/no-explicit-any
const updateState = (value: any) => {
@ -18,21 +20,22 @@ export function useAudioAsset(topicId: string, asset: MediaAsset) {
}
const actions = {
unloadAudio: () => {
updateState({ dataUrl: null });
cancelLoad: () => {
cancelled.current = true;
},
loadAudio: async () => {
const { focus } = app.state;
const assetId = asset.audio ? asset.audio.full : asset.encrypted ? asset.encrypted.parts : null;
if (focus && assetId != null && !state.loading) {
if (focus && assetId != null && !state.loading && !state.dataUrl) {
cancelled.current = false;
updateState({ loading: true, loadPercent: 0 });
try {
const dataUrl = await focus.getTopicAssetUrl(topicId, assetId, (loadPercent: number)=>{ updateState({ loadPercent }) });
updateState({ dataUrl, loading: false });
const dataUrl = await focus.getTopicAssetUrl(topicId, assetId, (loadPercent: number)=>{ updateState({ loadPercent }); return !cancelled.current });
updateState({ dataUrl });
} catch (err) {
updateState({ loading: false });
console.log(err);
}
updateState({ loading: false });
}
}
}