atmosphere explorer
0
fork

Configure Feed

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

add cancel button to export notif

Juliet df77a5c2 af38609b

+39 -12
+15 -1
src/components/notification.tsx
··· 7 7 progress?: number; 8 8 total?: number; 9 9 type?: "info" | "success" | "error"; 10 + onCancel?: () => void; 10 11 }; 11 12 12 13 const [notifications, setNotifications] = createStore<Notification[]>([]); ··· 48 49 "animate-[slideIn_0.25s_ease-in]": !removingIds().has(notification.id), 49 50 "animate-[slideOut_0.25s_ease-in]": removingIds().has(notification.id), 50 51 }} 51 - onClick={() => removeNotification(notification.id)} 52 + onClick={() => 53 + notification.progress === undefined && removeNotification(notification.id) 54 + } 52 55 > 53 56 <div class="flex items-center gap-2 text-sm"> 54 57 <Show when={notification.progress !== undefined}> ··· 81 84 <div class="text-xs text-neutral-600 dark:text-neutral-400"> 82 85 {notification.progress}% 83 86 </div> 87 + </Show> 88 + <Show when={notification.onCancel}> 89 + <button 90 + class="dark:hover:bg-dark-200 dark:shadow-dark-700 dark:active:bg-dark-100 mt-1 rounded border-[0.5px] border-neutral-300 bg-neutral-50 px-2 py-1.5 text-xs shadow-xs select-none hover:bg-neutral-100 active:bg-neutral-200 dark:border-neutral-700 dark:bg-neutral-800" 91 + onClick={(e) => { 92 + e.stopPropagation(); 93 + notification.onCancel?.(); 94 + }} 95 + > 96 + Cancel 97 + </button> 84 98 </Show> 85 99 </div> 86 100 </Show>
+24 -11
src/views/repo.tsx
··· 193 193 194 194 const downloadRepo = async () => { 195 195 let notificationId: string | null = null; 196 + const abortController = new AbortController(); 196 197 197 198 try { 198 199 setDownloading(true); ··· 201 202 progress: 0, 202 203 total: 0, 203 204 type: "info", 205 + onCancel: () => { 206 + abortController.abort(); 207 + if (notificationId) { 208 + removeNotification(notificationId); 209 + } 210 + }, 204 211 }); 205 212 206 - const response = await fetch(`${pds}/xrpc/com.atproto.sync.getRepo?did=${did}`); 213 + const response = await fetch(`${pds}/xrpc/com.atproto.sync.getRepo?did=${did}`, { 214 + signal: abortController.signal, 215 + }); 207 216 if (!response.ok) { 208 217 throw new Error(`HTTP error status: ${response.status}`); 209 218 } ··· 254 263 message: "Repository downloaded successfully", 255 264 type: "success", 256 265 progress: undefined, 266 + onCancel: undefined, 257 267 }); 258 268 setTimeout(() => { 259 269 if (notificationId) removeNotification(notificationId); 260 270 }, 3000); 261 271 } catch (error) { 262 - console.error("Download failed:", error); 263 - if (notificationId) { 264 - updateNotification(notificationId, { 265 - message: "Download failed", 266 - type: "error", 267 - progress: undefined, 268 - }); 269 - setTimeout(() => { 270 - if (notificationId) removeNotification(notificationId); 271 - }, 5000); 272 + if (!(error instanceof Error && error.name === "AbortError")) { 273 + console.error("Download failed:", error); 274 + if (notificationId) { 275 + updateNotification(notificationId, { 276 + message: "Download failed", 277 + type: "error", 278 + progress: undefined, 279 + onCancel: undefined, 280 + }); 281 + setTimeout(() => { 282 + if (notificationId) removeNotification(notificationId); 283 + }, 5000); 284 + } 272 285 } 273 286 } 274 287 setDownloading(false);