Coves frontend - a photon fork
1<script lang="ts">
2 import type { CommentView } from '$lib/api/coves/types'
3 import { coves } from '$lib/api/client.svelte'
4 import { profile } from '$lib/app/auth.svelte'
5 import { errorMessage } from '$lib/app/error'
6 import { t } from '$lib/app/i18n'
7 import { settings } from '$lib/app/settings.svelte'
8 import { Button, Menu, MenuButton, toast } from 'mono-svelte'
9 import {
10 ChatBubbleOvalLeft,
11 EllipsisHorizontal,
12 PencilSquare,
13 Share,
14 Trash,
15 } from 'svelte-hero-icons/dist'
16 import CommentVote from './CommentVote.svelte'
17
18 interface Props {
19 comment: CommentView
20 replying?: boolean
21 disabled?: boolean
22 onedit?: (comment: CommentView) => void
23 }
24
25 let {
26 comment = $bindable(),
27 replying = $bindable(false),
28 disabled = false,
29 onedit,
30 }: Props = $props()
31</script>
32
33<div
34 class={[
35 'flex flex-row items-center gap-0.5 w-full',
36 settings.posts.reverseActions && 'flex-row-reverse',
37 ]}
38>
39 <CommentVote
40 uri={comment.uri}
41 cid={comment.cid}
42 bind:stats={comment.stats}
43 bind:viewer={comment.viewer}
44 />
45 <Button
46 color="tertiary"
47 rounding="pill"
48 size="sm"
49 class="text-slate-500 dark:text-zinc-400 gap-1!"
50 onclick={() => (replying = !replying)}
51 disabled={disabled || !profile.current?.jwt}
52 icon={ChatBubbleOvalLeft}
53 >
54 {$t('comment.reply')}
55 </Button>
56 <Menu placement="bottom">
57 {#snippet target(attachment)}
58 <Button
59 {@attach attachment}
60 title={$t('comment.actions.label')}
61 color="tertiary"
62 rounding="pill"
63 size="square-md"
64 class="text-slate-600 dark:text-zinc-400"
65 icon={EllipsisHorizontal}
66 ></Button>
67 {/snippet}
68 <MenuButton
69 onclick={async () => {
70 try {
71 if (navigator.share) {
72 await navigator.share({ url: comment.uri as string })
73 } else {
74 await navigator.clipboard.writeText(comment.uri as string)
75 toast({ content: $t('toast.copied'), type: 'success' })
76 }
77 } catch (err) {
78 if (err instanceof Error && err.name === 'AbortError') return
79 toast({
80 content: err instanceof Error ? err.message : String(err),
81 type: 'error',
82 })
83 }
84 }}
85 icon={Share}
86 >
87 {$t('post.actions.more.share')}
88 </MenuButton>
89 {#if profile.current?.jwt}
90 {#if profile.current?.did && profile.current.did === comment.author.did}
91 <MenuButton onclick={() => onedit?.(comment)} icon={PencilSquare}>
92 {$t('post.actions.more.edit')}
93 </MenuButton>
94 {/if}
95 {#if profile.current?.did && profile.current.did === comment.author.did}
96 <MenuButton
97 disabled={comment.isDeleted}
98 color="danger-subtle"
99 onclick={async () => {
100 if (!profile.current?.jwt) return
101 try {
102 await coves().deleteComment({ uri: comment.uri })
103 comment.isDeleted = true
104 } catch (err) {
105 toast({
106 content: errorMessage(err),
107 type: 'error',
108 })
109 }
110 }}
111 icon={Trash}
112 >
113 {$t('post.actions.more.delete')}
114 </MenuButton>
115 {/if}
116 <!-- TODO(coves-migration): Re-enable save when backend API is available -->
117 <MenuButton
118 onclick={() => {
119 toast({ content: 'Reporting is not yet available', type: 'warning' })
120 }}
121 color="danger-subtle"
122 >
123 Report
124 </MenuButton>
125 {/if}
126 </Menu>
127 <div class="flex-1 w-full"></div>
128</div>