fix image uploads
123412345678131491011121311 unmodified lines2526272834353629303132333441353637383940414243505152534445464748495073 unmodified lines<script lang="ts" module> const profileCache = new SvelteMap<string, { displayName?: string; handle: string }>();</script>
<script lang="ts"> import ProfilePicture from './ProfilePicture.svelte'; import BlockedUserIndicator from './BlockedUserIndicator.svelte'; import { getRelativeTime } from '$lib/date'; import { generateColorForDid } from '$lib/accounts'; import type { Did } from '@atcute/lexicons'; import type { calculateFollowedUserStats, Sort } from '$lib/following'; import { resolveDidDoc, type AtpClient } from '$lib/at/client.svelte'; import { SvelteMap } from 'svelte/reactivity'; import { router, getBlockRelationship } from '$lib/state.svelte'; import { router, getBlockRelationship, profiles, handles } from '$lib/state.svelte'; import { map } from '$lib/result';
interface Props { style: string;11 unmodified lines userDid ? getBlockRelationship(userDid, did) : { userBlocked: false, blockedByTarget: false } ); const isBlocked = $derived(blockRel.userBlocked || blockRel.blockedByTarget);
const cached = $derived(profileCache.get(did)); const displayName = $derived(cached?.displayName); const handle = $derived(cached?.handle ?? 'handle.invalid'); const displayName = $derived(profiles.get(did)?.displayName); const handle = $derived(handles.get(did) ?? 'loading...');
let error = $state('');
const loadProfile = async (targetDid: Did) => { if (profileCache.has(targetDid)) return; if (profiles.has(targetDid) && handles.has(targetDid)) return;
try { const [profileRes, handleRes] = await Promise.all([ client.getProfile(targetDid), resolveDidDoc(targetDid).then((r) => map(r, (doc) => doc.handle)) ]); if (did !== targetDid) return;
profileCache.set(targetDid, { handle: handleRes.ok ? handleRes.value : handle, displayName: profileRes.ok ? profileRes.value.displayName : displayName }); if (profileRes.ok) profiles.set(targetDid, profileRes.value); if (handleRes.ok) handles.set(targetDid, handleRes.value); else handles.set(targetDid, 'handle.invalid'); } catch (e) { if (did !== targetDid) return; console.error(`failed to load profile for ${targetDid}`, e); error = String(e);73 unmodified lines42 unmodified lines4344454647484748495051523 unmodified lines56575859606160616263646534 unmodified lines10010110210310410410510610710846 unmodified lines15515615715815916016116216316416516616716816916217017117217317452 unmodified lines227228229230223224225231232233234235236237228 unmodified linesExpand all466467468469462463464470471472473474249 unmodified linesExpand all42 unmodified lines client.user?.did ? generateColorForDid(client.user?.did) : 'var(--nucleus-accent2)' );
const uploadVideo = async (blobUrl: string, mimeType: string) => { const blob = await (await fetch(blobUrl)).blob(); return await client.uploadVideo(blob, mimeType, (status) => { const file = await (await fetch(blobUrl)).blob(); return await client.uploadVideo(file, mimeType, (status) => { if (status.stage === 'uploading' && status.progress !== undefined) { _state.blobsState.set(blobUrl, { state: 'uploading', progress: status.progress * 0.5 }); } else if (status.stage === 'processing' && status.progress !== undefined) { _state.blobsState.set(blobUrl, {3 unmodified lines } }); }; const uploadImage = async (blobUrl: string) => { const blob = await (await fetch(blobUrl)).blob(); return await client.uploadBlob(blob, (progress) => { const file = await (await fetch(blobUrl)).blob(); return await client.uploadBlob(file, (progress) => { _state.blobsState.set(blobUrl, { state: 'uploading', progress }); }); };
34 unmodified lines $type: 'app.bsky.embed.video', video: upload.blob }; } console.log('media', media); // console.log('media', media);
const record: AppBskyFeedPost.Main = { $type: 'app.bsky.feed.post', text: rt.text,46 unmodified lines let textareaEl: HTMLTextAreaElement | undefined = $state(); let fileInputEl: HTMLInputElement | undefined = $state(); let selectingFile = $state(false);
const canUpload = $derived( !( _state.attachedMedia?.$type === 'app.bsky.embed.video' || (_state.attachedMedia?.$type === 'app.bsky.embed.images' && _state.attachedMedia.images.length >= 4) ) );
const unfocus = () => (_state.focus = 'null');
const handleFiles = (files: File[]) => { if (!files || files.length === 0) return; if (!canUpload || !files || files.length === 0) return;
const existingImages = _state.attachedMedia?.$type === 'app.bsky.embed.images' ? _state.attachedMedia.images : [];
52 unmodified lines images: newImages }; }
const handleUpload = (blobUrl: string, blob: Result<AtpBlob<string>, string>) => { if (blob.ok) _state.blobsState.set(blobUrl, { state: 'uploaded', blob: blob.value }); else _state.blobsState.set(blobUrl, { state: 'error', message: blob.error }); const handleUpload = (blobUrl: string, res: Result<AtpBlob<string>, string>) => { if (res.ok) _state.blobsState.set(blobUrl, { state: 'uploaded', blob: res.value }); else _state.blobsState.set(blobUrl, { state: 'error', message: res.error }); };
const media = _state.attachedMedia; if (media?.$type == 'app.bsky.embed.images') {228 unmodified linesExpand all selectingFile = true; fileInputEl?.click(); }} onmousedown={(e) => e.preventDefault()} disabled={_state.attachedMedia?.$type === 'app.bsky.embed.video' || (_state.attachedMedia?.$type === 'app.bsky.embed.images' && _state.attachedMedia.images.length >= 4)} disabled={!canUpload} class="rounded-sm p-1.5 transition-all duration-150 enabled:hover:scale-110 disabled:cursor-not-allowed disabled:opacity-50" style="background: color-mix(in srgb, {color} 15%, transparent); color: {color};" title="attach media" >249 unmodified linesExpand all325 unmodified linesExpand all326327328329330330331332333334156 unmodified linesExpand all325 unmodified linesExpand all { authorization: `Bearer ${tokenResult.value}` }, (uploaded, total) => onProgress?.(uploaded / total) ); if (!result.ok) return err(`upload failed: ${result.error.message}`); return ok(result.value); return ok(result.value.blob); }
async uploadVideo( blob: Blob,156 unmodified linesExpand all