tangled
alpha
login
or
join now
whey.party
/
red-dwarf
83
fork
atom
an independent Bluesky client using Constellation, PDS Queries, and other services
reddwarf.app
frontend
spa
bluesky
reddwarf
microcosm
client
app
83
fork
atom
overview
issues
25
pulls
pipelines
reposted by indicators
rimar1337
6 months ago
78b79fd1
bd1ce421
+58
-15
2 changed files
expand all
collapse all
unified
split
src
components
InfiniteCustomFeed.tsx
UniversalPostRenderer.tsx
+33
-9
src/components/InfiniteCustomFeed.tsx
···
2
//import { useInView } from "react-intersection-observer";
3
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
4
import { useAuth } from "~/providers/PassAuthProvider";
5
-
import { useQueryArbitrary, useQueryIdentity, useInfiniteQueryFeedSkeleton } from "~/utils/useQuery";
0
0
0
0
6
7
interface InfiniteCustomFeedProps {
8
feedUri: string;
···
10
feedServiceDid?: string;
11
}
12
13
-
export function InfiniteCustomFeed({ feedUri, pdsUrl, feedServiceDid }: InfiniteCustomFeedProps) {
0
0
0
0
14
const { agent, authed } = useAuth();
15
-
16
// const identityresultmaybe = useQueryIdentity(agent?.did);
17
// const identity = identityresultmaybe?.data;
18
// const feedGenGetRecordQuery = useQueryArbitrary(feedUri);
···
46
}
47
48
if (isError) {
49
-
return <div className="p-4 text-center text-red-500">Error: {error.message}</div>;
0
0
50
}
51
52
-
const allPosts = data?.pages.flatMap((page) => {if (page) return page.feed}) ?? [];
0
0
0
53
54
if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) {
55
-
return <div className="p-4 text-center text-gray-500">No posts in this feed.</div>;
0
0
0
0
56
}
57
58
return (
59
<>
60
{allPosts.map((item, i) => {
61
-
if (item) return (
62
-
<UniversalPostRendererATURILoader key={item.post || i} atUri={item.post} />
63
-
)})}
0
0
0
0
0
0
0
64
{/* allPosts?: {allPosts ? "true" : "false"}
65
hasNextPage?: {hasNextPage ? "true" : "false"}
66
isFetchingNextPage?: {isFetchingNextPage ? "true" : "false"} */}
···
2
//import { useInView } from "react-intersection-observer";
3
import { UniversalPostRendererATURILoader } from "~/components/UniversalPostRenderer";
4
import { useAuth } from "~/providers/PassAuthProvider";
5
+
import {
6
+
useQueryArbitrary,
7
+
useQueryIdentity,
8
+
useInfiniteQueryFeedSkeleton,
9
+
} from "~/utils/useQuery";
10
11
interface InfiniteCustomFeedProps {
12
feedUri: string;
···
14
feedServiceDid?: string;
15
}
16
17
+
export function InfiniteCustomFeed({
18
+
feedUri,
19
+
pdsUrl,
20
+
feedServiceDid,
21
+
}: InfiniteCustomFeedProps) {
22
const { agent, authed } = useAuth();
23
+
24
// const identityresultmaybe = useQueryIdentity(agent?.did);
25
// const identity = identityresultmaybe?.data;
26
// const feedGenGetRecordQuery = useQueryArbitrary(feedUri);
···
54
}
55
56
if (isError) {
57
+
return (
58
+
<div className="p-4 text-center text-red-500">Error: {error.message}</div>
59
+
);
60
}
61
62
+
const allPosts =
63
+
data?.pages.flatMap((page) => {
64
+
if (page) return page.feed;
65
+
}) ?? [];
66
67
if (!allPosts || typeof allPosts !== "object" || allPosts.length === 0) {
68
+
return (
69
+
<div className="p-4 text-center text-gray-500">
70
+
No posts in this feed.
71
+
</div>
72
+
);
73
}
74
75
return (
76
<>
77
{allPosts.map((item, i) => {
78
+
if (item)
79
+
return (
80
+
<UniversalPostRendererATURILoader
81
+
key={item.post || i}
82
+
atUri={item.post}
83
+
feedviewpost={true}
84
+
repostedby={!!item.reason?.$type && (item.reason as any)?.repost}
85
+
/>
86
+
);
87
+
})}
88
{/* allPosts?: {allPosts ? "true" : "false"}
89
hasNextPage?: {hasNextPage ? "true" : "false"}
90
isFetchingNextPage?: {isFetchingNextPage ? "true" : "false"} */}
+25
-6
src/components/UniversalPostRenderer.tsx
···
25
topReplyLine?: boolean;
26
bottomBorder?: boolean;
27
feedviewpost?: boolean;
0
28
}
29
30
// export async function cachedGetRecord({
···
128
topReplyLine,
129
bottomBorder = true,
130
feedviewpost = false,
0
131
}: UniversalPostRendererATURILoaderProps) {
132
console.log("atUri", atUri);
133
//const { get, set } = usePersistentStore();
···
381
// });
382
// }
383
// };
0
0
0
0
384
385
return (
386
<UniversalPostRendererRawRecordShim
···
396
topReplyLine={topReplyLine}
397
bottomBorder={bottomBorder}
398
feedviewpost={feedviewpost}
0
399
/>
400
);
401
}
···
413
topReplyLine = false,
414
bottomBorder = true,
415
feedviewpost = false,
0
416
}: {
417
postRecord: any;
418
profileRecord: any;
···
426
topReplyLine?: boolean;
427
bottomBorder?: boolean;
428
feedviewpost?: boolean;
0
429
}) {
430
console.log(`received aturi: ${aturi} of post content: ${postRecord}`);
431
const navigate = useNavigate();
···
583
feedviewpost ? feedviewpostreplydid : undefined
584
);
585
const feedviewpostreplyhandle = replyhookvalue?.data?.handle;
0
0
0
0
0
0
0
586
return (
587
<>
588
{/* <p>
···
616
bottomBorder={bottomBorder}
617
//extraOptionalItemInfo={{reply: postRecord?.value?.reply as AppBskyFeedDefs.ReplyRef, post: fakepost}}
618
feedviewpostreplyhandle={feedviewpostreplyhandle}
0
619
/>
620
</>
621
);
···
1058
bottomBorder = true,
1059
feedviewpostreplyhandle,
1060
depth = 0,
0
1061
}: {
1062
post: PostView;
1063
// optional for now because i havent ported every use to this yet
···
1076
bottomBorder?: boolean;
1077
feedviewpostreplyhandle?: string;
1078
depth?: number;
0
1079
}) {
1080
const navigate = useNavigate();
1081
const [hasRetweeted, setHasRetweeted] = useState<Boolean>(
···
1124
}
1125
};
1126
1127
-
const isRepost = extraOptionalItemInfo
1128
? AppBskyFeedDefs.isReasonRepost(extraOptionalItemInfo.reason)
1129
? extraOptionalItemInfo.reason?.by.displayName
1130
: undefined
···
1190
}}
1191
className="text-gray-500 dark:text-gray-400"
1192
>
1193
-
<MdiRepost /> Reposted by {isRepost}{" "}
1194
</div>
1195
)}
1196
{!isQuote && (
···
1292
maxWidth: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1293
width: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1294
marginLeft: !expanded ? (isQuote ? 26 : 0) : 54,
1295
-
marginBottom: !expanded ? 4 : 0,
1296
}}
1297
>
1298
<div
···
1308
gap: expanded ? 0 : 6,
1309
alignItems: expanded ? "flex-start" : "center",
1310
flexDirection: expanded ? "column" : "row",
1311
-
height: expanded ? 48 : "1rem",
1312
}}
1313
>
1314
<span
···
1395
}}
1396
className="text-gray-500 dark:text-gray-400"
1397
>
1398
-
<MdiReply /> Reply to {feedviewpostreplyhandle}
1399
</div>
1400
)}
1401
<div
···
1428
) : null}
1429
{post.embed && depth > 0 && (
1430
<>
1431
-
<div className="border-gray-300 dark:border-gray-600 p-3 rounded-xl border italic text-gray-400">
1432
(there is an embed here thats too deep to render)
1433
</div>
1434
</>
···
25
topReplyLine?: boolean;
26
bottomBorder?: boolean;
27
feedviewpost?: boolean;
28
+
repostedby?: string;
29
}
30
31
// export async function cachedGetRecord({
···
129
topReplyLine,
130
bottomBorder = true,
131
feedviewpost = false,
132
+
repostedby,
133
}: UniversalPostRendererATURILoaderProps) {
134
console.log("atUri", atUri);
135
//const { get, set } = usePersistentStore();
···
383
// });
384
// }
385
// };
386
+
if (!postQuery?.value) {
387
+
// deleted post more often than a non-resolvable post
388
+
return (<></>)
389
+
}
390
391
return (
392
<UniversalPostRendererRawRecordShim
···
402
topReplyLine={topReplyLine}
403
bottomBorder={bottomBorder}
404
feedviewpost={feedviewpost}
405
+
repostedby={repostedby}
406
/>
407
);
408
}
···
420
topReplyLine = false,
421
bottomBorder = true,
422
feedviewpost = false,
423
+
repostedby,
424
}: {
425
postRecord: any;
426
profileRecord: any;
···
434
topReplyLine?: boolean;
435
bottomBorder?: boolean;
436
feedviewpost?: boolean;
437
+
repostedby?: string;
438
}) {
439
console.log(`received aturi: ${aturi} of post content: ${postRecord}`);
440
const navigate = useNavigate();
···
592
feedviewpost ? feedviewpostreplydid : undefined
593
);
594
const feedviewpostreplyhandle = replyhookvalue?.data?.handle;
595
+
596
+
597
+
const aturirepostbydid = repostedby ? new AtUri(repostedby).host : undefined
598
+
const repostedbyhookvalue = useQueryIdentity(
599
+
repostedby ? aturirepostbydid : undefined
600
+
);
601
+
const feedviewpostrepostedbyhandle = repostedbyhookvalue?.data?.handle;
602
return (
603
<>
604
{/* <p>
···
632
bottomBorder={bottomBorder}
633
//extraOptionalItemInfo={{reply: postRecord?.value?.reply as AppBskyFeedDefs.ReplyRef, post: fakepost}}
634
feedviewpostreplyhandle={feedviewpostreplyhandle}
635
+
repostedby={feedviewpostrepostedbyhandle}
636
/>
637
</>
638
);
···
1075
bottomBorder = true,
1076
feedviewpostreplyhandle,
1077
depth = 0,
1078
+
repostedby,
1079
}: {
1080
post: PostView;
1081
// optional for now because i havent ported every use to this yet
···
1094
bottomBorder?: boolean;
1095
feedviewpostreplyhandle?: string;
1096
depth?: number;
1097
+
repostedby?: string;
1098
}) {
1099
const navigate = useNavigate();
1100
const [hasRetweeted, setHasRetweeted] = useState<Boolean>(
···
1143
}
1144
};
1145
1146
+
const isRepost = repostedby ? repostedby : extraOptionalItemInfo
1147
? AppBskyFeedDefs.isReasonRepost(extraOptionalItemInfo.reason)
1148
? extraOptionalItemInfo.reason?.by.displayName
1149
: undefined
···
1209
}}
1210
className="text-gray-500 dark:text-gray-400"
1211
>
1212
+
<MdiRepost /> Reposted by @{isRepost}{" "}
1213
</div>
1214
)}
1215
{!isQuote && (
···
1311
maxWidth: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1312
width: `calc(100% - ${!expanded ? (isQuote ? 26 : 0) : 54}px)`,
1313
marginLeft: !expanded ? (isQuote ? 26 : 0) : 54,
1314
+
marginBottom: !expanded ? 4 : 6,
1315
}}
1316
>
1317
<div
···
1327
gap: expanded ? 0 : 6,
1328
alignItems: expanded ? "flex-start" : "center",
1329
flexDirection: expanded ? "column" : "row",
1330
+
height: expanded ? 42 : "1rem",
1331
}}
1332
>
1333
<span
···
1414
}}
1415
className="text-gray-500 dark:text-gray-400"
1416
>
1417
+
<MdiReply /> Reply to @{feedviewpostreplyhandle}
1418
</div>
1419
)}
1420
<div
···
1447
) : null}
1448
{post.embed && depth > 0 && (
1449
<>
1450
+
<div className="border-gray-300 dark:border-gray-600 p-3 rounded-xl border italic text-gray-400 text-[14px]">
1451
(there is an embed here thats too deep to render)
1452
</div>
1453
</>