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

Configure Feed

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

at main 198 lines 6.0 kB view raw
1<script lang="ts"> 2 import { session } from '$lib/stores/auth'; 3 import { appTheme, type AppTheme } from '$lib/stores/ui'; 4 import { createQuery } from '@tanstack/svelte-query'; 5 import { Cat, LogOut, MenuIcon, Paintbrush, SearchIcon, TriangleAlert } from 'lucide-svelte'; 6 import Button from './ui/Button.svelte'; 7 import PopupMenu from './ui/PopupMenu.svelte'; 8 import { navItems } from '$lib/nav'; 9 import { ads } from '$lib/ads'; 10 11 let { onSearch } = $props<{ 12 onSearch: () => void; 13 }>(); 14 15 async function handleLogout() { 16 if ($session) { 17 await $session.session.session.signOut(); 18 } 19 localStorage.removeItem('meowzone-password-session'); 20 session.set(null); 21 window.location.href = '/login'; 22 } 23 24 function setAppTheme(theme: AppTheme) { 25 appTheme.set(theme); 26 } 27 28 const profileQuery = createQuery(() => ({ 29 queryKey: ['profile'], 30 queryFn: async () => { 31 if (!$session) { 32 throw new Error('No active session'); 33 } 34 const profile = await $session.agent.getProfile({ actor: $session.agent.did! }); 35 return profile.data; 36 }, 37 enabled: !!$session 38 })); 39 40 function handleChange(event: Event) { 41 const adsEnabled = (event.target as HTMLInputElement).checked; 42 ads.toggle(adsEnabled); 43 } 44</script> 45 46<div 47 class="mx-auto mt-5 mb-4 flex max-w-2xl items-center justify-between rounded-xl border border-ctp-surface1 px-2 py-2" 48> 49 <a class="ml-3 cursor-pointer" href="/"> 50 <Cat class="text-ctp-subtext1 hover:text-ctp-text" /> 51 </a> 52 <div class="flex items-center gap-2"> 53 <Button 54 variant="ghost" 55 size="icon" 56 onclick={() => onSearch()} 57 className="items-center size-10" 58 aria-label="Menu" 59 > 60 <SearchIcon class="size-5" /> 61 </Button> 62 <PopupMenu 63 originClass="origin-top-right" 64 wrapperClass="relative" 65 menuClass="absolute top-full right-0 z-50 w-48 rounded-md border border-ctp-surface1 bg-ctp-base p-1.5 shadow-lg" 66 > 67 <svelte:fragment slot="trigger" let:toggle> 68 <Button 69 variant="ghost" 70 size="icon" 71 onclick={() => toggle()} 72 className="items-center size-10" 73 aria-label="Menu" 74 > 75 <div class="size-8"> 76 {#if profileQuery.isLoading} 77 <div class="size-8 rounded-full bg-ctp-surface1"></div> 78 {:else if profileQuery.isError || !profileQuery.data} 79 <div class="size-8 rounded-full bg-ctp-red/20"> 80 <TriangleAlert class="size-full p-2 text-ctp-red" /> 81 </div> 82 {:else if profileQuery.data && $session} 83 <img 84 src={profileQuery.data.avatar} 85 alt={profileQuery.data.displayName || profileQuery.data.handle} 86 class="size-8 rounded-full" 87 /> 88 {/if} 89 </div> 90 </Button> 91 </svelte:fragment> 92 93 <svelte:fragment slot="content"> 94 <div class="mb-1 flex items-center gap-2 px-2 py-1 text-xs text-ctp-subtext0"> 95 <Paintbrush size={16} /> 96 <span>Theme</span> 97 </div> 98 <div class="grid grid-cols-2 gap-2 px-2 py-1"> 99 <button 100 type="button" 101 onclick={() => setAppTheme('catppuccin')} 102 class="cursor-pointer rounded border border-ctp-surface1 px-2 py-1 text-xs text-ctp-text hover:bg-ctp-surface0" 103 class:bg-ctp-surface0={$appTheme === 'catppuccin'} 104 > 105 Catppuccin 106 </button> 107 <button 108 type="button" 109 onclick={() => setAppTheme('evergarden')} 110 class="cursor-pointer rounded border border-ctp-surface1 px-2 py-1 text-xs text-ctp-text hover:bg-ctp-surface0" 111 class:bg-ctp-surface0={$appTheme === 'evergarden'} 112 > 113 Evergarden 114 </button> 115 </div> 116 <!-- <div class="my-2 border-t border-ctp-surface1"></div> 117 <div class="mb-1 px-2 py-1 text-xs text-ctp-subtext0">Accent</div> 118 <div class="flex gap-2 px-2 py-1"> 119 {#each accentColours as colour} 120 <button 121 class="size-5 cursor-pointer rounded-full hover:opacity-80" 122 class:bg-ctp-sapphire={colour === 'sapphire'} 123 class:bg-ctp-mauve={colour === 'mauve'} 124 class:bg-ctp-lavender={colour === 'lavender'} 125 class:ring-2={$inputAccentColor === colour} 126 class:ring-ctp-overlay1={$inputAccentColor === colour} 127 class:text-ctp-subtext0={$inputAccentColor !== colour} 128 onclick={() => setInputAccentColor(colour)} 129 aria-label={`Set input accent color to ${colour}`} 130 > 131 </button> 132 {/each} 133 </div> --> 134 <div class="my-2 border-t border-ctp-surface1"></div> 135 <div> 136 <div class="flex items-center gap-2 px-2 py-1"> 137 <input 138 type="checkbox" 139 id="ads-toggle" 140 class="cursor-pointer rounded accent-ctp-sapphire" 141 bind:checked={$ads} 142 onchange={handleChange} 143 /> 144 <label for="ads-toggle" class="cursor-pointer text-ctp-text">Enable ads</label> 145 </div> 146 <div class="my-2 border-t border-ctp-surface1"></div> 147 <Button 148 variant="danger" 149 fullWidth={true} 150 size="sm" 151 onclick={handleLogout} 152 className="justify-start py-1.5 rounded-sm" 153 > 154 <LogOut size={18} class="mr-3" /> 155 <span>Logout</span> 156 </Button> 157 </div></svelte:fragment 158 > 159 </PopupMenu> 160 <PopupMenu 161 originClass="origin-top-right" 162 wrapperClass="relative" 163 menuClass="absolute top-full right-0 z-50 w-40 rounded-md border border-ctp-surface1 bg-ctp-base p-1.5 shadow-lg" 164 > 165 <svelte:fragment slot="trigger" let:toggle> 166 <Button 167 variant="ghost" 168 size="icon" 169 onclick={() => toggle()} 170 className="items-center size-10" 171 aria-label="Menu" 172 > 173 <MenuIcon class="size-5" /> 174 </Button> 175 </svelte:fragment> 176 177 <svelte:fragment slot="content"> 178 {#each navItems as item (item.label)} 179 {@const Icon = item.icon} 180 181 <a href={item.href}> 182 <Button 183 variant="ghost" 184 fullWidth={true} 185 size="icon" 186 className="justify-start rounded-md hover:bg-ctp-surface0" 187 > 188 <span class="grid size-6 place-items-center"> 189 <Icon size={16} /> 190 </span> 191 <span>{item.label}</span> 192 </Button> 193 </a> 194 {/each} 195 </svelte:fragment> 196 </PopupMenu> 197 </div> 198</div>