diff --git a/app/client/web/src/conversation/Conversation.tsx b/app/client/web/src/conversation/Conversation.tsx index 2cdf7061..b5411849 100644 --- a/app/client/web/src/conversation/Conversation.tsx +++ b/app/client/web/src/conversation/Conversation.tsx @@ -8,6 +8,8 @@ import { Message } from '../message/Message'; import { modals } from '@mantine/modals' import { ImageFile } from './imageFile/ImageFile'; import { VideoFile } from './videoFile/VideoFile'; +import { AudioFile } from './audioFile/AudioFile'; +import { BinaryFile } from './binaryFile/BinaryFile'; const PAD_HEIGHT = (1024 - 64); const LOAD_DEBOUNCE = 1000; @@ -28,6 +30,8 @@ export function Conversation() { const { state, actions } = useConversation(); const attachImage = useRef({ click: ()=>{} } as HTMLInputElement); const attachVideo = useRef({ click: ()=>{} } as HTMLInputElement); + const attachAudio = useRef({ click: ()=>{} } as HTMLInputElement); + const attachBinary = useRef({ click: ()=>{} } as HTMLInputElement); const addImage = (image: File | undefined) => { if (image) { @@ -41,6 +45,18 @@ export function Conversation() { } } + const addAudio = (audio: File | undefined) => { + if (audio) { + actions.addAudio(audio); + } + } + + const addBinary = (binary: File | undefined) => { + if (binary) { + actions.addBinary(binary); + } + } + const sendMessage = async () => { if (!sending) { setSending(true); @@ -111,14 +127,13 @@ export function Conversation() { return } else if (asset.type === 'video') { return actions.setThumbPosition(index, position)} disabled={sending} /> + } else if (asset.type === 'audio') { + return } else { - return
+ return } }); -console.log(state.assets); - - return (
@@ -180,6 +195,8 @@ console.log(state.assets);
addImage(e.target?.files?.[0])} style={{display: 'none'}}/> addVideo(e.target?.files?.[0])} style={{display: 'none'}}/> + addAudio(e.target?.files?.[0])} style={{display: 'none'}}/> + addBinary(e.target?.files?.[0])} style={{display: 'none'}}/>
{ media }
@@ -191,10 +208,10 @@ console.log(state.assets); attachVideo.current.click()}> - + attachAudio.current.click()}> - + attachBinary.current.click()}> diff --git a/app/client/web/src/conversation/audioFile/AudioFile.module.css b/app/client/web/src/conversation/audioFile/AudioFile.module.css new file mode 100644 index 00000000..185ed2db --- /dev/null +++ b/app/client/web/src/conversation/audioFile/AudioFile.module.css @@ -0,0 +1,9 @@ +.asset { + padding-top: 16px; + + .thumb { + width: auto; + height: 92px; + } +} + diff --git a/app/client/web/src/conversation/audioFile/AudioFile.tsx b/app/client/web/src/conversation/audioFile/AudioFile.tsx new file mode 100644 index 00000000..aa347985 --- /dev/null +++ b/app/client/web/src/conversation/audioFile/AudioFile.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Image } from '@mantine/core' +import { useAudioFile } from './useAudioFile.hook'; +import classes from './AudioFile.module.css' +import audio from '../../images/audio.png' + +export function AudioFile({ source }: {source: File}) { + const { state, actions } = useAudioFile(source); + + return ( +
+ +
+ ); +} + diff --git a/app/client/web/src/conversation/audioFile/useAudioFile.hook.ts b/app/client/web/src/conversation/audioFile/useAudioFile.hook.ts new file mode 100644 index 00000000..741c5275 --- /dev/null +++ b/app/client/web/src/conversation/audioFile/useAudioFile.hook.ts @@ -0,0 +1,23 @@ +import { useState, useEffect } from 'react' + +export function useAudioFile(source: File) { + const [state, setState] = useState({ + thumbUrl: null, + }) + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const updateState = (value: any) => { + setState((s) => ({ ...s, ...value })) + } + + useEffect(() => { + const thumbUrl = URL.createObjectURL(source); + updateState({ thumbUrl }); + return () => { URL.revokeObjectURL(thumbUrl) }; + }, [source]); + + const actions = { + } + + return { state, actions } +} diff --git a/app/client/web/src/conversation/binaryFile/BinaryFile.module.css b/app/client/web/src/conversation/binaryFile/BinaryFile.module.css new file mode 100644 index 00000000..185ed2db --- /dev/null +++ b/app/client/web/src/conversation/binaryFile/BinaryFile.module.css @@ -0,0 +1,9 @@ +.asset { + padding-top: 16px; + + .thumb { + width: auto; + height: 92px; + } +} + diff --git a/app/client/web/src/conversation/binaryFile/BinaryFile.tsx b/app/client/web/src/conversation/binaryFile/BinaryFile.tsx new file mode 100644 index 00000000..83679c02 --- /dev/null +++ b/app/client/web/src/conversation/binaryFile/BinaryFile.tsx @@ -0,0 +1,16 @@ +import React from 'react'; +import { Image } from '@mantine/core' +import { useBinaryFile } from './useBinaryFile.hook'; +import classes from './BinaryFile.module.css' +import binary from '../../images/binary.png' + +export function BinaryFile({ source }: {source: File}) { + const { state, actions } = useBinaryFile(source); + + return ( +
+ +
+ ); +} + diff --git a/app/client/web/src/conversation/binaryFile/useBinaryFile.hook.ts b/app/client/web/src/conversation/binaryFile/useBinaryFile.hook.ts new file mode 100644 index 00000000..8181b7f8 --- /dev/null +++ b/app/client/web/src/conversation/binaryFile/useBinaryFile.hook.ts @@ -0,0 +1,19 @@ +import { useState, useEffect } from 'react' + +export function useBinaryFile(source: File) { + const [state, setState] = useState({ + }) + + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const updateState = (value: any) => { + setState((s) => ({ ...s, ...value })) + } + + useEffect(() => { + }, [source]); + + const actions = { + } + + return { state, actions } +} diff --git a/app/client/web/src/conversation/useConversation.hook.ts b/app/client/web/src/conversation/useConversation.hook.ts index 19437b85..f38b3601 100644 --- a/app/client/web/src/conversation/useConversation.hook.ts +++ b/app/client/web/src/conversation/useConversation.hook.ts @@ -32,7 +32,7 @@ function getImageThumb(file: File) { }); } -function getVideoThumb(file: File, position: number) { +function getVideoThumb(file: File, position?: number) { return new Promise((resolve, reject) => { const url = URL.createObjectURL(file); var video = document.createElement("video"); @@ -71,7 +71,7 @@ function getVideoThumb(file: File, position: number) { video.src = url; video.muted = true; video.playsInline = true; - video.currentTime = position; + video.currentTime = position ? position : 0; video.play(); }); } @@ -98,7 +98,7 @@ export function useConversation() { subjectNames: [], unknownContacts: 0, message: '', - assets: [] as {type: string, file: File}[], + assets: [] as {type: string, file: File, position?: number}[], }) // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -106,7 +106,7 @@ export function useConversation() { setState((s) => ({ ...s, ...value })) } - const updateAsset = (index, value) => { + const updateAsset = (index: number, value: any) => { setState((s) => { s.assets[index] = { ...s.assets[index], ...value }; return { ...s }; @@ -270,7 +270,11 @@ export function useConversation() { const type = asset.encrypted.type; const thumb = uploaded.find(upload => upload.appId === asset.encrypted.thumb)?.assetId; const parts = uploaded.find(upload => upload.appId === asset.encrypted.parts)?.assetId; - return { encrypted: { type, thumb, parts }}; + if (type === 'image' || type === 'video') { + return { encrypted: { type, thumb, parts }}; + } else { + return { encrypted: { type, thumb, parts }}; + } } else if (asset.image) { const thumb = uploaded.find(upload => upload.appId === asset.image.thumb)?.assetId; const full = uploaded.find(upload => upload.appId === asset.image.full)?.assetId; @@ -288,6 +292,8 @@ export function useConversation() { return { binary: { data } }; } }); +console.log(assets, uploaded); + return { text: state.message, assets }; } const progress = (precent: number) => {}; @@ -303,6 +309,14 @@ export function useConversation() { const type = 'video'; updateState({ assets: [ ...state.assets, { type, file } ]}); }, + addAudio: (file: File) => { + const type = 'audio'; + updateState({ assets: [ ...state.assets, { type, file } ]}); + }, + addBinary: (file: File) => { + const type = 'binary'; + updateState({ assets: [ ...state.assets, { type, file } ]}); + }, } return { state, actions } diff --git a/app/client/web/src/conversation/videoFile/VideoFile.tsx b/app/client/web/src/conversation/videoFile/VideoFile.tsx index 53fc175e..63e9da8e 100644 --- a/app/client/web/src/conversation/videoFile/VideoFile.tsx +++ b/app/client/web/src/conversation/videoFile/VideoFile.tsx @@ -8,7 +8,7 @@ export function VideoFile({ source, thumbPosition, disabled }: {source: File, th const { state, actions } = useVideoFile(source); const [loaded, setLoaded] = useState(false); const position = useRef(0); - const player = useRef(); + const player = useRef(null as null | HTMLVideoElement); const seek = (offset: number) => { if (player.current) { @@ -29,13 +29,15 @@ export function VideoFile({ source, thumbPosition, disabled }: {source: File, th } const onPause = () => { - player.current.pause(); + if (player.current) { + player.current.pause(); + } } return (
{ state.videoUrl && ( -