misskey/packages/frontend/src/pages/settings/sounds.sound.vue
かっこかり 0d7f9308cc
enhance(frontend): バブルゲームの諸々を修正・改良2 (#12948)
* (fix) ゲームが正常に終了するように

* (enhance) 効果音の音量を設定可能に

* (add) store

* (add) スクショにロゴの透かしを入れる

* Update packages/frontend/src/pages/drop-and-fusion.vue

Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>

* tweak

* tweak

* tweak

* tweak

* Update drop-and-fusion.vue

* tweak

* tweak

---------

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
Co-authored-by: まっちゃとーにゅ <17376330+u1-liquid@users.noreply.github.com>
2024-01-09 13:25:33 +09:00

175 lines
4.3 KiB
Vue

<!--
SPDX-FileCopyrightText: syuilo and other misskey contributors
SPDX-License-Identifier: AGPL-3.0-only
-->
<template>
<div class="_gaps_m">
<MkSelect v-model="type">
<template #label>{{ i18n.ts.sound }}</template>
<option v-for="x in soundsTypes" :key="x ?? 'null'" :value="x">{{ getSoundTypeName(x) }}</option>
</MkSelect>
<div v-if="type === '_driveFile_'" :class="$style.fileSelectorRoot">
<MkButton :class="$style.fileSelectorButton" inline rounded primary @click="selectSound">{{ i18n.ts.selectFile }}</MkButton>
<div :class="['_nowrap', !fileUrl && $style.fileNotSelected]">{{ friendlyFileName }}</div>
</div>
<MkRange v-model="volume" :min="0" :max="1" :step="0.05" :textConverter="(v) => `${Math.floor(v * 100)}%`">
<template #label>{{ i18n.ts.volume }}</template>
</MkRange>
<div class="_buttons">
<MkButton inline @click="listen"><i class="ti ti-player-play"></i> {{ i18n.ts.listen }}</MkButton>
<MkButton inline primary @click="save"><i class="ti ti-check"></i> {{ i18n.ts.save }}</MkButton>
</div>
</div>
</template>
<script lang="ts" setup>
import { ref, computed } from 'vue';
import type { SoundType } from '@/scripts/sound.js';
import MkSelect from '@/components/MkSelect.vue';
import MkButton from '@/components/MkButton.vue';
import MkRange from '@/components/MkRange.vue';
import { i18n } from '@/i18n.js';
import * as os from '@/os.js';
import { misskeyApi } from '@/scripts/misskey-api.js';
import { playMisskeySfxFile, soundsTypes, getSoundDuration } from '@/scripts/sound.js';
import { selectFile } from '@/scripts/select-file.js';
const props = defineProps<{
type: SoundType;
fileId?: string;
fileUrl?: string;
volume: number;
}>();
const emit = defineEmits<{
(ev: 'update', result: { type: SoundType; fileId?: string; fileUrl?: string; volume: number; }): void;
}>();
const type = ref<SoundType>(props.type);
const fileId = ref(props.fileId);
const fileUrl = ref(props.fileUrl);
const fileName = ref<string>('');
const volume = ref(props.volume);
if (type.value === '_driveFile_' && fileId.value) {
const apiRes = await misskeyApi('drive/files/show', {
fileId: fileId.value,
});
fileName.value = apiRes.name;
}
function getSoundTypeName(f: SoundType): string {
switch (f) {
case null:
return i18n.ts.none;
case '_driveFile_':
return i18n.ts._soundSettings.driveFile;
default:
return f;
}
}
const friendlyFileName = computed<string>(() => {
if (fileName.value) {
return fileName.value;
}
if (fileUrl.value) {
return fileUrl.value;
}
return i18n.ts._soundSettings.driveFileWarn;
});
function selectSound(ev) {
selectFile(ev.currentTarget ?? ev.target, i18n.ts._soundSettings.driveFile).then(async (file) => {
if (!file.type.startsWith('audio')) {
os.alert({
type: 'warning',
title: i18n.ts._soundSettings.driveFileTypeWarn,
text: i18n.ts._soundSettings.driveFileTypeWarnDescription,
});
return;
}
const duration = await getSoundDuration(file.url);
if (duration >= 2000) {
const { canceled } = await os.confirm({
type: 'warning',
title: i18n.ts._soundSettings.driveFileDurationWarn,
text: i18n.ts._soundSettings.driveFileDurationWarnDescription,
okText: i18n.ts.continue,
cancelText: i18n.ts.cancel,
});
if (canceled) return;
}
fileUrl.value = file.url;
fileName.value = file.name;
fileId.value = file.id;
});
}
function listen() {
if (type.value === '_driveFile_' && (!fileUrl.value || !fileId.value)) {
os.alert({
type: 'warning',
text: i18n.ts._soundSettings.driveFileWarn,
});
return;
}
playMisskeySfxFile(type.value === '_driveFile_' ? {
type: '_driveFile_',
fileId: fileId.value as string,
fileUrl: fileUrl.value as string,
volume: volume.value,
} : {
type: type.value,
volume: volume.value,
});
}
function save() {
if (type.value === '_driveFile_' && !fileUrl.value) {
os.alert({
type: 'warning',
text: i18n.ts._soundSettings.driveFileWarn,
});
return;
}
if (type.value !== '_driveFile_') {
fileUrl.value = undefined;
fileName.value = '';
fileId.value = undefined;
}
emit('update', {
type: type.value,
fileId: fileId.value,
fileUrl: fileUrl.value,
volume: volume.value,
});
os.success();
}
</script>
<style module>
.fileSelectorRoot {
display: flex;
align-items: center;
gap: 8px;
}
.fileSelectorButton {
flex-shrink: 0;
}
.fileNotSelected {
font-weight: 700;
color: var(--infoWarnFg);
}
</style>