refactor: サウンド関連の設定をpizzaxに移行 (#8105)

* enhane: unison-reloadに指定したパスに移動できるように

* null

* null

* feat: ログインするアカウントのIDをクエリ文字列で指定する機能

* null

* await?

* rename

* rename

* Update read.ts

* merge

* get-note-summary

* fix

* swパッケージに

* add missing packages

* fix getNoteSummary

* add webpack-cli

* ✌️

* remove plugins

* sw-inject分離したがテストしてない

* fix notification.vue

* remove a blank line

* disconnect intersection observer

* disconnect2

* fix notification.vue

* remove a blank line

* disconnect intersection observer

* disconnect2

* fix

* ✌️

* clean up config

* typesを戻した

* backend/src/web/index.ts

* notification-badges

* add scripts

* change create-notification.ts

* Update packages/client/src/components/notification.vue

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>

* disconnect

* oops

* Failed to load the script unexpectedly回避
sw.jsとlib.tsを分離してみた

* truncate notification

* Update packages/client/src/ui/_common_/common.vue

Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>

* clean up

* clean up

* refactor

* キャッシュ対策

* Truncate push notification message

* fix

* wip

* clean up

* migration

* migration

* comment

* move soundConfigStore

* ✌️

* clean up

* クライアントがあったらストリームに接続しているということなので通知しない判定の位置を修正

* components/drive-file-thumbnail.vue

* components/drive-select-dialog.vue

* components/drive-window.vue

* merge

* fix

* remove reversi setting

* Service Workerのビルドにesbuildを使うようにする

* return createEmptyNotification()

* fix

* fix

* i18n.ts

* update

* ✌️

* remove ts-loader

* fix

* fix

* enhance: Service Workerを常に登録するように

* pollEnded

* pollEnded

* URLをsw.jsに戻す

* clean up

* clean up

* update sounds.vue

* update

* fix type

* ✌️

* ;v;

---------

Co-authored-by: Acid Chicken (硫酸鶏) <root@acid-chicken.com>
Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
tamaina 2023-04-12 10:39:57 +09:00 committed by GitHub
parent f9720e0e6e
commit 0db88a5a3b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
4 changed files with 80 additions and 43 deletions

View file

@ -31,7 +31,7 @@
import { onMounted } from 'vue'; import { onMounted } from 'vue';
import * as misskey from 'misskey-js'; import * as misskey from 'misskey-js';
import VuePlyr from 'vue-plyr'; import VuePlyr from 'vue-plyr';
import { ColdDeviceStorage } from '@/store'; import { soundConfigStore } from '@/scripts/sound';
import 'vue-plyr/dist/vue-plyr.css'; import 'vue-plyr/dist/vue-plyr.css';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
@ -44,11 +44,11 @@ const audioEl = $shallowRef<HTMLAudioElement | null>();
let hide = $ref(true); let hide = $ref(true);
function volumechange() { function volumechange() {
if (audioEl) ColdDeviceStorage.set('mediaVolume', audioEl.volume); if (audioEl) soundConfigStore.set('mediaVolume', audioEl.volume);
} }
onMounted(() => { onMounted(() => {
if (audioEl) audioEl.volume = ColdDeviceStorage.get('mediaVolume'); if (audioEl) audioEl.volume = soundConfigStore.state.mediaVolume;
}); });
</script> </script>

View file

@ -7,7 +7,7 @@
<FormSection> <FormSection>
<template #label>{{ i18n.ts.sounds }}</template> <template #label>{{ i18n.ts.sounds }}</template>
<div class="_gaps_s"> <div class="_gaps_s">
<MkFolder v-for="type in Object.keys(sounds)" :key="type"> <MkFolder v-for="type in soundsKeys" :key="type">
<template #label>{{ i18n.t('_sfx.' + type) }}</template> <template #label>{{ i18n.t('_sfx.' + type) }}</template>
<template #suffix>{{ sounds[type].type ?? i18n.ts.none }}</template> <template #suffix>{{ sounds[type].type ?? i18n.ts.none }}</template>
@ -21,51 +21,44 @@
</template> </template>
<script lang="ts" setup> <script lang="ts" setup>
import { computed, ref } from 'vue'; import { Ref, computed, ref } from 'vue';
import XSound from './sounds.sound.vue'; import XSound from './sounds.sound.vue';
import MkRange from '@/components/MkRange.vue'; import MkRange from '@/components/MkRange.vue';
import MkButton from '@/components/MkButton.vue'; import MkButton from '@/components/MkButton.vue';
import FormSection from '@/components/form/section.vue'; import FormSection from '@/components/form/section.vue';
import MkFolder from '@/components/MkFolder.vue'; import MkFolder from '@/components/MkFolder.vue';
import { ColdDeviceStorage } from '@/store'; import { soundConfigStore } from '@/scripts/sound';
import { i18n } from '@/i18n'; import { i18n } from '@/i18n';
import { definePageMetadata } from '@/scripts/page-metadata'; import { definePageMetadata } from '@/scripts/page-metadata';
const masterVolume = computed({ const masterVolume = computed(soundConfigStore.makeGetterSetter('sound_masterVolume'));
get: () => {
return ColdDeviceStorage.get('sound_masterVolume'); const soundsKeys = ['note', 'noteMy', 'notification', 'chat', 'chatBg', 'antenna', 'channel'] as const;
},
set: (value) => { const sounds = ref<Record<typeof soundsKeys[number], Ref<any>>>({
ColdDeviceStorage.set('sound_masterVolume', value); note: soundConfigStore.reactiveState.sound_note,
}, noteMy: soundConfigStore.reactiveState.sound_noteMy,
notification: soundConfigStore.reactiveState.sound_notification,
chat: soundConfigStore.reactiveState.sound_chat,
chatBg: soundConfigStore.reactiveState.sound_chatBg,
antenna: soundConfigStore.reactiveState.sound_antenna,
channel: soundConfigStore.reactiveState.sound_channel,
}); });
const volumeIcon = computed(() => masterVolume.value === 0 ? 'ti ti-volume-3' : 'ti ti-volume'); async function updated(type: keyof typeof sounds.value, sound) {
const sounds = ref({
note: ColdDeviceStorage.get('sound_note'),
noteMy: ColdDeviceStorage.get('sound_noteMy'),
notification: ColdDeviceStorage.get('sound_notification'),
chat: ColdDeviceStorage.get('sound_chat'),
chatBg: ColdDeviceStorage.get('sound_chatBg'),
antenna: ColdDeviceStorage.get('sound_antenna'),
channel: ColdDeviceStorage.get('sound_channel'),
});
async function updated(type, sound) {
const v = { const v = {
type: sound.type, type: sound.type,
volume: sound.volume, volume: sound.volume,
}; };
ColdDeviceStorage.set('sound_' + type, v); soundConfigStore.set(`sound_${type}`, v);
sounds.value[type] = v; sounds.value[type] = v;
} }
function reset() { function reset() {
for (const sound of Object.keys(sounds.value)) { for (const sound of Object.keys(sounds.value) as Array<keyof typeof sounds.value>) {
const v = ColdDeviceStorage.default['sound_' + sound]; const v = soundConfigStore.def[`sound_${sound}`].default;
ColdDeviceStorage.set('sound_' + sound, v); soundConfigStore.set(`sound_${sound}`, v);
sounds.value[sound] = v; sounds.value[sound] = v;
} }
} }

View file

@ -1,4 +1,56 @@
import { ColdDeviceStorage } from '@/store'; import { markRaw } from 'vue';
import { Storage } from '@/pizzax';
export const soundConfigStore = markRaw(new Storage('sound', {
mediaVolume: {
where: 'device',
default: 0.5
},
sound_masterVolume: {
where: 'device',
default: 0.3
},
sound_note: {
where: 'account',
default: { type: 'syuilo/n-aec', volume: 1 }
},
sound_noteMy: {
where: 'account',
default: { type: 'syuilo/n-cea-4va', volume: 1 }
},
sound_notification: {
where: 'account',
default: { type: 'syuilo/n-ea', volume: 1 }
},
sound_chat: {
where: 'account',
default: { type: 'syuilo/pope1', volume: 1 }
},
sound_chatBg: {
where: 'account',
default: { type: 'syuilo/waon', volume: 1 }
},
sound_antenna: {
where: 'account',
default: { type: 'syuilo/triple', volume: 1 }
},
sound_channel: {
where: 'account',
default: { type: 'syuilo/square-pico', volume: 1 }
},
}));
await soundConfigStore.ready;
//#region サウンドのColdDeviceStorage => indexedDBのマイグレーション
for (const target of Object.keys(soundConfigStore.state) as Array<keyof typeof soundConfigStore.state>) {
const value = localStorage.getItem(`miux:${target}`);
if (value) {
soundConfigStore.set(target, JSON.parse(value) as typeof soundConfigStore.def[typeof target]['default']);
localStorage.removeItem(`miux:${target}`);
}
}
//#endregion
const cache = new Map<string, HTMLAudioElement>(); const cache = new Map<string, HTMLAudioElement>();
@ -67,19 +119,20 @@ export function getAudio(file: string, useCache = true): HTMLAudioElement {
} }
export function setVolume(audio: HTMLAudioElement, volume: number): HTMLAudioElement { export function setVolume(audio: HTMLAudioElement, volume: number): HTMLAudioElement {
const masterVolume = ColdDeviceStorage.get('sound_masterVolume'); const masterVolume = soundConfigStore.state.sound_masterVolume;
audio.volume = masterVolume - ((1 - volume) * masterVolume); audio.volume = masterVolume - ((1 - volume) * masterVolume);
return audio; return audio;
} }
export function play(type: 'noteMy' | 'note' | 'antenna' | 'channel' | 'notification') { export function play(type: 'noteMy' | 'note' | 'antenna' | 'channel' | 'notification') {
const sound = ColdDeviceStorage.get(`sound_${type}`); const sound = soundConfigStore.state[`sound_${type}`];
if (_DEV_) console.log('play', type, sound);
if (sound.type == null) return; if (sound.type == null) return;
playFile(sound.type, sound.volume); playFile(sound.type, sound.volume);
} }
export function playFile(file: string, volume: number) { export function playFile(file: string, volume: number) {
const masterVolume = ColdDeviceStorage.get('sound_masterVolume'); const masterVolume = soundConfigStore.state.sound_masterVolume;
if (masterVolume === 0) return; if (masterVolume === 0) return;
const audio = setVolume(getAudio(file), volume); const audio = setVolume(getAudio(file), volume);

View file

@ -343,15 +343,6 @@ export class ColdDeviceStorage {
darkTheme, darkTheme,
syncDeviceDarkMode: true, syncDeviceDarkMode: true,
plugins: [] as Plugin[], plugins: [] as Plugin[],
mediaVolume: 0.5,
sound_masterVolume: 0.5,
sound_note: { type: 'syuilo/n-eca', volume: 0.5 },
sound_noteMy: { type: 'syuilo/n-cea-4va', volume: 0.5 },
sound_notification: { type: 'syuilo/n-ea', volume: 0.5 },
sound_chat: { type: 'syuilo/pope1', volume: 0.5 },
sound_chatBg: { type: 'syuilo/waon', volume: 0.5 },
sound_antenna: { type: 'syuilo/triple', volume: 0.5 },
sound_channel: { type: 'syuilo/square-pico', volume: 0.5 },
}; };
public static watchers: Watcher[] = []; public static watchers: Watcher[] = [];