appview-less bluesky client
24
fork

Configure Feed

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

cleanup css, allow adding blocks / mutes via handle

dawn b6ba04a0 c64c146b

+44 -16
+21 -2
src/app.css
··· 8 8 opacity: 0; 9 9 transform: scale(0.95); 10 10 } 11 + 11 12 100% { 12 13 opacity: 1; 13 14 transform: scale(1); ··· 25 26 26 27 @utility single-line-input { 27 28 @apply w-full rounded-sm border-2 border-(--nucleus-accent)/40 bg-(--nucleus-accent)/3 px-3 py-2 font-medium transition-all; 29 + 28 30 &:focus { 29 31 @apply scale-[1.02] border-(--nucleus-accent)/80 bg-(--nucleus-accent)/10 [box-shadow:none] outline-none; 30 32 } 31 33 } 32 34 33 35 @utility action-button { 34 - @apply rounded-sm border-2 border-(--nucleus-accent) px-3 py-2 font-semibold text-(--nucleus-accent) transition-all hover:scale-105 hover:bg-(--nucleus-accent)/20; 36 + @apply rounded-sm border-2 border-(--nucleus-accent) px-3 py-2 font-semibold text-(--nucleus-accent) transition-all; 37 + 38 + &:enabled { 39 + @apply hover:scale-105 hover:bg-(--nucleus-accent)/20; 40 + } 41 + 42 + &:disabled { 43 + @apply opacity-60 hover:scale-100; 44 + } 35 45 } 36 46 37 47 @utility error-disclaimer { 38 48 @apply rounded-sm border-2 border-red-500 p-2; 39 49 background-color: color-mix(in srgb, var(--color-red-500) 15%, var(--nucleus-bg)); 50 + 40 51 p { 41 52 @apply text-base text-wrap wrap-break-word text-red-500; 42 53 } ··· 49 60 50 61 button { 51 62 @apply hover:cursor-pointer; 63 + 64 + &:disabled { 65 + @apply cursor-not-allowed; 66 + } 52 67 } 53 68 54 69 a { ··· 87 102 } 88 103 89 104 @keyframes pulse-highlight { 105 + 90 106 0%, 91 107 100% { 92 108 box-shadow: 0 0 0 0 var(--nucleus-selected-post); 93 109 } 110 + 94 111 50% { 95 112 box-shadow: 0 0 20px 5px var(--nucleus-selected-post); 96 113 } ··· 101 118 transform: translateX(144px); 102 119 opacity: 0; 103 120 } 121 + 104 122 to { 105 123 transform: translateX(0); 106 124 opacity: 1; ··· 112 130 transform: translateX(-144px); 113 131 opacity: 0; 114 132 } 133 + 115 134 to { 116 135 transform: translateX(0); 117 136 opacity: 1; ··· 140 159 141 160 .settings-desc { 142 161 @apply mb-2 text-sm text-(--nucleus-fg)/80; 143 - } 162 + }
+23 -13
src/components/SettingsModerationTab.svelte
··· 1 1 <script lang="ts"> 2 2 import MutedAccountItem from './MutedAccountItem.svelte'; 3 3 import VirtualList from '@tutorlatin/svelte-tiny-virtual-list'; 4 - import type { Did } from '@atcute/lexicons'; 5 - import type { Preferences } from '$lib/at/pocket'; 4 + import type { ActorIdentifier, Did } from '@atcute/lexicons'; 6 5 import { allBacklinks, createBlock, deleteBlock, clients } from '$lib/state.svelte'; 7 6 import { blockSource } from '$lib'; 7 + import { isActorIdentifier } from '@atcute/lexicons/syntax'; 8 + import { resolveHandle } from '$lib/at/client.svelte'; 8 9 9 10 interface Props { 10 11 mutes: Did[]; 11 - currentPrefs: Preferences | null; 12 12 onAddMute: (did: Did) => void; 13 13 onRemoveMute: (did: Did) => void; 14 14 selectedAccount: Did | null; 15 15 } 16 16 17 - let { mutes, currentPrefs, onAddMute, onRemoveMute, selectedAccount }: Props = $props(); 17 + let { mutes, onAddMute, onRemoveMute, selectedAccount }: Props = $props(); 18 18 19 19 let newMuteInput = $state(''); 20 20 let newBlockInput = $state(''); 21 21 22 - const handleAddMute = () => { 22 + const handleAddMute = async () => { 23 23 if (!newMuteInput.trim()) return; 24 - const did = newMuteInput.trim() as Did; 25 - onAddMute(did); 24 + const did = await resolveHandle(newMuteInput.trim() as ActorIdentifier); 25 + if (!did.ok) return; 26 + onAddMute(did.value); 26 27 newMuteInput = ''; 27 28 }; 28 29 ··· 44 45 if (!newBlockInput.trim() || !selectedAccount) return; 45 46 const client = clients.get(selectedAccount); 46 47 if (!client) return; 47 - const did = newBlockInput.trim() as Did; 48 - await createBlock(client, did); 48 + const did = await resolveHandle(newBlockInput.trim() as ActorIdentifier); 49 + if (!did.ok) return; 50 + await createBlock(client, did.value); 49 51 newBlockInput = ''; 50 52 }; 51 53 ··· 65 67 <input 66 68 type="text" 67 69 bind:value={newMuteInput} 68 - placeholder="did:plc:..." 70 + placeholder="enter identifier" 69 71 class="single-line-input flex-1" 70 72 /> 71 - <button onclick={handleAddMute} class="action-button">add</button> 73 + <button 74 + disabled={!isActorIdentifier(newMuteInput)} 75 + onclick={handleAddMute} 76 + class="action-button">add</button 77 + > 72 78 </div> 73 79 {#if mutes.length > 0} 74 80 <div class="h-fit"> ··· 99 105 <input 100 106 type="text" 101 107 bind:value={newBlockInput} 102 - placeholder="did:plc:..." 108 + placeholder="enter identifier" 103 109 class="single-line-input flex-1" 104 110 /> 105 - <button onclick={handleAddBlock} class="action-button">add</button> 111 + <button 112 + disabled={!isActorIdentifier(newBlockInput)} 113 + onclick={handleAddBlock} 114 + class="action-button">add</button 115 + > 106 116 </div> 107 117 {#if blocks.length > 0} 108 118 <div class="h-fit">
-1
src/components/SettingsView.svelte
··· 160 160 {:else if tab === 'moderation'} 161 161 <SettingsModerationTab 162 162 {mutes} 163 - {currentPrefs} 164 163 onAddMute={handleAddMute} 165 164 onRemoveMute={handleRemoveMute} 166 165 {selectedAccount}