client side generation of thumbs for e2e based com

This commit is contained in:
Roland Osborne 2023-04-25 14:12:30 -07:00
parent a9cb556392
commit e388d9ba42
4 changed files with 76 additions and 12 deletions

View File

@ -29,6 +29,7 @@
"react-dom": "^18.2.0",
"react-easy-crop": "^4.1.4",
"react-icons": "^4.8.0",
"react-image-file-resizer": "^0.4.8",
"react-player": "^2.10.0",
"react-resize-detector": "^7.0.0",
"react-router-dom": "^6.2.2",

View File

@ -10,7 +10,7 @@ import { Carousel } from 'carousel/Carousel';
export function AddTopic({ contentKey }) {
const { state, actions } = useAddTopic();
const { state, actions } = useAddTopic(contentKey);
const [modal, modalContext] = Modal.useModal();
const attachImage = useRef(null);
@ -28,7 +28,7 @@ export function AddTopic({ contentKey }) {
const addTopic = async () => {
if (state.messageText || state.assets.length) {
try {
await actions.addTopic(contentKey);
await actions.addTopic();
}
catch (err) {
console.log(err);
@ -108,22 +108,22 @@ export function AddTopic({ contentKey }) {
value={state.messageText} autocapitalize="none" />
</div>
<div class="buttons">
{ !contentKey && state.enableImage && (
{ state.enableImage && (
<div class="button space" onClick={() => attachImage.current.click()}>
<PictureOutlined />
</div>
)}
{ !contentKey && state.enableVideo && (
{ state.enableVideo && (
<div class="button space" onClick={() => attachVideo.current.click()}>
<VideoCameraOutlined />
</div>
)}
{ !contentKey && state.enableAudio && (
{ state.enableAudio && (
<div class="button space" onClick={() => attachAudio.current.click()}>
<SoundOutlined />
</div>
)}
{ !contentKey && (
{ (state.enableImage || state.enableVideo || state.enableAudio) && (
<div class="bar space" />
)}
<div class="button space">

View File

@ -1,8 +1,9 @@
import { useContext, useState, useEffect } from 'react';
import { useContext, useState, useRef, useEffect } from 'react';
import { ConversationContext } from 'context/ConversationContext';
import { encryptTopicSubject } from 'context/sealUtil';
import Resizer from "react-image-file-resizer";
export function useAddTopic() {
export function useAddTopic(contentKey) {
const [state, setState] = useState({
enableImage: null,
@ -18,6 +19,7 @@ export function useAddTopic() {
});
const conversation = useContext(ConversationContext);
const objects = useRef([]);
const updateState = (value) => {
setState((s) => ({ ...s, ...value }));
@ -45,19 +47,33 @@ export function useAddTopic() {
});
}
const clearObjects = () => {
objects.current.forEach(object => {
URL.revokeObjectURL(object);
});
objects.current = [];
}
useEffect(() => {
updateState({ assets: [] });
return () => { console.log("RETURN CLEAR"); clearObjects() };
}, [contentKey]);
useEffect(() => {
const { enableImage, enableAudio, enableVideo } = conversation.state.channel?.data?.channelDetail || {};
updateState({ enableImage, enableAudio, enableVideo });
}, [conversation.state.channel?.data?.channelDetail]);
const actions = {
addImage: (image) => {
addImage: async (image) => {
let url = URL.createObjectURL(image);
addAsset({ image, url })
addAsset({ image, url });
objects.current.push(url);
},
addVideo: (video) => {
addVideo: async (video) => {
let url = URL.createObjectURL(video);
addAsset({ video, url, position: 0 })
objects.current.push(url);
},
addAudio: (audio) => {
let url = URL.createObjectURL(audio);
@ -81,7 +97,7 @@ export function useAddTopic() {
setTextSize: (value) => {
updateState({ textSizeSet: true, textSize: value });
},
addTopic: async (contentKey) => {
addTopic: async () => {
if (!state.busy) {
try {
updateState({ busy: true });
@ -119,6 +135,7 @@ export function useAddTopic() {
await conversation.actions.addTopic(type, message, state.assets);
updateState({ busy: false, messageText: null, textColor: '#444444', textColorSet: false,
textSize: 12, textSizeSet: false, assets: [] });
clearObjects();
}
catch(err) {
console.log(err);
@ -135,3 +152,44 @@ export function useAddTopic() {
return { state, actions };
}
async function getImageThumb(url) {
return new Promise(resolve => {
Resizer.imageFileResizer(url, 192, 192, 'JPEG', 50, 0,
uri => {
resolve(uri);
}, 'base64', 128, 128 );
});
}
async function getVideoThumb(url, pos) {
return new Promise((resolve, reject) => {
var video = document.createElement("video");
var timeupdate = function (ev) {
video.removeEventListener("timeupdate", timeupdate);
video.pause();
setTimeout(() => {
var canvas = document.createElement("canvas");
if (video.videoWidth > video.videoHeight) {
canvas.width = 192;
canvas.height = Math.floor((192 * video.videoHeight / video.videoWidth));
}
else {
canvas.height = 192;
canvas.width = Math.floor((192 * video.videoWidth / video.videoHeight));
}
canvas.getContext("2d").drawImage(video, 0, 0, canvas.width, canvas.height);
var image = canvas.toDataURL("image/jpeg", 0.75);
resolve(image);
canvas.remove();
video.remove();
}, 1000);
};
video.addEventListener("timeupdate", timeupdate);
video.preload = "metadata";
video.src = url;
video.muted = true;
video.playsInline = true;
video.currentTime = pos;
video.play();
});
}

View File

@ -9139,6 +9139,11 @@ react-icons@^4.8.0:
resolved "https://registry.yarnpkg.com/react-icons/-/react-icons-4.8.0.tgz#621e900caa23b912f737e41be57f27f6b2bff445"
integrity sha512-N6+kOLcihDiAnj5Czu637waJqSnwlMNROzVZMhfX68V/9bu9qHaMIJC4UdozWoOk57gahFCNHwVvWzm0MTzRjg==
react-image-file-resizer@^0.4.8:
version "0.4.8"
resolved "https://registry.yarnpkg.com/react-image-file-resizer/-/react-image-file-resizer-0.4.8.tgz#85f4ae4469fd2867d961568af660ef403d7a79af"
integrity sha512-Ue7CfKnSlsfJ//SKzxNMz8avDgDSpWQDOnTKOp/GNRFJv4dO9L5YGHNEnj40peWkXXAK2OK0eRIoXhOYpUzUTQ==
react-is@^16.12.0, "react-is@^16.12.0 || ^17.0.0 || ^18.0.0", react-is@^16.13.1, react-is@^16.7.0:
version "16.13.1"
resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz"