mirror of
https://github.com/toeverything/AFFiNE.git
synced 2026-08-03 18:40:00 +08:00
feat(core): add reload button to audio block (#12451)
Related to: [BS-3143](https://linear.app/affine-design/issue/BS-3143/更新-loading-和错误样式) <!-- This is an auto-generated comment: release notes by coderabbit.ai --> ## Summary by CodeRabbit - **New Features** - Added a reload button with an icon for audio blocks, allowing users to retry loading audio files if an error occurs. - Error messages are now displayed with actionable options when audio loading fails. - **Enhancements** - Audio file sizes are now shown in a human-readable format within the audio player. - Improved display of audio file information, including error messages and formatted descriptions. - **Style** - Updated styling for audio player and audio block components, including new styles for error states and reload button. - Renamed and refined audio player description styling for better layout and spacing. <!-- end of auto-generated comment: release notes by coderabbit.ai -->
This commit is contained in:
@@ -28,5 +28,24 @@ export const notesButtonIcon = style({
|
||||
});
|
||||
|
||||
export const error = style({
|
||||
display: 'flex',
|
||||
color: cssVarV2('aI/errorText'),
|
||||
});
|
||||
|
||||
export const reloadButton = style({
|
||||
display: 'flex',
|
||||
alignItems: 'center',
|
||||
padding: '0 4px',
|
||||
gap: '4px',
|
||||
border: 'none',
|
||||
background: 'none',
|
||||
cursor: 'pointer',
|
||||
outline: 'none',
|
||||
color: cssVarV2('button/primary'),
|
||||
fontSize: cssVar('fontSm'),
|
||||
fontWeight: 500,
|
||||
});
|
||||
|
||||
export const reloadButtonIcon = style({
|
||||
fontSize: 16,
|
||||
});
|
||||
|
||||
@@ -16,7 +16,9 @@ import { AudioAttachmentService } from '@affine/core/modules/media/services/audi
|
||||
import { Trans, useI18n } from '@affine/i18n';
|
||||
import track from '@affine/track';
|
||||
import type { AttachmentBlockModel } from '@blocksuite/affine/model';
|
||||
import { ResetIcon } from '@blocksuite/icons/rc';
|
||||
import { useLiveData, useService } from '@toeverything/infra';
|
||||
import bytes from 'bytes';
|
||||
import { useCallback, useEffect, useMemo, useState } from 'react';
|
||||
|
||||
import type { AttachmentViewerProps } from '../types';
|
||||
@@ -31,6 +33,8 @@ const AttachmentAudioPlayer = ({ block }: { block: AudioAttachmentBlock }) => {
|
||||
const [preflightChecking, setPreflightChecking] = useState(false);
|
||||
const transcribing =
|
||||
useLiveData(block.transcriptionJob.transcribing$) || preflightChecking;
|
||||
const loading = useLiveData(audioMedia.loading$);
|
||||
const loadingError = useLiveData(audioMedia.loadError$);
|
||||
const error = useLiveData(block.transcriptionJob.error$);
|
||||
const transcribed = useLiveData(block.hasTranscription$);
|
||||
const handleClick = useCallback((e: React.MouseEvent<HTMLDivElement>) => {
|
||||
@@ -65,6 +69,10 @@ const AttachmentAudioPlayer = ({ block }: { block: AudioAttachmentBlock }) => {
|
||||
[audioMedia]
|
||||
);
|
||||
|
||||
const reload = useCallback(() => {
|
||||
audioMedia?.revalidateBuffer();
|
||||
}, [audioMedia]);
|
||||
|
||||
const t = useI18n();
|
||||
|
||||
const enableAi = useEnableAI();
|
||||
@@ -179,17 +187,30 @@ const AttachmentAudioPlayer = ({ block }: { block: AudioAttachmentBlock }) => {
|
||||
return inner;
|
||||
}, [enableAi, transcribing, handleNotesClick, t]);
|
||||
|
||||
const sizeEntry = useMemo(() => {
|
||||
if (error) {
|
||||
const descriptionEntry = useMemo(() => {
|
||||
if (loadingError) {
|
||||
return (
|
||||
<>
|
||||
<div className={styles.error}>{loadingError.message}</div>
|
||||
<button className={styles.reloadButton} onClick={reload}>
|
||||
<ResetIcon className={styles.reloadButtonIcon} />
|
||||
Reload
|
||||
</button>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
if (!loading && error) {
|
||||
return <div className={styles.error}>{error.message}</div>;
|
||||
}
|
||||
return block.props.props.size;
|
||||
}, [error, block.props.props.size]);
|
||||
|
||||
return <>{bytes(block.props.props.size)}</>;
|
||||
}, [loading, loadingError, error, reload, block.props.props.size]);
|
||||
|
||||
return (
|
||||
<AudioPlayer
|
||||
name={block.props.props.name}
|
||||
size={sizeEntry}
|
||||
description={descriptionEntry}
|
||||
loading={stats.duration === 0}
|
||||
playbackState={playbackState?.state || 'idle'}
|
||||
waveform={stats.waveform}
|
||||
@@ -234,8 +255,8 @@ const useAttachmentMediaBlock = (model: AttachmentBlockModel) => {
|
||||
return audioAttachmentBlock;
|
||||
};
|
||||
|
||||
export const AudioBlockEmbedded = (props: AttachmentViewerProps) => {
|
||||
const audioAttachmentBlock = useAttachmentMediaBlock(props.model);
|
||||
export const AudioBlockEmbedded = ({ model }: AttachmentViewerProps) => {
|
||||
const audioAttachmentBlock = useAttachmentMediaBlock(model);
|
||||
const transcriptionBlock = useLiveData(
|
||||
audioAttachmentBlock?.transcriptionBlock$
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user