Skip to content

Commit

Permalink
Merge pull request #126 from mebtte/beta
Browse files Browse the repository at this point in the history
check usability of music file
  • Loading branch information
MEBTTE committed Apr 14, 2024
2 parents ddce75e + c7536ba commit 9409f2a
Show file tree
Hide file tree
Showing 8 changed files with 99 additions and 50 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ const ASSET_TYPE_MAP_OPTION: Record<

export default async (ctx: Context) => {
const { field, file } = await parseFormdata<'assetType', 'asset'>(ctx.req);
// @ts-expect-error
// @ts-expect-error: known type
const assetType: AssetType | undefined = field.assetType
? field.assetType[0]
: undefined;
Expand All @@ -75,12 +75,12 @@ export default async (ctx: Context) => {
return ctx.except(ExceptionCode.WRONG_PARAMETER);
}

const { maxSize, acceptTypes } = ASSET_TYPE_MAP[assetType];
const { maxSize, acceptType } = ASSET_TYPE_MAP[assetType];
if (asset.size > maxSize) {
return ctx.except(ExceptionCode.ASSET_OVERSIZE);
}
const ft = await fileType.fromFile(asset.path);
if (!ft || !acceptTypes.includes(ft.mime)) {
if (!ft || !new Set(Object.values(acceptType).flat()).has(ft.mime)) {
return ctx.except(ExceptionCode.WRONG_ASSET_TYPE);
}

Expand Down
7 changes: 5 additions & 2 deletions apps/pwa/src/components/file_select.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import styled, { css } from 'styled-components';
import upperCaseFirstLetter from '@/style/upper_case_first_letter';
import { CSSVariable } from '../global_style';
import useEvent from '../utils/use_event';
import selectFile from '../utils/select_file';
Expand All @@ -16,6 +15,10 @@ const Style = styled.div<{ disabled: boolean }>`
user-select: none;
word-break: break-all;
> .placeholder {
color: ${CSSVariable.TEXT_COLOR_SECONDARY};
}
&:active {
border-color: ${CSSVariable.COLOR_PRIMARY};
border-style: solid;
Expand Down Expand Up @@ -60,7 +63,7 @@ function FileSelect({

return (
<Style onClick={onSelectFile} disabled={disabled}>
{value ? value.name : placeholder}
{value ? value.name : <span className="placeholder">{placeholder}</span>}
</Style>
);
}
Expand Down
1 change: 1 addition & 0 deletions apps/pwa/src/i18n/en_us.ts
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,5 @@ export default {
feedback: 'feedback',
fork_from_these_musics: 'fork from these musics',
forked_by_these_musics: 'forked by these musics',
can_not_play_audio_file: 'this file can not be played',
};
1 change: 1 addition & 0 deletions apps/pwa/src/i18n/zh_hans.ts
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,7 @@ const zhCN: {
feedback: '反馈',
fork_from_these_musics: '二次创作自以下音乐',
forked_by_these_musics: '被以下音乐二次创作',
can_not_play_audio_file: '音乐文件无法被播放',
};

export default zhCN;
15 changes: 11 additions & 4 deletions apps/pwa/src/pages/player/music_drawer/edit_menu.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ import playerEventemitter, {
} from '../eventemitter';
import MusicInfo from '../components/music_info';
import MissingSinger from '../components/missing_singer';
import upperCaseFirstLetter from '#/utils/upper_case_first_letter';

interface Singer {
id: string;
Expand Down Expand Up @@ -378,10 +379,16 @@ function EditMenu({ music }: { music: MusicDetail }) {
dialog.fileSelect({
title: t('modify_file_of_music'),
label: t('file_of_music'),
acceptTypes: ASSET_TYPE_MAP[AssetType.MUSIC].acceptTypes,
placeholder: t(
'one_of_formats',
ASSET_TYPE_MAP[AssetType.MUSIC].acceptTypes.join(','),
acceptTypes: Object.values(
ASSET_TYPE_MAP[AssetType.MUSIC].acceptType,
).flat(),
placeholder: upperCaseFirstLetter(
t(
'one_of_formats',
Object.keys(ASSET_TYPE_MAP[AssetType.MUSIC].acceptType).join(
'/',
),
),
),
onConfirm: async (file) => {
if (!file) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ import playerEventemitter, {
} from '../../../eventemitter';
import { Singer } from './constants';
import upperCaseFirstLetter from '#/utils/upper_case_first_letter';
import { base64ToCover } from './utils';
import { base64ToCover, canAudioPlay } from './utils';

const maskProps: { style: CSSProperties } = {
style: { zIndex: ZIndex.DIALOG },
Expand Down Expand Up @@ -90,33 +90,43 @@ function CreateMusicDialog() {
setMusicType(option.actualValue);

const [asset, setAsset] = useState<File | null>(null);
const onAssetChange = (a) => {
const onAssetChange = (a: File | null) => {
setAsset(a);

getMusicFileMetadata(a)
.then((metadata) => {
const { title, artist } = metadata;
if (!name && title) {
setName(title);
if (a) {
canAudioPlay(a).then((canPlay) => {
if (!canPlay) {
setAsset(null);
return notice.error(t('can_not_play_audio_file'));
}
if (!singerList.length && artist) {
searchSingerRequest({
keyword: artist,
page: 1,
pageSize: 10,
requestMinimalDuration: 0,
})
.then((data) => {
if (!singerList.length) {
setSingerList(data.singerList);
}
});
getMusicFileMetadata(a)
.then((metadata) => {
const { title, artist } = metadata;
if (!name && title) {
setName(title);
}
if (!singerList.length && artist) {
searchSingerRequest({
keyword: artist,
page: 1,
pageSize: 10,
requestMinimalDuration: 0,
})
.catch((error) => logger.error(error, 'Failed to search singers'));
}
})
.catch((error) =>
logger.error(error, "Failed to parse music's metadata"),
);
.then((data) => {
if (!singerList.length) {
setSingerList(data.singerList);
}
})
.catch((error) =>
logger.error(error, 'Failed to search singers'),
);
}
})
.catch((error) =>
logger.error(error, "Failed to parse music's metadata"),
);
}
};

const [loading, setLoading] = useState(false);
Expand Down Expand Up @@ -229,11 +239,13 @@ function CreateMusicDialog() {
value={asset}
onChange={onAssetChange}
disabled={loading}
acceptTypes={ASSET_TYPE_MAP[AssetType.MUSIC].acceptTypes}
acceptTypes={Object.values(
ASSET_TYPE_MAP[AssetType.MUSIC].acceptType,
).flat()}
placeholder={upperCaseFirstLetter(
`${t('empty_file_warning')}, ${t(
'supported_formats',
)} ${ASSET_TYPE_MAP[AssetType.MUSIC].acceptTypes.join(', ')}`,
`${t('supported_formats')}: ${Object.keys(
ASSET_TYPE_MAP[AssetType.MUSIC].acceptType,
).join('/')}`,
)}
/>
</Label>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,18 @@ export async function base64ToCover(base64: string) {
canvas.toBlob((blob) => resolve(blob!), 'image/jpeg', 0.8),
);
}

export function canAudioPlay(file: File) {
const url = URL.createObjectURL(file);
const audio = new Audio();
return new Promise<boolean>((resolve) => {
audio.muted = true;
audio.autoplay = true;
audio.onplay = () => resolve(true);
audio.onerror = () => resolve(false);
audio.src = url;
}).finally(() => {
audio.pause();
URL.revokeObjectURL(url);
});
}
36 changes: 23 additions & 13 deletions shared/constants/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,35 +25,45 @@ export const ASSET_TYPES = Object.values(AssetType);
export const ASSET_TYPE_MAP: Record<
AssetType,
{
acceptTypes: string[];
acceptType: Record<string, string[]>;
maxSize: number;
}
> = {
[AssetType.SINGER_AVATAR]: {
acceptTypes: ['image/jpeg'],
acceptType: {
jpg: ['image/jpeg'],
jpeg: ['image/jpeg'],
},
maxSize: 1024 * 1024 * 2,
},
[AssetType.MUSICBILL_COVER]: {
acceptTypes: ['image/jpeg'],
acceptType: {
jpg: ['image/jpeg'],
jpeg: ['image/jpeg'],
},
maxSize: 1024 * 1024 * 2,
},
[AssetType.MUSIC_COVER]: {
acceptTypes: ['image/jpeg'],
acceptType: {
jpg: ['image/jpeg'],
jpeg: ['image/jpeg'],
},
maxSize: 1024 * 1024 * 2,
},
[AssetType.USER_AVATAR]: {
acceptTypes: ['image/jpeg'],
acceptType: {
jpg: ['image/jpeg'],
jpeg: ['image/jpeg'],
},
maxSize: 1024 * 1024 * 2,
},
[AssetType.MUSIC]: {
acceptTypes: [
'audio/mpeg', // .mp3
'audio/mp4', // .mp4
'audio/flac', // .flac
'audio/x-flac', // .flac
'audio/m4a', // .m4a
'audio/x-m4a', // .m4a
],
acceptType: {
mp3: ['audio/mpeg'],
flac: ['audio/flac', 'audio/x-flac'],
m4a: ['audio/m4a', 'audio/x-m4a'],
mp4: ['audio/mp4', 'video/mp4'],
},
maxSize: 1024 * 1024 * 200,
},
};
Expand Down

0 comments on commit 9409f2a

Please sign in to comment.