ATlast — you'll never need to find your favorites on another platform again. Find your favs in the ATmosphere.
atproto

remove / replace emojis w favicons

Changed files
+74 -12
src
+52
src/components/FaviconIcon.tsx
··· 1 + import { useState } from "react"; 2 + import { Globe, Settings as SettingsIcon } from "lucide-react"; 3 + 4 + interface FaviconIconProps { 5 + url: string; 6 + alt: string; 7 + className?: string; 8 + } 9 + 10 + export default function FaviconIcon({ url, alt, className }: FaviconIconProps) { 11 + const [loaded, setLoaded] = useState(false); 12 + const [error, setError] = useState(false); 13 + 14 + if (error) { 15 + return ( 16 + <Globe 17 + className={ 18 + className || "w-4 h-4 text-neutral-400 dark:text-neutral-500" 19 + } 20 + /> 21 + ); 22 + } 23 + 24 + return ( 25 + <> 26 + {/* Fallback/Placeholder */} 27 + {!loaded && ( 28 + <Globe 29 + className={ 30 + className || "w-4 h-4 text-neutral-400 dark:text-neutral-500" 31 + } 32 + /> 33 + )} 34 + 35 + {/* The actual image */} 36 + <img 37 + src={url} 38 + alt={`${alt} favicon`} 39 + className={className || "h-4 w-4"} 40 + // Use inline style to show only when loaded, preventing a broken image icon flicker 41 + style={{ display: loaded ? "block" : "none" }} 42 + onLoad={() => { 43 + setLoaded(true); 44 + setError(false); 45 + }} 46 + onError={() => { 47 + setError(true); 48 + }} 49 + /> 50 + </> 51 + ); 52 + }
+11 -2
src/components/HistoryTab.tsx
··· 1 1 import { Upload, Sparkles, ChevronRight, Database } from "lucide-react"; 2 2 import { ATPROTO_APPS } from "../constants/atprotoApps"; 3 3 import type { Upload as UploadType } from "../types"; 4 + import FaviconIcon from "../components/FaviconIcon"; 4 5 import type { UserSettings } from "../types/settings"; 5 6 6 7 interface HistoryTabProps { ··· 157 158 href={destApp.link} 158 159 target="_blank" 159 160 rel="noopener noreferrer" 160 - className="text-sm text-purple-750 dark:text-cyan-250 hover:underline leading-tight" 161 + className="text-sm text-purple-750 dark:text-cyan-250 hover:underline leading-tight flex items-center space-x-1" 161 162 > 162 - {destApp.action} on {destApp.icon} {destApp.name} 163 + <span>{destApp.action} on</span> 164 + 165 + <FaviconIcon 166 + url={destApp.icon} 167 + alt={destApp.name} 168 + className="w-3 h-3 mb-0.5 flex-shrink-0" 169 + /> 170 + 171 + <span>{destApp.name}</span> 163 172 </a> 164 173 )} 165 174 <div className="flex items-center flex-wrap gap-2">
+1 -1
src/components/SetupWizard.tsx
··· 211 211 > 212 212 {Object.values(ATPROTO_APPS).map((app) => ( 213 213 <option key={app.id} value={app.id}> 214 - {app.icon} {app.name} 214 + {app.name} 215 215 </option> 216 216 ))} 217 217 </select>
+9 -8
src/constants/atprotoApps.ts
··· 4 4 bluesky: { 5 5 id: "bluesky", 6 6 name: "Bluesky", 7 - description: "The main ATmosphere social network", 7 + description: "Social app built for better conversations.", 8 8 link: "https://bsky.app/", 9 - icon: "🦋", 9 + icon: "https://web-cdn.bsky.app/static/apple-touch-icon.png", 10 10 action: "Follow", 11 11 followLexicon: "app.bsky.graph.follow", 12 12 enabled: true, ··· 14 14 tangled: { 15 15 id: "tangled", 16 16 name: "Tangled", 17 - description: "Alternative following for developers & creators", 17 + description: "Tightly-knit social coding!", 18 18 link: "https://tangled.org/", 19 - icon: "🐑", 19 + icon: "https://tangled.org/favicon.ico", 20 20 action: "Follow", 21 21 followLexicon: "sh.tangled.graph.follow", 22 22 enabled: true, ··· 24 24 spark: { 25 25 id: "spark", 26 26 name: "Spark", 27 - description: "Short-form video focused social", 27 + description: 28 + "Social that puts the user in control, dedicated to video and photo.", 28 29 link: "https://sprk.so/", 29 - icon: "✨", 30 + icon: "https://sprk.so/favicon.ico", 30 31 action: "Follow", 31 32 followLexicon: "so.sprk.graph.follow", 32 33 enabled: true, ··· 35 36 id: "bsky list", 36 37 name: "Bluesky List", 37 38 description: "Organize into custom Bluesky lists", 38 - link: "https://bsky.app/", 39 - icon: "📃", 39 + link: "https://bsky.app", 40 + icon: "https://web-cdn.bsky.app/static/apple-touch-icon.png", 40 41 action: "Add to", 41 42 followLexicon: "app.bsky.graph.follow", 42 43 enabled: false, // Not yet implemented
+1 -1
src/pages/Settings.tsx
··· 176 176 > 177 177 {Object.values(ATPROTO_APPS).map((app) => ( 178 178 <option key={app.id} value={app.id}> 179 - {app.icon} {app.name} 179 + {app.name} 180 180 </option> 181 181 ))} 182 182 </select>