/* * Wire * Copyright (C) 2018 Wire Swiss GmbH * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see http://www.gnu.org/licenses/. * */ import React, {useEffect, useState} from 'react'; import cx from 'classnames'; import {container} from 'tsyringe'; import {RestrictedAudio} from 'Components/asset/RestrictedAudio'; import * as Icon from 'Components/Icon'; import {useKoSubscribableChildren} from 'Util/ComponentUtil'; import {getLogger} from 'Util/Logger'; import {formatSeconds} from 'Util/TimeUtil'; import {useEffectRef} from 'Util/useEffectRef'; import {AssetHeader} from './AssetHeader'; import {AudioSeekBar} from './controls/AudioSeekBar'; import {MediaButton} from './controls/MediaButton'; import {SeekBar} from './controls/SeekBar'; import {AssetUrl, useAssetTransfer} from './useAssetTransfer'; import {AssetTransferState} from '../../../../../assets/AssetTransferState'; import type {ContentMessage} from '../../../../../entity/message/ContentMessage'; import type {FileAsset} from '../../../../../entity/message/FileAsset'; import {TeamState} from '../../../../../team/TeamState'; const logger = getLogger('AudioAssetComponent'); export interface AudioAssetProps { className?: string; /* Does the asset have a visible header? */ hasHeader?: boolean; message: ContentMessage; teamState?: TeamState; isFocusable?: boolean; } export const AudioAsset: React.FC = ({ message, className, hasHeader = false, teamState = container.resolve(TeamState), isFocusable = true, }) => { const asset = message.getFirstAsset() as FileAsset; const [audioElement, setAudioElement] = useEffectRef(); const {isFileSharingReceivingEnabled} = useKoSubscribableChildren(teamState, ['isFileSharingReceivingEnabled']); const {isObfuscated} = useKoSubscribableChildren(message, ['isObfuscated']); const {transferState, uploadProgress, cancelUpload, getAssetUrl} = useAssetTransfer(message); const [audioTime, setAudioTime] = useState(asset?.meta?.duration || 0); const [audioSrc, setAudioSrc] = useState(); const onTimeupdate = () => audioElement && setAudioTime(audioElement.currentTime); const showLoudnessPreview = !!(asset.meta?.loudness?.length ?? 0 > 0); const onPauseButtonClicked = () => audioElement?.pause(); const onPlayButtonClicked = async () => { if (audioSrc) { audioElement?.play(); } else { asset.status(AssetTransferState.DOWNLOADING); try { const url = await getAssetUrl(asset.original_resource()); setAudioSrc(url); } catch (error) { logger.error('Failed to load audio asset ', error); } asset.status(AssetTransferState.UPLOADED); } }; useEffect(() => { if (audioSrc && audioElement) { const playPromise = audioElement.play(); playPromise?.catch(error => { logger.error('Failed to load audio asset ', error); }); } }, [audioElement, audioSrc]); useEffect(() => () => audioSrc?.dispose(), []); return (