-1
src/App.tsx
-1
src/App.tsx
-1
src/components/SearchResultCard.tsx
-1
src/components/SearchResultCard.tsx
-24
src/hooks/useSearch.ts
-24
src/hooks/useSearch.ts
···
3
3
import { SEARCH_CONFIG } from "../constants/platforms";
4
4
import type { SearchResult, SearchProgress, AtprotoSession } from "../types";
5
5
6
-
function sortSearchResults(results: SearchResult[]): SearchResult[] {
7
-
return [...results].sort((a, b) => {
8
-
// 1. Users with matches first
9
-
const aHasMatches = a.atprotoMatches.length > 0 ? 0 : 1;
10
-
const bHasMatches = b.atprotoMatches.length > 0 ? 0 : 1;
11
-
if (aHasMatches !== bHasMatches) return aHasMatches - bHasMatches;
12
-
13
-
// 2. For matched users, sort by highest posts count of their top match
14
-
if (a.atprotoMatches.length > 0 && b.atprotoMatches.length > 0) {
15
-
const aTopPosts = a.atprotoMatches[0]?.postCount || 0;
16
-
const bTopPosts = b.atprotoMatches[0]?.postCount || 0;
17
-
if (aTopPosts !== bTopPosts) return bTopPosts - aTopPosts;
18
-
19
-
// 3. Then by followers count
20
-
const aTopFollowers = a.atprotoMatches[0]?.followerCount || 0;
21
-
const bTopFollowers = b.atprotoMatches[0]?.followerCount || 0;
22
-
if (aTopFollowers !== bTopFollowers) return bTopFollowers - aTopFollowers;
23
-
}
24
-
25
-
// 4. Username as tiebreaker
26
-
return a.sourceUser.username.localeCompare(b.sourceUser.username);
27
-
});
28
-
}
29
-
30
6
export function useSearch(session: AtprotoSession | null) {
31
7
const [searchResults, setSearchResults] = useState<SearchResult[]>([]);
32
8
const [isSearchingAll, setIsSearchingAll] = useState(false);
-6
src/lib/apiClient/realApiClient.ts
-6
src/lib/apiClient/realApiClient.ts
···
121
121
return data;
122
122
},
123
123
124
-
async getProfile(): Promise<AtprotoSession> {
125
-
// This is now redundant - getSession returns profile data
126
-
// Keeping for backwards compatibility but it just calls getSession
127
-
return this.getSession();
128
-
},
129
-
130
124
async logout(): Promise<void> {
131
125
const res = await fetch("/.netlify/functions/logout", {
132
126
method: "POST",
+1
-5
src/lib/fileExtractor.ts
+1
-5
src/lib/fileExtractor.ts
···
1
1
import JSZip from "jszip";
2
-
import {
3
-
ParseRule,
4
-
getRulesForPlatform,
5
-
FileFormat,
6
-
} from "./platformDefinitions";
2
+
import { ParseRule, getRulesForPlatform } from "./platformDefinitions";
7
3
import { parseContent } from "./parserLogic";
8
4
9
5
// Type for the final aggregated results
+1
-1
src/lib/parserLogic.ts
+1
-1
src/lib/parserLogic.ts
-1
src/pages/Loading.tsx
-1
src/pages/Loading.tsx
+1
-1
src/pages/Login.tsx
+1
-1
src/pages/Login.tsx
+1
-70
src/pages/Settings.tsx
+1
-70
src/pages/Settings.tsx
···
1
-
import {
2
-
Settings as SettingsIcon,
3
-
Sparkles,
4
-
Shield,
5
-
Trash2,
6
-
Download,
7
-
ChevronRight,
8
-
} from "lucide-react";
1
+
import { Settings as SettingsIcon, ChevronRight } from "lucide-react";
9
2
import { PLATFORMS } from "../constants/platforms";
10
3
import { ATPROTO_APPS } from "../constants/atprotoApps";
11
4
import type { UserSettings, PlatformDestinations } from "../types/settings";
···
28
21
[platform]: destination,
29
22
},
30
23
});
31
-
};
32
-
33
-
const handleExportSettings = () => {
34
-
const dataStr = JSON.stringify(userSettings, null, 2);
35
-
const dataUri =
36
-
"data:application/json;charset=utf-8," + encodeURIComponent(dataStr);
37
-
const exportFileDefaultName = "atlast-settings.json";
38
-
39
-
const linkElement = document.createElement("a");
40
-
linkElement.setAttribute("href", dataUri);
41
-
linkElement.setAttribute("download", exportFileDefaultName);
42
-
linkElement.click();
43
-
};
44
-
45
-
const handleResetSettings = () => {
46
-
if (
47
-
confirm(
48
-
"Are you sure you want to reset all settings to defaults? This cannot be undone.",
49
-
)
50
-
) {
51
-
const { DEFAULT_SETTINGS } = require("../types/settings");
52
-
onSettingsUpdate({
53
-
...DEFAULT_SETTINGS,
54
-
wizardCompleted: true,
55
-
});
56
-
}
57
24
};
58
25
59
26
return (
···
275
242
</div>
276
243
)}
277
244
</div>
278
-
279
-
{/* Export Settings Button */}
280
-
{/*<button
281
-
onClick={handleExportSettings}
282
-
className="w-full flex items-start space-x-4 p-4 bg-purple-100/20 dark:bg-slate-900/50 hover:bg-purple-100/40 dark:hover:bg-slate-900/70 rounded-xl transition-all text-left border-2 border-orange-650/30 dark:border-amber-400/30 hover:border-orange-500 dark:hover:border-orange-400 shadow-md hover:shadow-lg"
283
-
>
284
-
<div className="w-12 h-12 bg-gradient-to-r from-gray-400 to-gray-600 rounded-xl flex items-center justify-center flex-shrink-0 shadow-md">
285
-
<Download className="w-6 h-6 text-white" />
286
-
</div>
287
-
<div className="flex-1 min-w-0">
288
-
<div className="font-semibold text-purple-950 dark:text-cyan-50 leading-tight mb-1">
289
-
Export Settings
290
-
</div>
291
-
<p className="text-sm text-purple-750 dark:text-cyan-250 leading-tight">
292
-
Download your settings as a JSON file
293
-
</p>
294
-
</div>
295
-
</button>*/}
296
-
297
-
{/* Delete Data Button */}
298
-
{/*<button
299
-
onClick={handleResetSettings}
300
-
className="w-full flex items-start space-x-4 p-4 bg-red-50/50 dark:bg-red-900/20 hover:bg-red-50 dark:hover:bg-red-900/30 rounded-xl transition-all text-left border-2 border-red-200/50 dark:border-red-800/50 hover:border-red-400 dark:hover:border-red-600 shadow-md hover:shadow-lg"
301
-
>
302
-
<div className="w-12 h-12 bg-gradient-to-r from-red-500 to-red-600 rounded-xl flex items-center justify-center flex-shrink-0 shadow-md">
303
-
<Trash2 className="w-6 h-6 text-white" />
304
-
</div>
305
-
<div className="flex-1 min-w-0">
306
-
<div className="font-semibold text-red-700 dark:text-red-400 leading-tight mb-1">
307
-
Reset All Settings
308
-
</div>
309
-
<p className="text-sm text-red-600 dark:text-red-300 leading-tight">
310
-
Restore all settings to default values
311
-
</p>
312
-
</div>
313
-
</button>*/}
314
245
</div>
315
246
</div>
316
247
</div>