Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix/enhance(frontend): 映像・音声周りの改修 #13206

Merged
merged 23 commits into from
Mar 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
274f0cf
enhance(frontend): 映像・音声周りの改修
kakkokari-gtyih Feb 8, 2024
45aa257
fix
kakkokari-gtyih Feb 8, 2024
bdaacb6
fix design
kakkokari-gtyih Feb 8, 2024
6e5722c
fix lint
kakkokari-gtyih Feb 8, 2024
498e94f
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Feb 9, 2024
91404ba
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Feb 16, 2024
3a6b2ab
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Feb 23, 2024
4cc7eab
キーボードショートカットを整備
kakkokari-gtyih Feb 23, 2024
ee2e5e2
Update Changelog
kakkokari-gtyih Feb 23, 2024
0bbe05f
fix
kakkokari-gtyih Feb 23, 2024
01848c2
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Mar 4, 2024
4ac797b
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Mar 7, 2024
024a9f4
feat: ループ再生
kakkokari-gtyih Mar 7, 2024
00eb189
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Mar 7, 2024
18af6a3
ネイティブの動作と同期されるように
kakkokari-gtyih Mar 7, 2024
53d5c0d
Merge branch 'tempfix-13101' of https://github.com/kakkokari-gtyih/mi…
kakkokari-gtyih Mar 7, 2024
635aa03
Update Changelog
kakkokari-gtyih Mar 7, 2024
873ccf8
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Mar 7, 2024
3f54b88
key指定を消す
kakkokari-gtyih Mar 7, 2024
bd7867f
Merge branch 'tempfix-13101' of https://github.com/kakkokari-gtyih/mi…
kakkokari-gtyih Mar 7, 2024
1c0c5e9
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Mar 17, 2024
a6331a6
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Mar 25, 2024
cac50bd
Merge branch 'develop' into tempfix-13101
kakkokari-gtyih Mar 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
- Enhance: ページのデザインを変更
- Enhance: 2要素認証(ワンタイムパスワード)の入力欄を改善
- Enhance: 「今日誕生日のフォロー中ユーザー」ウィジェットを手動でリロードできるように
- Enhance: 映像・音声の再生にブラウザのネイティブプレイヤーを使用できるように
- Enhance: 映像・音声の再生メニューに「再生速度」「ループ再生」「ピクチャインピクチャ」を追加
- Enhance: 映像・音声の再生にキーボードショートカットが使えるように
- Fix: 一部のページ内リンクが正しく動作しない問題を修正
- Fix: 周年の実績が閏年を考慮しない問題を修正
- Fix: ローカルURLのプレビューポップアップが左上に表示される
Expand Down
18 changes: 18 additions & 0 deletions locales/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4932,6 +4932,10 @@ export interface Locale extends ILocale {
* アプリを起動
*/
"launchApp": string;
/**
* 動画・音声の再生にブラウザのUIを使用する
*/
"useNativeUIForVideoAudioPlayer": string;
"_bubbleGame": {
/**
* 遊び方
Expand Down Expand Up @@ -9834,6 +9838,20 @@ export interface Locale extends ILocale {
*/
"summaryProxyDescription2": string;
};
"_mediaControls": {
/**
* ピクチャインピクチャ
*/
"pip": string;
/**
* 再生速度
*/
"playbackRate": string;
/**
* ループ再生
*/
"loop": string;
};
}
declare const locales: {
[lang: string]: Locale;
Expand Down
7 changes: 7 additions & 0 deletions locales/ja-JP.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1229,6 +1229,7 @@ notUsePleaseLeaveBlank: "使用しない場合は空欄にしてください"
useTotp: "ワンタイムパスワードを使う"
useBackupCode: "バックアップコードを使う"
launchApp: "アプリを起動"
useNativeUIForVideoAudioPlayer: "動画・音声の再生にブラウザのUIを使用する"

_bubbleGame:
howToPlay: "遊び方"
Expand Down Expand Up @@ -2619,3 +2620,9 @@ _urlPreviewSetting:
summaryProxy: "プレビューを生成するプロキシのエンドポイント"
summaryProxyDescription: "Misskey本体ではなく、サマリープロキシを使用してプレビューを生成します。"
summaryProxyDescription2: "プロキシには下記パラメータがクエリ文字列として連携されます。プロキシ側がこれらをサポートしない場合、設定値は無視されます。"

_mediaControls:
pip: "ピクチャインピクチャ"
playbackRate: "再生速度"
loop: "ループ再生"

112 changes: 111 additions & 1 deletion packages/frontend/src/components/MkMediaAudio.vue
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,15 @@ SPDX-License-Identifier: AGPL-3.0-only

<template>
<div
ref="playerEl"
v-hotkey="keymap"
tabindex="0"
:class="[
$style.audioContainer,
(audio.isSensitive && defaultStore.state.highlightSensitiveMedia) && $style.sensitive,
]"
@contextmenu.stop
@keydown.stop
>
<button v-if="hide" :class="$style.hidden" @click="hide = false">
<div :class="$style.hiddenTextWrapper">
Expand All @@ -18,6 +22,19 @@ SPDX-License-Identifier: AGPL-3.0-only
<span style="display: block;">{{ i18n.ts.clickToShow }}</span>
</div>
</button>

<div v-else-if="defaultStore.reactiveState.useNativeUIForVideoAudioPlayer.value" :class="$style.nativeAudioContainer">
<audio
ref="audioEl"
preload="metadata"
controls
:class="$style.nativeAudio"
@keydown.prevent
>
<source :src="audio.url">
</audio>
</div>

<div v-else :class="$style.audioControls">
<audio
ref="audioEl"
Expand Down Expand Up @@ -72,6 +89,41 @@ const props = defineProps<{
audio: Misskey.entities.DriveFile;
}>();

const keymap = {
'up': () => {
if (hasFocus() && audioEl.value) {
volume.value = Math.min(volume.value + 0.1, 1);
}
},
'down': () => {
if (hasFocus() && audioEl.value) {
volume.value = Math.max(volume.value - 0.1, 0);
}
},
'left': () => {
if (hasFocus() && audioEl.value) {
audioEl.value.currentTime = Math.max(audioEl.value.currentTime - 5, 0);
}
},
'right': () => {
if (hasFocus() && audioEl.value) {
audioEl.value.currentTime = Math.min(audioEl.value.currentTime + 5, audioEl.value.duration);
}
},
'space': () => {
if (hasFocus()) {
togglePlayPause();
}
},
};

// PlayerElもしくはその子要素にフォーカスがあるかどうか
function hasFocus() {
if (!playerEl.value) return false;
return playerEl.value === document.activeElement || playerEl.value.contains(document.activeElement);
}

const playerEl = shallowRef<HTMLDivElement>();
const audioEl = shallowRef<HTMLAudioElement>();

// eslint-disable-next-line vue/no-setup-props-destructure
Expand All @@ -85,6 +137,30 @@ function showMenu(ev: MouseEvent) {

menu = [
// TODO: 再生キューに追加
{
type: 'switch',
text: i18n.ts._mediaControls.loop,
icon: 'ti ti-repeat',
ref: loop,
},
{
type: 'radio',
text: i18n.ts._mediaControls.playbackRate,
icon: 'ti ti-clock-play',
ref: speed,
options: {
'0.25x': 0.25,
'0.5x': 0.5,
'0.75x': 0.75,
'1.0x': 1,
'1.25x': 1.25,
'1.5x': 1.5,
'2.0x': 2,
},
},
{
type: 'divider',
},
{
text: i18n.ts.hide,
icon: 'ti ti-eye-off',
Expand Down Expand Up @@ -147,6 +223,8 @@ const rangePercent = computed({
},
});
const volume = ref(.25);
const speed = ref(1);
const loop = ref(false); // TODO: ドライブファイルのフラグに置き換える
const bufferedEnd = ref(0);
const bufferedDataRatio = computed(() => {
if (!audioEl.value) return 0;
Expand Down Expand Up @@ -176,6 +254,7 @@ function toggleMute() {
}

let onceInit = false;
let mediaTickFrameId: number | null = null;
let stopAudioElWatch: () => void;

function init() {
Expand All @@ -195,8 +274,12 @@ function init() {
}

elapsedTimeMs.value = audioEl.value.currentTime * 1000;

if (audioEl.value.loop !== loop.value) {
loop.value = audioEl.value.loop;
}
}
window.requestAnimationFrame(updateMediaTick);
mediaTickFrameId = window.requestAnimationFrame(updateMediaTick);
}

updateMediaTick();
Expand Down Expand Up @@ -234,6 +317,14 @@ watch(volume, (to) => {
if (audioEl.value) audioEl.value.volume = to;
});

watch(speed, (to) => {
if (audioEl.value) audioEl.value.playbackRate = to;
});

watch(loop, (to) => {
if (audioEl.value) audioEl.value.loop = to;
});

onMounted(() => {
init();
});
Expand All @@ -252,6 +343,10 @@ onDeactivated(() => {
hide.value = (defaultStore.state.nsfw === 'force' || defaultStore.state.dataSaver.media) ? true : (props.audio.isSensitive && defaultStore.state.nsfw !== 'ignore');
stopAudioElWatch();
onceInit = false;
if (mediaTickFrameId) {
window.cancelAnimationFrame(mediaTickFrameId);
mediaTickFrameId = null;
}
});
</script>

Expand All @@ -262,6 +357,10 @@ onDeactivated(() => {
border: .5px solid var(--divider);
border-radius: var(--radius);
overflow: clip;

&:focus {
outline: none;
}
}

.sensitive {
Expand Down Expand Up @@ -367,4 +466,15 @@ onDeactivated(() => {
}
}
}

.nativeAudioContainer {
display: flex;
align-items: center;
padding: 6px;
}

.nativeAudio {
display: block;
width: 100%;
}
</style>
Loading
Loading