diff --git a/web/src/lib/components/MenuButton.svelte b/web/src/lib/components/MenuButton.svelte index 04d785e44..ceb1878ec 100644 --- a/web/src/lib/components/MenuButton.svelte +++ b/web/src/lib/components/MenuButton.svelte @@ -8,7 +8,7 @@ import { broadcast } from '$lib/Broadcast'; import { copy } from '$lib/Clipboard'; import { shareUrl } from '$lib/Share'; - import { rom, pubkey as authorPubkey } from '$lib/stores/Author'; + import { rom, pubkey as authorPubkey, mutePubkeys, muteEventIds } from '$lib/stores/Author'; import { developerMode } from '$lib/stores/Preference'; import IconDots from '@tabler/icons-svelte/icons/dots'; import IconBookmark from '@tabler/icons-svelte/icons/bookmark'; @@ -18,7 +18,10 @@ import IconCodeDots from '@tabler/icons-svelte/icons/code-dots'; import IconBroadcast from '@tabler/icons-svelte/icons/broadcast'; import IconTrash from '@tabler/icons-svelte/icons/trash'; + import IconVolumeOff from '@tabler/icons-svelte/icons/volume-off'; import { deleteEvent } from '$lib/author/Delete'; + import { mute, unmute } from '$lib/author/Mute'; + import { referTags } from '$lib/EventHelper'; export let event: Event; export let iconSize: number; @@ -27,6 +30,7 @@ $: bookmarked = isBookmarked(event); $: nevent = nip19.neventEncode({ id: event.id }); $: url = `${$page.url.origin}/${nevent}`; + $: rootId = referTags(event).root?.at(1) ?? event.id; async function onBookmark(note: Event) { console.log('[bookmark]', note, $rom); @@ -73,6 +77,50 @@ console.log('[delete]', event); await deleteEvent([event]); } + + async function onMute(): Promise { + console.debug('[mute pubkey]', event.pubkey); + + try { + await mute('p', event.pubkey); + } catch (error) { + console.error('[mute failed]', error); + alert($_('actions.mute.failed')); + } + } + + async function onUnmute(): Promise { + console.debug('[unmute pubkey]', event.pubkey); + + try { + await unmute('p', event.pubkey); + } catch (error) { + console.error('[unmute failed]', error); + alert($_('actions.unmute.failed')); + } + } + + async function onMuteThread(): Promise { + console.debug('[mute thread]', rootId); + + try { + await mute('e', rootId); + } catch (error) { + console.error('[mute failed]', error); + alert($_('actions.mute.failed')); + } + } + + async function onUnmuteThread(): Promise { + console.debug('[unmute thread]', rootId); + + try { + await unmute('e', rootId); + } catch (error) { + console.error('[unmute failed]', error); + alert($_('actions.unmute.failed')); + } + } @@ -130,6 +178,30 @@ {/if} + + + {$_('preferences.mute.mute')} + + {#if $mutePubkeys.includes(event.pubkey)} + + {$_('actions.unmute.user')} + + {:else} + + {$_('actions.mute.user')} + + {/if} + + {#if $muteEventIds.includes(rootId)} + + {$_('actions.unmute.thread')} + + {:else} + + {$_('actions.mute.thread')} + + {/if} + {#if $developerMode} {$_('menu.developer')} diff --git a/web/src/lib/components/ProfileMenuButton.svelte b/web/src/lib/components/ProfileMenuButton.svelte index 19cf47f03..3e4e3e2ac 100644 --- a/web/src/lib/components/ProfileMenuButton.svelte +++ b/web/src/lib/components/ProfileMenuButton.svelte @@ -76,7 +76,7 @@ await mute('p', pubkey); } catch (error) { console.error('[mute failed]', error); - alert('Failed to mute.'); + alert($_('actions.mute.failed')); } } @@ -87,7 +87,7 @@ await unmute('p', pubkey); } catch (error) { console.error('[unmute failed]', error); - alert('Failed to unmute.'); + alert($_('actions.unmute.failed')); } } diff --git a/web/src/lib/i18n/locales/en.json b/web/src/lib/i18n/locales/en.json index d57c5d114..64e56c2c1 100644 --- a/web/src/lib/i18n/locales/en.json +++ b/web/src/lib/i18n/locales/en.json @@ -205,15 +205,21 @@ }, "mute": { "button": "Mute", + "user": "Mute this user", "reposts": "Mute reposts", "reactions": "Mute reactions (likes)", - "zaps": "Mute zaps" + "zaps": "Mute zaps", + "thread": "Mute this thread", + "failed": "Failed to mute." }, "unmute": { "button": "Unmute", + "user": "Unmute this user", "reposts": "Unmute this user's reposts", "reactions": "Unmute this user's reactions", - "zaps": "Unmute this user's zaps" + "zaps": "Unmute this user's zaps", + "thread": "Unmute this thread", + "failed": "Failed to unmute." }, "delete": { "button": "Delete", diff --git a/web/src/lib/i18n/locales/ja.json b/web/src/lib/i18n/locales/ja.json index 5319cd3e9..06ca682c1 100644 --- a/web/src/lib/i18n/locales/ja.json +++ b/web/src/lib/i18n/locales/ja.json @@ -204,15 +204,21 @@ }, "mute": { "button": "ミュート", + "user": "ユーザーをミュート", "reposts": "リポストをミュート", "reactions": "リアクション(いいね)をミュート", - "zaps": "Zap をミュート" + "zaps": "Zap をミュート", + "thread": "スレッドをミュート", + "failed": "ミュートできませんでした。" }, "unmute": { "button": "ミュート解除", + "user": "ユーザーをミュート解除", "reposts": "リポストをミュート解除", "reactions": "リアクション(いいね)をミュート解除", - "zaps": "Zap をミュート解除" + "zaps": "Zap をミュート解除", + "thread": "スレッドをミュート解除", + "failed": "ミュートを解除できませんでした。" }, "delete": { "button": "削除", diff --git a/web/src/routes/(app)/[slug=note]/+page.svelte b/web/src/routes/(app)/[slug=note]/+page.svelte index 70351d062..61a92888d 100644 --- a/web/src/routes/(app)/[slug=note]/+page.svelte +++ b/web/src/routes/(app)/[slug=note]/+page.svelte @@ -10,7 +10,7 @@ import { rxNostr, referencesReqEmit } from '$lib/timelines/MainTimeline'; import { eventItemStore, metadataStore } from '$lib/cache/Events'; import type { LayoutData } from './$types'; - import { author, readRelays } from '$lib/stores/Author'; + import { readRelays } from '$lib/stores/Author'; import { pool } from '$lib/stores/Pool'; import TimelineView from '../TimelineView.svelte'; import { Api } from '$lib/Api'; @@ -20,7 +20,6 @@ import ProfileIconList from './ProfileIconList.svelte'; import { appName, chronologicalItem } from '$lib/Constants'; import { tick } from 'svelte'; - import MuteButton from '$lib/components/MuteButton.svelte'; import CustomEmoji from '$lib/components/content/CustomEmoji.svelte'; import IconRepeat from '@tabler/icons-svelte/icons/repeat'; import IconHeart from '@tabler/icons-svelte/icons/heart'; @@ -405,18 +404,6 @@ {/if} -{#if $author !== undefined && item !== undefined} - -{/if} @@ -465,15 +452,6 @@ text-decoration: underline; } - .mute { - display: flex; - flex-direction: row; - } - - .mute span { - margin-left: 0.5rem; - } - header { display: flex; }