diff --git a/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.jsx b/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.jsx index d074dce6..a34b5ef8 100644 --- a/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.jsx +++ b/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.jsx @@ -1,9 +1,10 @@ import React, { useEffect, useState, useRef } from 'react'; -import { Modal, Spin } from 'antd'; +import { Progress, Modal, Spin } from 'antd'; import ReactResizeDetector from 'react-resize-detector'; import { PlayCircleOutlined, MinusCircleOutlined, SoundOutlined } from '@ant-design/icons'; import { AudioAssetWrapper, AudioModalWrapper } from './AudioAsset.styled'; import { useAudioAsset } from './useAudioAsset.hook'; +import Colors from 'constants/Colors'; import background from 'images/audio.png'; @@ -56,6 +57,9 @@ export function AudioAsset({ asset }) { { state.loading && !state.error && (
+ { state.total != 0 && ( + + )}
)} { !state.ready && !state.loading && ( diff --git a/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.styled.js b/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.styled.js index e3dcd5c0..27d5431a 100644 --- a/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.styled.js +++ b/net/web/src/session/conversation/topicItem/audioAsset/AudioAsset.styled.js @@ -80,6 +80,8 @@ export const AudioModalWrapper = styled.div` position: absolute; color: white; border-radius: 8px; + display: flex; + flex-direction: column; .ant-spin-dot-item { background-color: ${Colors.white}; diff --git a/net/web/src/session/conversation/topicItem/audioAsset/useAudioAsset.hook.js b/net/web/src/session/conversation/topicItem/audioAsset/useAudioAsset.hook.js index 6dd0d523..a93cc27d 100644 --- a/net/web/src/session/conversation/topicItem/audioAsset/useAudioAsset.hook.js +++ b/net/web/src/session/conversation/topicItem/audioAsset/useAudioAsset.hook.js @@ -11,6 +11,8 @@ export function useAudioAsset(asset) { error: false, ready: false, url: null, + block: 0, + total: 0, }); const updateState = (value) => { @@ -23,7 +25,7 @@ export function useAudioAsset(asset) { try { const view = index.current; updateState({ active: true, ready: false, error: false, loading: true, url: null }); - const blob = await asset.getDecryptedBlob(() => view != index.current); + const blob = await asset.getDecryptedBlob(() => view != index.current, (block, total) => updateState({ block, total })); const url = URL.createObjectURL(blob); revoke.current = url; updateState({ loading: false, url }); diff --git a/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.jsx b/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.jsx index 57514679..88c46c9a 100644 --- a/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.jsx +++ b/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.jsx @@ -1,8 +1,9 @@ import React, { useState } from 'react'; -import { Modal, Spin } from 'antd'; +import { Progress, Modal, Spin } from 'antd'; import ReactResizeDetector from 'react-resize-detector'; import { ImageAssetWrapper, ImageModalWrapper } from './ImageAsset.styled'; import { useImageAsset } from './useImageAsset.hook'; +import Colors from 'constants/Colors'; export function ImageAsset({ asset }) { @@ -42,6 +43,9 @@ export function ImageAsset({ asset }) { { !state.error && (
+ { state.total != 0 && ( + + )}
)} { state.error && ( diff --git a/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.styled.js b/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.styled.js index 1d4e6cb8..7162a19e 100644 --- a/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.styled.js +++ b/net/web/src/session/conversation/topicItem/imageAsset/ImageAsset.styled.js @@ -76,6 +76,8 @@ export const ImageModalWrapper = styled.div` position: absolute; color: white; border-radius: 8px; + display: flex; + flex-direction: column; .ant-spin-dot-item { background-color: ${Colors.white}; diff --git a/net/web/src/session/conversation/topicItem/imageAsset/useImageAsset.hook.js b/net/web/src/session/conversation/topicItem/imageAsset/useImageAsset.hook.js index e278d43f..f1aff86c 100644 --- a/net/web/src/session/conversation/topicItem/imageAsset/useImageAsset.hook.js +++ b/net/web/src/session/conversation/topicItem/imageAsset/useImageAsset.hook.js @@ -11,7 +11,9 @@ export function useImageAsset(asset) { height: 0, loading: false, error: false, - url: null, + url: null, + block: 0, + total: 0, }); const updateState = (value) => { @@ -24,7 +26,7 @@ export function useImageAsset(asset) { try { const view = index.current; updateState({ popout: true, width, height, error: false, loading: true, url: null }); - const blob = await asset.getDecryptedBlob(() => view != index.current); + const blob = await asset.getDecryptedBlob(() => view != index.current, (block, total) => updateState({ block, total })); const url = URL.createObjectURL(blob); updateState({ loading: false, url }); revoke.current = url; diff --git a/net/web/src/session/conversation/topicItem/useTopicItem.hook.js b/net/web/src/session/conversation/topicItem/useTopicItem.hook.js index 6fd97da5..c017bd38 100644 --- a/net/web/src/session/conversation/topicItem/useTopicItem.hook.js +++ b/net/web/src/session/conversation/topicItem/useTopicItem.hook.js @@ -30,7 +30,7 @@ export function useTopicItem(topic, contentKey) { if (asset.encrypted) { const encrypted = true; const { type, thumb, label, parts } = asset.encrypted; - const getDecryptedBlob = async (abort) => { + const getDecryptedBlob = async (abort, progress) => { let pos = 0; let len = 0; @@ -39,6 +39,7 @@ export function useTopicItem(topic, contentKey) { if (abort()) { throw new Error("asset unseal aborted"); } + progress(i, parts.length); const part = parts[i]; const url = topic.assetUrl(part.partId, topic.id); const response = await fetchWithTimeout(url, { method: 'GET' }); @@ -48,6 +49,7 @@ export function useTopicItem(topic, contentKey) { slices.push(slice); len += slice.byteLength; }; + progress(parts.length, parts.length); const data = new Uint8Array(len) for (let i = 0; i < slices.length; i++) { diff --git a/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.jsx b/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.jsx index 76b1eae2..7ca4cebf 100644 --- a/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.jsx +++ b/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.jsx @@ -1,8 +1,9 @@ -import { Modal, Spin } from 'antd'; +import { Modal, Spin, Progress } from 'antd'; import ReactResizeDetector from 'react-resize-detector'; import { VideoCameraOutlined } from '@ant-design/icons'; import { VideoAssetWrapper, VideoModalWrapper } from './VideoAsset.styled'; import { useVideoAsset } from './useVideoAsset.hook'; +import Colors from 'constants/Colors'; export function VideoAsset({ asset }) { @@ -51,6 +52,9 @@ export function VideoAsset({ asset }) { { !state.error && (
+ { state.total != 0 && ( + + )}
)} diff --git a/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.styled.js b/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.styled.js index 892c468c..c0b5db69 100644 --- a/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.styled.js +++ b/net/web/src/session/conversation/topicItem/videoAsset/VideoAsset.styled.js @@ -48,6 +48,8 @@ export const VideoModalWrapper = styled.div` position: absolute; color: white; border-radius: 8px; + display: flex; + flex-direction: column; .ant-spin-dot-item { background-color: ${Colors.white}; diff --git a/net/web/src/session/conversation/topicItem/videoAsset/useVideoAsset.hook.js b/net/web/src/session/conversation/topicItem/videoAsset/useVideoAsset.hook.js index ff353d12..bfeca798 100644 --- a/net/web/src/session/conversation/topicItem/videoAsset/useVideoAsset.hook.js +++ b/net/web/src/session/conversation/topicItem/videoAsset/useVideoAsset.hook.js @@ -14,6 +14,8 @@ export function useVideoAsset(asset) { error: false, url: null, loaded: false, + block: 0, + total: 0, }); const updateState = (value) => { @@ -26,7 +28,7 @@ export function useVideoAsset(asset) { try { const view = index.current; updateState({ active: true, width, height, error: false, loaded: false, loading: true, url: null }); - const blob = await asset.getDecryptedBlob(() => view != index.current); + const blob = await asset.getDecryptedBlob(() => view != index.current, (block, total) => updateState({ block, total })); const url = URL.createObjectURL(blob); revoke.current = url; updateState({ url, loading: false });