Skip to content

Commit

Permalink
(refactor) better types
Browse files Browse the repository at this point in the history
  • Loading branch information
kakkokari-gtyih committed Nov 26, 2023
1 parent acd87bb commit 3a9e671
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 36 deletions.
13 changes: 8 additions & 5 deletions packages/frontend/src/pages/settings/sounds.sound.vue
Original file line number Diff line number Diff line change
Expand Up @@ -110,18 +110,21 @@ function selectSound(ev) {
}
function listen() {
if (type.value === 'driveFile' && !fileUrl.value) {
if (type.value === 'driveFile' && (!fileUrl.value || !fileId.value)) {
os.alert({
type: 'warning',
text: i18n.ts._soundSettings.driveFileWarn,
});
return;
}
playFile({
soundType: type.value,
fileUrl: fileUrl.value,
fileId: fileId.value,
playFile(type.value === 'driveFile' ? {
type: 'driveFile',
fileId: fileId.value as string,
fileUrl: fileUrl.value as string,
volume: volume.value,
} : {
type: type.value,
volume: volume.value,
});
}
Expand Down
66 changes: 40 additions & 26 deletions packages/frontend/src/scripts/sound.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
* SPDX-License-Identifier: AGPL-3.0-only
*/

import type { SoundStore } from '@/store.js';
import { defaultStore } from '@/store.js';
import * as os from '@/os.js';

Expand Down Expand Up @@ -75,37 +76,43 @@ export const operationTypes = [
'reaction',
] as const;

/** サウンドの種類 */
export type SoundType = typeof soundsTypes[number];

/** スプライトの種類 */
export type OperationType = typeof operationTypes[number];

export async function loadAudio(options: { soundType: SoundType, fileId?: string, fileUrl?: string, useCache?: boolean; }) {
/**
* 音声を読み込む
* @param soundStore サウンド設定
* @param options `useCache`: デフォルトは`true` 一度再生した音声はキャッシュする
*/
export async function loadAudio(soundStore: SoundStore, options?: { useCache?: boolean; }) {
if (_DEV_) console.log('loading audio. opts:', options);
if (options.soundType === null || (options.soundType === 'driveFile' && !options.fileUrl)) {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-condition
if (soundStore.type === null || (soundStore.type === 'driveFile' && !soundStore.fileUrl)) {
return;
}
if (options.useCache ?? true) {
if (options.soundType === 'driveFile' && options.fileId && cache.has(options.fileId)) {
if (options?.useCache ?? true) {
if (soundStore.type === 'driveFile' && cache.has(soundStore.fileId)) {
if (_DEV_) console.log('use cache');
return cache.get(options.fileId)!;
} else if (cache.has(options.soundType)) {
return cache.get(soundStore.fileId) as AudioBuffer;
} else if (cache.has(soundStore.type)) {
if (_DEV_) console.log('use cache');
return cache.get(options.soundType)!;
return cache.get(soundStore.type) as AudioBuffer;
}
}

let response;

if (options.soundType === 'driveFile') {
if (!options.fileUrl) return;
if (soundStore.type === 'driveFile') {
try {
response = await fetch(options.fileUrl);
response = await fetch(soundStore.fileUrl);
} catch (err) {
try {
// URLが変わっている可能性があるのでドライブ側からURLを取得するフォールバック
if (!options.fileId) return;
const apiRes = await os.api('drive/files/show', {
fileId: options.fileId,
fileId: soundStore.fileId,
});
response = await fetch(apiRes.url);
} catch (fbErr) {
Expand All @@ -115,7 +122,7 @@ export async function loadAudio(options: { soundType: SoundType, fileId?: string
}
} else {
try {
response = await fetch(`/client-assets/sounds/${options.soundType}.mp3`);
response = await fetch(`/client-assets/sounds/${soundStore.type}.mp3`);
} catch (err) {
return;
}
Expand All @@ -124,40 +131,43 @@ export async function loadAudio(options: { soundType: SoundType, fileId?: string
const arrayBuffer = await response.arrayBuffer();
const audioBuffer = await ctx.decodeAudioData(arrayBuffer);

if (options.useCache ?? true) {
if (options.soundType === 'driveFile' && options.fileId) {
cache.set(options.fileId, audioBuffer);
if (options?.useCache ?? true) {
if (soundStore.type === 'driveFile') {
cache.set(soundStore.fileId, audioBuffer);
} else {
cache.set(options.soundType, audioBuffer);
cache.set(soundStore.type, audioBuffer);
}
}

return audioBuffer;
}

/**
* 既定のスプライトを再生する
* @param type スプライトの種類を指定
*/
export function play(type: OperationType) {
const sound = defaultStore.state[`sound_${type}`];
if (_DEV_) console.log('play', type, sound);
if (sound.type == null || !canPlay) return;

canPlay = false;
playFile({
soundType: sound.type,
fileId: sound.fileId,
fileUrl: sound.fileUrl,
volume: sound.volume,
}).then(() => {
playFile(sound).then(() => {
// ごく短時間に音が重複しないように
setTimeout(() => {
canPlay = true;
}, 25);
});
}

export async function playFile(options: { soundType: SoundType, fileId?: string, fileUrl?: string, volume: number }) {
const buffer = await loadAudio(options);
/**
* サウンド設定形式で指定された音声を再生する
* @param soundStore サウンド設定
*/
export async function playFile(soundStore: SoundStore) {
const buffer = await loadAudio(soundStore);
if (!buffer) return;
createSourceNode(buffer, options.volume)?.start();
createSourceNode(buffer, soundStore.volume)?.start();
}

export function createSourceNode(buffer: AudioBuffer, volume: number) : AudioBufferSourceNode | null {
Expand All @@ -176,6 +186,10 @@ export function createSourceNode(buffer: AudioBuffer, volume: number) : AudioBuf
return soundSource;
}

/**
* 音声の長さをミリ秒で取得する
* @param file ファイルのURL(ドライブIDではない)
*/
export async function getSoundDuration(file: string): Promise<number> {
const audioEl = document.createElement('audio');
audioEl.src = file;
Expand Down
13 changes: 8 additions & 5 deletions packages/frontend/src/store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,11 +36,14 @@ interface PageViewInterruptor {
handler: (page: Misskey.entities.Page) => unknown;
}

export interface SoundStore {
type: SoundType,
fileId?: string,
fileUrl?: string,
volume: number,
export type SoundStore = {
type: Exclude<SoundType, 'driveFile'>;
volume: number;
} | {
type: 'driveFile';
fileId: string;
fileUrl: string;
volume: number;
}

export const postFormActions: PostFormAction[] = [];
Expand Down

0 comments on commit 3a9e671

Please sign in to comment.