beatufitull front end for ozone modration ,, wit catpucoin and ebergarden !
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

add help panel

+116 -2
+2
pnpm-workspace.yaml
··· 2 2 - better-sqlite3 3 3 - core-js 4 4 - esbuild 5 + - protobufjs 6 + - sharp
+100
src/components/MikuHelp.svelte
··· 1 + <script lang="ts"> 2 + import miku from '$lib/assets/miku.png'; 3 + import { AtUri, ComAtprotoRepoStrongRef } from '@atproto/api'; 4 + import { isRepoRef } from '@atproto/api/dist/client/types/com/atproto/admin/defs'; 5 + import type { SubjectStatusView } from '@atproto/api/dist/client/types/tools/ozone/moderation/defs'; 6 + import { ExternalLink, TriangleAlert, XIcon } from 'lucide-svelte'; 7 + import { onMount } from 'svelte'; 8 + 9 + const { 10 + featuredReport, 11 + onOpenPost, 12 + onOpenUser 13 + }: { 14 + featuredReport?: SubjectStatusView | undefined; 15 + onOpenPost: (uri: string) => void; 16 + onOpenUser: (did: string) => void; 17 + } = $props(); 18 + let show = $state(false); 19 + 20 + onMount(() => { 21 + const localValue = localStorage.getItem('showHelp'); 22 + 23 + if (localValue === null) { 24 + show = true; 25 + } else { 26 + show = localValue === 'true'; 27 + } 28 + }); 29 + 30 + function dismiss() { 31 + show = false; 32 + localStorage.setItem('showHelp', 'false'); 33 + } 34 + </script> 35 + 36 + {#if show} 37 + <div class="pb-5"> 38 + <div class="relative rounded-4xl border-3 border-dashed border-ctp-mauve"> 39 + <button 40 + class="absolute top-5 right-5 cursor-pointer rounded-xl p-1 text-ctp-subtext0 hover:bg-ctp-surface0" 41 + onclick={dismiss} 42 + > 43 + <XIcon /> 44 + </button> 45 + <div class="flex items-center justify-center gap-10 p-10 text-ctp-text"> 46 + <div class="flex-1"> 47 + <!-- <h2 class="mb-2 text-2xl font-bold">hatsune miku is here to help !</h2> --> 48 + <p class="text-ctp-text"> 49 + {#if featuredReport} 50 + not sure where to start? start by clicking a report with a <span 51 + class="ml-1 inline-flex items-center gap-2 whitespace-nowrap text-ctp-yellow" 52 + ><TriangleAlert class="size-5" /> 53 + triangle alert</span 54 + > 55 + which means it hasnt been resolved yet! like this one: 56 + {:else} 57 + not sure where to start? wait for a report to come in and it will show up below! 58 + {/if} 59 + </p> 60 + {#if featuredReport} 61 + {@const subject = featuredReport.subject} 62 + <div class="mt-3 flex items-center rounded-xl border-2 border-ctp-surface1 px-4 py-3"> 63 + <div class="flex items-center gap-2"> 64 + <TriangleAlert class="size-5 text-ctp-yellow" /> 65 + <p> 66 + {#if ComAtprotoRepoStrongRef.isMain(subject)} 67 + <button 68 + onclick={() => onOpenPost(subject.uri)} 69 + class="inline-flex cursor-pointer items-center px-0 py-0 text-ctp-blue hover:underline" 70 + > 71 + Post 72 + <ExternalLink size={15} class="ml-1" /> 73 + </button> 74 + created by 75 + <button 76 + onclick={() => onOpenUser(new AtUri(subject.uri).host)} 77 + class="inline-flex cursor-pointer items-center px-0 py-0 text-ctp-blue hover:underline" 78 + > 79 + @{featuredReport.subjectRepoHandle} 80 + <ExternalLink size={15} class="ml-1" /> 81 + </button> 82 + {:else if isRepoRef(subject)} 83 + <button 84 + onclick={() => onOpenUser(subject.did)} 85 + class="inline-flex cursor-pointer items-center px-0 py-0 text-ctp-blue hover:underline" 86 + > 87 + @{featuredReport.subjectRepoHandle} 88 + <ExternalLink size={15} class="ml-1" /> 89 + </button> 90 + {/if} 91 + </p> 92 + </div> 93 + </div> 94 + {/if} 95 + </div> 96 + <img src={miku} alt="Miku" class="h-auto w-32 flex-shrink-0" /> 97 + </div> 98 + </div> 99 + </div> 100 + {/if}
src/lib/assets/miku.png

This is a binary file and will not be displayed.

+14 -2
src/routes/+page.svelte
··· 18 18 import { goto } from '$app/navigation'; 19 19 import AdvertisementOverlay from '$components/AdvertisementOverlay.svelte'; 20 20 import Tabs from '$components/ui/Tabs.svelte'; 21 + import MikuHelp from '$components/MikuHelp.svelte'; 21 22 22 23 function buildUrlForView(view: 'user' | 'post' | null, value?: string) { 23 24 const url = new URL(page.url); ··· 118 119 } 119 120 }; 120 121 } 122 + 123 + const firstUnresolvedReport = $derived( 124 + reportsQuery.data?.pages 125 + .flatMap((page) => page.subjectStatuses) 126 + .find((report) => report.reviewState !== 'tools.ozone.moderation.defs#reviewClosed') 127 + ); 121 128 </script> 122 129 123 130 <div class="min-h-screen w-full bg-ctp-base p-4"> ··· 135 142 <p>{reportsQuery.error?.message}</p> 136 143 </div> 137 144 {:else if reportsQuery.data} 145 + <MikuHelp 146 + featuredReport={firstUnresolvedReport} 147 + onOpenPost={openPost} 148 + onOpenUser={openUser} 149 + /> 138 150 <div class="mb-4 flex items-center gap-2"> 139 151 <div class="flex items-center gap-2 text-ctp-subtext0"> 140 152 <ShieldAlertIcon size={16} /> ··· 168 180 /> 169 181 </div> 170 182 <ul class="space-y-4 text-ctp-text"> 171 - {#each reportsQuery.data.pages as page} 172 - {#each page.subjectStatuses as report} 183 + {#each reportsQuery.data.pages as page (page.cursor)} 184 + {#each page.subjectStatuses as report (report.id)} 173 185 {@const subject = report.subject} 174 186 <li class="rounded-lg border border-ctp-surface1 p-4"> 175 187 <div class="flex items-center justify-between">