+31
-16
src/components/FaviconIcon.tsx
+31
-16
src/components/FaviconIcon.tsx
···
1
+
// FaviconIcon.tsx (Conceptual Component Update)
2
+
1
3
import { useState } from "react";
2
-
import { Globe, Settings as SettingsIcon } from "lucide-react";
4
+
import { Globe } from "lucide-react";
3
5
4
6
interface FaviconIconProps {
5
7
url: string;
6
8
alt: string;
7
9
className?: string;
10
+
useButtonStyling?: boolean; // ⬅️ NEW OPTIONAL PROP
8
11
}
9
12
10
-
export default function FaviconIcon({ url, alt, className }: FaviconIconProps) {
13
+
export default function FaviconIcon({
14
+
url,
15
+
alt,
16
+
className,
17
+
useButtonStyling = false,
18
+
}: FaviconIconProps) {
19
+
const [error, setError] = useState(false);
11
20
const [loaded, setLoaded] = useState(false);
12
-
const [error, setError] = useState(false);
21
+
22
+
// Define the base classes (applied to the image itself)
23
+
const imageClasses = "w-full h-full object-contain";
24
+
25
+
// Define the special button classes conditionally
26
+
const boundaryClasses = useButtonStyling
27
+
? "bg-white p-1 rounded-full shadow-md flex items-center justify-center"
28
+
: ""; // No special styling by default
29
+
30
+
// Combine the passed-in class name (for size) with the conditional boundary classes
31
+
const finalWrapperClasses = `${className || "w-4 h-4"} ${boundaryClasses}`;
13
32
14
33
if (error) {
15
34
return (
16
-
<Globe
17
-
className={
18
-
className || "w-4 h-4 text-neutral-400 dark:text-neutral-500"
19
-
}
20
-
/>
35
+
<div className={`${finalWrapperClasses}`}>
36
+
<Globe className={`${imageClasses} text-neutral-500`} />
37
+
</div>
21
38
);
22
39
}
23
40
24
41
return (
25
-
<>
26
-
{/* Fallback/Placeholder */}
42
+
// Use the final combined classes on the wrapper
43
+
<div className={finalWrapperClasses}>
44
+
{/* Placeholder while loading */}
27
45
{!loaded && (
28
46
<Globe
29
-
className={
30
-
className || "w-4 h-4 text-neutral-400 dark:text-neutral-500"
31
-
}
47
+
className={`${imageClasses} text-neutral-400 dark:text-neutral-500`}
32
48
/>
33
49
)}
34
50
···
36
52
<img
37
53
src={url}
38
54
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
55
+
className={imageClasses}
41
56
style={{ display: loaded ? "block" : "none" }}
42
57
onLoad={() => {
43
58
setLoaded(true);
···
47
62
setError(true);
48
63
}}
49
64
/>
50
-
</>
65
+
</div>
51
66
);
52
67
}
+3
-3
src/components/HistoryTab.tsx
+3
-3
src/components/HistoryTab.tsx
···
45
45
<div className="p-6">
46
46
{/* Setup Assistant Banner - Only show if wizard not completed */}
47
47
{!wizardCompleted && (
48
-
<div className="bg-firefly-banner-dark dark:bg-firefly-banner-dark rounded-2xl p-6 text-white">
48
+
<div className="bg-firefly-banner-dark dark:bg-firefly-banner-dark rounded-2xl p-6 text-white mb-3">
49
49
<div className="flex flex-col md:flex-row items-start md:items-center justify-between gap-4">
50
50
<div className="flex-1">
51
51
<h2 className="text-2xl font-bold mb-2">
···
67
67
</div>
68
68
)}
69
69
70
-
<div className="flex items-center space-x-3 mt-3 mb-4">
70
+
<div className="flex items-center space-x-3 mb-4">
71
71
<div>
72
72
<h2 className="text-xl font-bold text-purple-950 dark:text-cyan-50">
73
73
Previously Uploaded
···
171
171
<span>{destApp.name}</span>
172
172
</a>
173
173
)}
174
-
<div className="flex items-center flex-wrap gap-2">
174
+
<div className="flex items-center flex-wrap gap-2 py-1.5">
175
175
<span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium">
176
176
{upload.totalUsers}{" "}
177
177
{upload.totalUsers === 1 ? "user found" : "users found"}
+1
-1
src/components/PlatformSelector.tsx
+1
-1
src/components/PlatformSelector.tsx
···
26
26
title={isEnabled ? `Upload ${p.name} data` : "Coming soon"}
27
27
>
28
28
<PlatformIcon
29
-
className={`w-8 h-8 mx-auto mb-2 ${isEnabled ? "text-purple-750 dark:text-cyan-250" : "text-purple-750/50 dark:text-cyan-250/50"}`}
29
+
className={`w-6 h-6 mx-auto mb-2 ${isEnabled ? "text-purple-750 dark:text-cyan-250" : "text-purple-750/50 dark:text-cyan-250/50"}`}
30
30
/>
31
31
<div className="text-sm font-medium text-center text-purple-900 dark:text-cyan-100">
32
32
{p.name}
+12
-10
src/components/SearchResultCard.tsx
+12
-10
src/components/SearchResultCard.tsx
···
118
118
119
119
{/* User Stats and Match Percent */}
120
120
<div className="flex items-center flex-wrap gap-2">
121
-
{match.postCount && match.postCount > 0 && (
122
-
<span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium">
123
-
{match.postCount.toLocaleString()} posts
124
-
</span>
125
-
)}
126
-
{match.followerCount && match.followerCount > 0 && (
127
-
<span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium">
128
-
{match.followerCount.toLocaleString()} followers
129
-
</span>
130
-
)}
121
+
{typeof match.postCount === "number" &&
122
+
match.postCount > 0 && (
123
+
<span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium">
124
+
{match.postCount.toLocaleString()} posts
125
+
</span>
126
+
)}
127
+
{typeof match.followerCount === "number" &&
128
+
match.followerCount > 0 && (
129
+
<span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium">
130
+
{match.followerCount.toLocaleString()} followers
131
+
</span>
132
+
)}
131
133
<span className="text-xs px-2 py-0.5 rounded-full bg-purple-100 dark:bg-slate-900 text-purple-950 dark:text-cyan-50 font-medium">
132
134
{match.matchScore}% match
133
135
</span>
+5
-5
src/components/UploadTab.tsx
+5
-5
src/components/UploadTab.tsx
···
31
31
<div className="p-6">
32
32
{/* Upload Section */}
33
33
<div className="space-y-3">
34
-
<div className="flex items-center justify-between mb-4">
35
-
<div className="flex items-center space-x-3">
34
+
<div className="flex flex-col sm:flex-row items-start sm:items-center justify-between mb-4">
35
+
<div className="flex items-center space-x-3 mb-2 sm:mb-0">
36
36
<div>
37
37
<h2 className="text-xl font-bold text-purple-950 dark:text-cyan-50">
38
38
Upload Following Data
···
42
42
</p>
43
43
</div>
44
44
</div>
45
-
{wizardCompleted && (
45
+
{!wizardCompleted && (
46
46
<button
47
47
onClick={onShowWizard}
48
-
className="text-sm text-orange-650 hover:text-orange-500 dark:text-amber-400 dark:hover:text-amber-300 font-medium transition-colors flex items-center space-x-1"
48
+
className="text-md text-orange-650 hover:text-orange-500 dark:text-amber-400 dark:hover:text-amber-300 font-medium transition-colors flex items-center space-x-1"
49
49
>
50
50
<Settings className="w-4 h-4" />
51
-
<span>Reconfigure</span>
51
+
<span>Configure</span>
52
52
</button>
53
53
)}
54
54
</div>
+2
-2
src/pages/Loading.tsx
+2
-2
src/pages/Loading.tsx
···
64
64
<div className="max-w-3xl mx-auto px-4 py-6">
65
65
<div className="flex items-center justify-between">
66
66
<div className="flex items-center space-x-4">
67
-
<div className="relative w-14 h-14">
68
-
<PlatformIcon className="w-12 h-12" />
67
+
<div className="relative w-12 h-12">
68
+
<PlatformIcon className="w-10 h-10" />
69
69
</div>
70
70
<div>
71
71
<h2 className="text-xl font-bold">Finding Your Fireflies</h2>
+10
-2
src/pages/Results.tsx
+10
-2
src/pages/Results.tsx
···
1
1
import { Sparkles, Heart } from "lucide-react";
2
2
import { PLATFORMS } from "../constants/platforms";
3
+
import { ATPROTO_APPS } from "../constants/atprotoApps";
3
4
import AppHeader from "../components/AppHeader";
4
5
import SearchResultCard from "../components/SearchResultCard";
6
+
import FaviconIcon from "../components/FaviconIcon";
5
7
import type { AtprotoAppId } from "../types/settings";
6
8
7
9
interface atprotoSession {
···
73
75
}: ResultsPageProps) {
74
76
const platform = PLATFORMS[sourcePlatform] || PLATFORMS.tiktok;
75
77
const PlatformIcon = platform.icon;
78
+
const destinationApp = ATPROTO_APPS[destinationAppId];
76
79
77
80
return (
78
81
<div className="min-h-screen pb-24">
···
203
206
disabled={isFollowing}
204
207
className="w-full bg-firefly-banner dark:bg-firefly-banner-dark text-white hover:from-amber-600 hover:via-orange-600 hover:to-pink-600 py-5 rounded-2xl font-bold text-lg transition-all shadow-2xl hover:shadow-3xl flex items-center justify-center space-x-3 hover:scale-105 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100"
205
208
>
206
-
<Sparkles className="w-6 h-6" />
209
+
<FaviconIcon
210
+
url={destinationApp.icon}
211
+
alt={destinationApp.name}
212
+
className="w-5 h-5"
213
+
useButtonStyling={true}
214
+
/>
207
215
<span>
208
216
Light Up {totalSelected} Connection
209
-
{totalSelected === 1 ? "" : "s"} ✨
217
+
{totalSelected === 1 ? "" : "s"}
210
218
</span>
211
219
</button>
212
220
</div>
+1
-1
src/pages/Settings.tsx
+1
-1
src/pages/Settings.tsx
···
162
162
className="flex items-center justify-between px-3 py-2 rounded-xl transition-colors"
163
163
>
164
164
<div className="flex items-center space-x-3 flex-1">
165
-
<Icon className="w-6 h-6 text-purple-950 dark:text-cyan-50 flex-shrink-0" />
165
+
<Icon className="w-4 h-4 text-purple-950 dark:text-cyan-50 flex-shrink-0" />
166
166
<div className="flex-1 min-w-0">
167
167
<div className="font-medium text-purple-950 dark:text-cyan-50">
168
168
{p.name}