diff options
| author | おさむのひと <46447427+samunohito@users.noreply.github.com> | 2025-11-07 08:39:21 +0900 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-11-07 08:39:21 +0900 |
| commit | 729abbef621aea5b8b697644181915935b74bbf8 (patch) | |
| tree | 27545c0cfd3e6272dd40de2c77daf0d2adec3e6c /packages/frontend/src/pages | |
| parent | Bump version to 2025.11.0-alpha.1 (diff) | |
| download | misskey-729abbef621aea5b8b697644181915935b74bbf8.tar.gz misskey-729abbef621aea5b8b697644181915935b74bbf8.tar.bz2 misskey-729abbef621aea5b8b697644181915935b74bbf8.zip | |
feat: チャンネルミュートの実装 (#14105)
* add channel_muting table and entities
* add channel_muting services
* タイムライン取得処理への組み込み
* misskey-jsの型とインターフェース生成
* Channelスキーマにミュート情報を追加
* フロントエンドの実装
* 条件が逆だったのを修正
* 期限切れミュートを掃除する機能を実装
* TLの抽出条件調節
* 名前の変更と変更不要の差分をロールバック
* 修正漏れ
* isChannelRelatedの条件に誤りがあった
* [wip] テスト追加
* テストの追加と検出した不備の修正
* fix test
* fix CHANGELOG.md
* 通常はFTTにしておく
* 実装忘れ対応
* fix merge
* fix merge
* add channel tl test
* fix CHANGELOG.md
* remove unused import
* fix lint
* fix test
* fix favorite -> favorited
* exclude -> include
* fix CHANGELOG.md
* fix CHANGELOG.md
* maintenance
* fix CHANGELOG.md
* fix
* fix ci
* regenerate
* fix
* Revert "fix"
This reverts commit 699d50c6ec798777d8e9667cb5d45a26b06bfc93.
* fixed
---------
Co-authored-by: syuilo <4439005+syuilo@users.noreply.github.com>
Diffstat (limited to 'packages/frontend/src/pages')
| -rw-r--r-- | packages/frontend/src/pages/channel.vue | 82 |
1 files changed, 74 insertions, 8 deletions
diff --git a/packages/frontend/src/pages/channel.vue b/packages/frontend/src/pages/channel.vue index 7c19e6798d..dff8be2a57 100644 --- a/packages/frontend/src/pages/channel.vue +++ b/packages/frontend/src/pages/channel.vue @@ -129,24 +129,25 @@ useInterval(() => { }); watch(() => props.channelId, async () => { - channel.value = await misskeyApi('channels/show', { + const _channel = await misskeyApi('channels/show', { channelId: props.channelId, }); - if (channel.value == null) return; // TSを黙らすため - favorited.value = channel.value.isFavorited ?? false; - if (favorited.value || channel.value.isFollowing) { + favorited.value = _channel.isFavorited ?? false; + if (favorited.value || _channel.isFollowing) { tab.value = 'timeline'; } - if ((favorited.value || channel.value.isFollowing) && channel.value.lastNotedAt) { - const lastReadedAt: number = miLocalStorage.getItemAsJson(`channelLastReadedAt:${channel.value.id}`) ?? 0; - const lastNotedAt = Date.parse(channel.value.lastNotedAt); + if ((favorited.value || _channel.isFollowing) && _channel.lastNotedAt) { + const lastReadedAt: number = miLocalStorage.getItemAsJson(`channelLastReadedAt:${_channel.id}`) ?? 0; + const lastNotedAt = Date.parse(_channel.lastNotedAt); if (lastNotedAt > lastReadedAt) { - miLocalStorage.setItemAsJson(`channelLastReadedAt:${channel.value.id}`, lastNotedAt); + miLocalStorage.setItemAsJson(`channelLastReadedAt:${_channel.id}`, lastNotedAt); } } + + channel.value = _channel; }, { immediate: true }); function edit() { @@ -190,6 +191,53 @@ async function unfavorite() { }); } +async function mute() { + if (!channel.value) return; + const _channel = channel.value; + + const { canceled, result: period } = await os.select({ + title: i18n.ts.mutePeriod, + items: [{ + value: 'indefinitely', text: i18n.ts.indefinitely, + }, { + value: 'tenMinutes', text: i18n.ts.tenMinutes, + }, { + value: 'oneHour', text: i18n.ts.oneHour, + }, { + value: 'oneDay', text: i18n.ts.oneDay, + }, { + value: 'oneWeek', text: i18n.ts.oneWeek, + }], + default: 'indefinitely', + }); + if (canceled) return; + + const expiresAt = period === 'indefinitely' ? null + : period === 'tenMinutes' ? Date.now() + (1000 * 60 * 10) + : period === 'oneHour' ? Date.now() + (1000 * 60 * 60) + : period === 'oneDay' ? Date.now() + (1000 * 60 * 60 * 24) + : period === 'oneWeek' ? Date.now() + (1000 * 60 * 60 * 24 * 7) + : null; + + os.apiWithDialog('channels/mute/create', { + channelId: _channel.id, + expiresAt, + }).then(() => { + _channel.isMuting = true; + }); +} + +async function unmute() { + if (!channel.value) return; + const _channel = channel.value; + + os.apiWithDialog('channels/mute/delete', { + channelId: _channel.id, + }).then(() => { + _channel.isMuting = false; + }); +} + async function search() { if (!channel.value) return; @@ -243,6 +291,24 @@ const headerActions = computed(() => { }); } + if (!channel.value.isMuting) { + headerItems.push({ + icon: 'ti ti-volume', + text: i18n.ts.mute, + handler: async (): Promise<void> => { + await mute(); + }, + }); + } else { + headerItems.push({ + icon: 'ti ti-volume-off', + text: i18n.ts.unmute, + handler: async (): Promise<void> => { + await unmute(); + }, + }); + } + if (($i && $i.id === channel.value.userId) || iAmModerator) { headerItems.push({ icon: 'ti ti-settings', |