fix: AI slop

This commit is contained in:
2025-06-18 14:48:40 +01:00
parent 9290443a20
commit 84b475d11a
6 changed files with 96 additions and 82 deletions

View File

@ -35,19 +35,20 @@ export default function MirrorSuggestions({ servers }: MirrorSuggestionsProps) {
async function fetchSuggestions() {
if (!pub || !login?.pubkey) return;
if (loading) return;
try {
setLoading(true);
setError(undefined);
const fileMap: Map<string, FileMirrorSuggestion> = new Map();
// Fetch files from each server
for (const serverUrl of servers) {
try {
const blossom = new Blossom(serverUrl, pub);
const files = await blossom.list(login.pubkey);
for (const file of files) {
const suggestion = fileMap.get(file.sha256);
if (suggestion) {
@ -68,7 +69,7 @@ export default function MirrorSuggestions({ servers }: MirrorSuggestionsProps) {
// Continue with other servers instead of failing completely
}
}
// Determine missing servers for each file
for (const suggestion of fileMap.values()) {
for (const serverUrl of servers) {
@ -77,12 +78,12 @@ export default function MirrorSuggestions({ servers }: MirrorSuggestionsProps) {
}
}
}
// Filter to only files that are missing from at least one server and available on at least one
const filteredSuggestions = Array.from(fileMap.values()).filter(
s => s.missing_from.length > 0 && s.available_on.length > 0
);
setSuggestions(filteredSuggestions);
} catch (e) {
if (e instanceof Error) {
@ -97,23 +98,23 @@ export default function MirrorSuggestions({ servers }: MirrorSuggestionsProps) {
async function mirrorFile(suggestion: FileMirrorSuggestion, targetServer: string) {
if (!pub) return;
const mirrorKey = `${suggestion.sha256}-${targetServer}`;
setMirroring(prev => new Set(prev.add(mirrorKey)));
try {
const blossom = new Blossom(targetServer, pub);
await blossom.mirror(suggestion.url);
// Update suggestions by removing this server from missing_from
setSuggestions(prev =>
prev.map(s =>
s.sha256 === suggestion.sha256
setSuggestions(prev =>
prev.map(s =>
s.sha256 === suggestion.sha256
? {
...s,
available_on: [...s.available_on, targetServer],
missing_from: s.missing_from.filter(server => server !== targetServer)
}
...s,
available_on: [...s.available_on, targetServer],
missing_from: s.missing_from.filter(server => server !== targetServer)
}
: s
).filter(s => s.missing_from.length > 0) // Remove suggestions with no missing servers
);
@ -174,14 +175,14 @@ export default function MirrorSuggestions({ servers }: MirrorSuggestionsProps) {
<p className="text-gray-400 mb-6">
The following files are missing from some of your servers and can be mirrored:
</p>
<div className="space-y-4">
{suggestions.map((suggestion) => (
<div key={suggestion.sha256} className="bg-gray-800 border border-gray-700 rounded-lg p-4">
<div className="flex items-start justify-between mb-3">
<div className="flex-1">
<p className="text-sm font-medium text-gray-300 mb-1">
File: {suggestion.sha256.substring(0, 16)}...
File: {suggestion.sha256}
</p>
<p className="text-xs text-gray-400">
Size: {FormatBytes(suggestion.size)}
@ -189,7 +190,7 @@ export default function MirrorSuggestions({ servers }: MirrorSuggestionsProps) {
</p>
</div>
</div>
<div className="space-y-2">
<div>
<p className="text-xs text-green-400 mb-1">Available on:</p>
@ -201,14 +202,14 @@ export default function MirrorSuggestions({ servers }: MirrorSuggestionsProps) {
))}
</div>
</div>
<div>
<p className="text-xs text-red-400 mb-1">Missing from:</p>
<div className="flex flex-wrap gap-2">
{suggestion.missing_from.map((server) => {
const mirrorKey = `${suggestion.sha256}-${server}`;
const isMirroring = mirroring.has(mirrorKey);
return (
<div key={server} className="flex items-center gap-2">
<span className="text-xs bg-red-900/30 text-red-300 px-2 py-1 rounded">

View File

@ -43,3 +43,6 @@ export function FormatBytes(b: number, f?: number) {
if (b >= kiB) return (b / kiB).toFixed(f) + " KiB";
return b.toFixed(f) + " B";
}
export const ServerUrl =
import.meta.env.VITE_API_URL || `${location.protocol}//${location.host}`;

View File

@ -1,26 +1,22 @@
import { useMemo } from "react";
import useLogin from "./login";
import { useRequestBuilder } from "@snort/system-react";
import { EventKind, RequestBuilder } from "@snort/system";
import { appendDedupe, dedupe, removeUndefined, sanitizeRelayUrl } from "@snort/shared";
import { ServerUrl } from "../const";
const DefaultMediaServers = ["https://cdn.satellite.earth/", "https://cdn.self.hosted/"];
const DefaultMediaServers = ["https://blossom.band/", "https://blossom.primal.net", ServerUrl];
export function useBlossomServers() {
const login = useLogin();
return useMemo(() => {
// For now, just return default servers
// TODO: Implement proper nostr event kind 10063 querying when system supports it
const servers = DefaultMediaServers;
const rb = new RequestBuilder("media-servers");
if (login?.pubkey) {
rb.withFilter()
.kinds([10_063 as EventKind])
.authors([login.pubkey]);
}
const req = useRequestBuilder(rb);
return {
servers,
addServer: async (serverUrl: string) => {
// TODO: Implement adding server to event kind 10063
console.log("Adding server not implemented yet:", serverUrl);
},
removeServer: async (serverUrl: string) => {
// TODO: Implement removing server from event kind 10063
console.log("Removing server not implemented yet:", serverUrl);
},
};
}, [login?.pubkey]);
const servers = req === undefined ? undefined : dedupe(removeUndefined(req.flatMap((e) => e.tags.filter(t => t[0] === "server").map((t) => sanitizeRelayUrl(t[1])))));
return appendDedupe(DefaultMediaServers, servers);
}

View File

@ -65,7 +65,7 @@ export class Blossom {
const rsp = await this.#req(
"mirror",
"PUT",
"mirror",
"upload",
JSON.stringify({ url }),
undefined,
{

View File

@ -11,7 +11,7 @@ import useLogin from "../hooks/login";
import usePublisher from "../hooks/publisher";
import { Nip96, Nip96FileList } from "../upload/nip96";
import { AdminSelf, Route96 } from "../upload/admin";
import { FormatBytes } from "../const";
import { FormatBytes, ServerUrl } from "../const";
import { UploadProgress } from "../upload/progress";
export default function Upload() {
@ -25,14 +25,11 @@ export default function Upload() {
const [isUploading, setIsUploading] = useState(false);
const [uploadProgress, setUploadProgress] = useState<UploadProgress>();
const { servers: blossomServers } = useBlossomServers();
const blossomServers = useBlossomServers();
const login = useLogin();
const pub = usePublisher();
const url =
import.meta.env.VITE_API_URL || `${location.protocol}//${location.host}`;
// Check if file should have compression enabled by default
const shouldCompress = (file: File) => {
return file.type.startsWith('video/') || file.type.startsWith('image/');
@ -52,7 +49,7 @@ export default function Upload() {
setUploadProgress(progress);
};
const uploader = new Blossom(url, pub);
const uploader = new Blossom(ServerUrl, pub);
// Use compression by default for video and image files, unless explicitly disabled
const useCompression = shouldCompress(file) && !noCompress;
const result = useCompression
@ -75,11 +72,11 @@ export default function Upload() {
async function handleFileSelection() {
if (isUploading) return;
try {
const files = await openFiles();
if (!files || files.length === 0) return;
// Start uploading each file immediately
for (let i = 0; i < files.length; i++) {
const file = files[i];
@ -99,7 +96,7 @@ export default function Upload() {
if (!pub) return;
try {
setError(undefined);
const uploader = new Nip96(url, pub);
const uploader = new Nip96(ServerUrl, pub);
await uploader.loadInfo();
const result = await uploader.listFiles(n, 50);
setListedFiles(result);
@ -115,14 +112,14 @@ export default function Upload() {
}
}
},
[pub, url],
[pub],
);
async function deleteFile(id: string) {
if (!pub) return;
try {
setError(undefined);
const uploader = new Blossom(url, pub);
const uploader = new Blossom(ServerUrl, pub);
await uploader.delete(id);
} catch (e) {
if (e instanceof Error) {
@ -143,10 +140,10 @@ export default function Upload() {
useEffect(() => {
if (pub && !self) {
const r96 = new Route96(url, pub);
const r96 = new Route96(ServerUrl, pub);
r96.getSelf().then((v) => setSelf(v.data));
}
}, [pub, self, url]);
}, [pub, self]);
if (!login) {
return (
@ -189,8 +186,8 @@ export default function Upload() {
{/* Upload Progress */}
{isUploading && uploadProgress && (
<ProgressBar
progress={uploadProgress}
<ProgressBar
progress={uploadProgress}
/>
)}
@ -240,13 +237,12 @@ export default function Upload() {
</div>
<div className="w-full bg-gray-700 rounded-full h-2.5">
<div
className={`h-2.5 rounded-full transition-all duration-300 ${
self.total_size / self.total_available_quota > 0.8
className={`h-2.5 rounded-full transition-all duration-300 ${self.total_size / self.total_available_quota > 0.8
? "bg-red-500"
: self.total_size / self.total_available_quota > 0.6
? "bg-yellow-500"
: "bg-green-500"
}`}
}`}
style={{
width: `${Math.min(100, (self.total_size / self.total_available_quota) * 100)}%`,
}}
@ -261,13 +257,12 @@ export default function Upload() {
% used
</span>
<span
className={`${
self.total_size / self.total_available_quota > 0.8
className={`${self.total_size / self.total_available_quota > 0.8
? "text-red-400"
: self.total_size / self.total_available_quota > 0.6
? "text-yellow-400"
: "text-green-400"
}`}
}`}
>
{FormatBytes(
Math.max(
@ -332,7 +327,7 @@ export default function Upload() {
{showPaymentFlow && pub && (
<div className="card">
<PaymentFlow
route96={new Route96(url, pub)}
route96={new Route96(ServerUrl, pub)}
onPaymentRequested={(pr) => {
console.log("Payment requested:", pr);
}}
@ -342,9 +337,9 @@ export default function Upload() {
)}
{/* Mirror Suggestions */}
{blossomServers.length > 1 && (
<MirrorSuggestions
servers={blossomServers}
{blossomServers && blossomServers.length > 1 && (
<MirrorSuggestions
servers={blossomServers}
/>
)}