tangled
alpha
login
or
join now
whey.party
/
red-dwarf
82
fork
atom
an independent Bluesky client using Constellation, PDS Queries, and other services
reddwarf.app
frontend
spa
bluesky
reddwarf
microcosm
client
app
82
fork
atom
overview
issues
25
pulls
pipelines
post content hider
whey.party
1 month ago
cde0d3df
36d82759
+251
-86
3 changed files
expand all
collapse all
unified
split
src
auto-imports.d.ts
components
LogoSvg.tsx
UniversalPostRenderer.tsx
+2
src/auto-imports.d.ts
···
24
const IconMdiCheck: typeof import('~icons/mdi/check.jsx').default
25
const IconMdiCheckCircle: typeof import('~icons/mdi/check-circle.jsx').default
26
const IconMdiCheckboxMultipleMarked: typeof import('~icons/mdi/checkbox-multiple-marked.jsx').default
0
27
const IconMdiClock: typeof import('~icons/mdi/clock.jsx').default
28
const IconMdiClockOutline: typeof import('~icons/mdi/clock-outline.jsx').default
29
const IconMdiClose: typeof import('~icons/mdi/close.jsx').default
···
42
const IconMdiShield: typeof import('~icons/mdi/shield.jsx').default
43
const IconMdiShieldOutline: typeof import('~icons/mdi/shield-outline.jsx').default
44
const IconMdiVerified: typeof import('~icons/mdi/verified.jsx').default
0
45
}
···
24
const IconMdiCheck: typeof import('~icons/mdi/check.jsx').default
25
const IconMdiCheckCircle: typeof import('~icons/mdi/check-circle.jsx').default
26
const IconMdiCheckboxMultipleMarked: typeof import('~icons/mdi/checkbox-multiple-marked.jsx').default
27
+
const IconMdiChevronDown: typeof import('~icons/mdi/chevron-down.jsx').default
28
const IconMdiClock: typeof import('~icons/mdi/clock.jsx').default
29
const IconMdiClockOutline: typeof import('~icons/mdi/clock-outline.jsx').default
30
const IconMdiClose: typeof import('~icons/mdi/close.jsx').default
···
43
const IconMdiShield: typeof import('~icons/mdi/shield.jsx').default
44
const IconMdiShieldOutline: typeof import('~icons/mdi/shield-outline.jsx').default
45
const IconMdiVerified: typeof import('~icons/mdi/verified.jsx').default
46
+
const IconMdiWarning: typeof import('~icons/mdi/warning.jsx').default
47
}
+77
src/components/LogoSvg.tsx
···
76
</svg>)
77
}
78
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
79
// defaultpfp
80
export function DefaultPFP(props: SVGProps<SVGSVGElement>) {
81
return (
···
76
</svg>)
77
}
78
79
+
// candidate for default
80
+
export function WheyMadeModernistMonogram2Partial(props: SVGProps<SVGSVGElement>) {
81
+
return (
82
+
<svg
83
+
viewBox="0 0 512 512"
84
+
version="1.1"
85
+
xmlns="http://www.w3.org/2000/svg"
86
+
{...props}
87
+
>
88
+
<title>Logotype 2partial</title>
89
+
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
90
+
<g id="Logotype-partial" transform="translate(25, 25)" fill="currentColor">
91
+
<path d="M231,2.27373675e-13 C358.577777,2.27373675e-13 462,103.422223 462,231 C462,358.577777 358.577777,462 231,462 Z" id="Half"></path>
92
+
<circle id="Oval" cx="115.5" cy="115.5" r="115.5"></circle>
93
+
<path d="M0.082,231 L0.083,231.001 L3.82032351,231.030947 C129.607985,233.070408 230.954808,335.652489 230.999823,461.916004 L231.000162,461.999838 L230.877,461.999 L230.999838,461.99916 C230.999838,461.97144 230.999833,461.943722 230.999823,461.916004 L0.083,231.001 L0.00032417037,231 L0.0312715054,234.82001 C2.07117982,360.63597 104.698104,462.000162 230.999838,462.000162 L230.877,461.999 L0,461.999838 L0,231.000324 L0.082,231 Z" id="Combined-Shape"></path>
94
+
</g>
95
+
<rect id="Rectangle" fill="currentColor" x="25" y="25" width="116" height="231"></rect>
96
+
</g>
97
+
</svg>
98
+
)
99
+
}
100
+
101
+
export function WheyMade5Square(props: SVGProps<SVGSVGElement>) {
102
+
return (
103
+
<svg
104
+
viewBox="0 0 512 512"
105
+
version="1.1"
106
+
xmlns="http://www.w3.org/2000/svg"
107
+
transform='rotate(135)'
108
+
{...props}
109
+
>
110
+
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
111
+
<g id="Logotype-5Square" transform="translate(0.4991, -0.0005)" fill="currentColor">
112
+
<path d="M255.500876,25.0005352 C383.078653,25.0005352 486.500876,128.422758 486.500876,256.000535 C486.500876,356.786979 421.955067,442.497942 331.945007,474.051864 L331.3,474.272 L381.857,512 L0.000430968674,512.000535 L1.42108547e-14,130.312 L37.229,180.2 L37.4495474,179.556404 C68.6040527,90.6857123 152.553212,26.6386865 251.680869,25.0314826 L255.500876,25.0005352 Z M512,288.919 L512.000431,512.000535 L482.724,512 L480.160326,311.436715 L512,288.919 Z M50.543,362.647 L0.0982429603,511.403168 L148.855,460.958 L146.179023,459.545342 C106.285176,438.073726 73.427685,405.216235 51.9560695,365.322388 L50.543,362.647 Z M262.03074,422.579291 L148.855,460.958 L149.343076,461.216735 C181.12821,477.692535 217.227543,487.000535 255.500876,487.000535 C281.016431,487.000535 305.565765,482.863646 328.514742,475.224002 L331.3,474.272 L262.03074,422.579291 Z M37.229,180.2 L36.2774093,182.986669 C28.6377649,205.935647 24.500876,230.48498 24.500876,256.000535 C24.500876,294.273868 33.808876,330.373202 50.2846761,362.158335 L50.543,362.647 L88.9221204,249.470671 L37.229,180.2 Z M512.000431,0.00053522388 L512,91.44 L441.863205,69.6382067 L420.216,-2.84217094e-14 L512.000431,0.00053522388 Z M222.228,-2.84217094e-14 L200.064696,31.3410852 L1.42108547e-14,28.784 L0.000430968674,0.00053522388 L222.228,-2.84217094e-14 Z" id="Combined-Shape"></path>
113
+
</g>
114
+
</g>
115
+
</svg>
116
+
)
117
+
}
118
+
119
+
120
+
export function WheyMadeBoubaKiki(props: SVGProps<SVGSVGElement>) {
121
+
return (
122
+
<svg
123
+
viewBox="0 0 1047 1047"
124
+
version="1.1"
125
+
xmlns="http://www.w3.org/2000/svg"
126
+
{...props}
127
+
>
128
+
<title>Logotype-1.5Nonequal15nonequal</title>
129
+
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
130
+
<g id="Logotype-1.5Nonequal" transform="translate(0.6169, 0.861)" fill="currentColor">
131
+
<path d="M700.664553,340.034383 C715.327713,340.002333 729.11121,347.025376 737.704071,358.906959 L799.154445,443.876074 C811.895531,461.493523 834.561151,468.85803 855.224183,462.094237 L954.882173,429.472402 C978.810344,421.639806 1004.55753,434.687847 1012.39013,458.616018 C1016.95178,472.551607 1014.5318,487.830732 1005.88708,499.674639 L944.065863,584.374318 C931.247885,601.935903 931.247885,625.767946 944.065863,643.32953 L1005.88708,728.02921 C1020.73054,748.365847 1016.27743,776.884946 995.940794,791.7284 C984.096887,800.373117 968.817762,802.793093 954.882173,798.231446 L855.224183,765.609612 C834.561151,758.845819 811.895531,766.210325 799.154445,783.827774 L737.704071,868.796889 C722.949658,889.198219 694.450298,893.775951 674.048968,879.021538 C662.167385,870.428678 655.144342,856.64518 655.176392,841.982021 L655.405588,737.120939 C655.425626,727.953131 652.946531,719.22295 648.520961,711.691065 C709.97811,670.185396 750.383113,599.880758 750.383113,520.139025 C750.383113,452.082396 720.952137,390.89974 674.123265,348.624137 C681.586594,343.239367 690.752706,340.056047 700.664553,340.034383 Z M390.074839,115.030765 L389.612789,326.427069 L392.214218,327.263752 C329.654126,368.59486 288.383113,439.547262 288.383113,520.139025 C288.383113,522.478677 288.417896,524.810206 288.486973,527.133121 L390.074839,667.594601 L389.612789,456.198297 L590.805403,391.312683 L392.214218,327.263752 C428.68754,303.167195 472.397099,289.139025 519.383113,289.139025 C578.904262,289.139025 633.167544,311.650627 674.123265,348.624137 C662.616835,356.926725 655.143026,370.456226 655.176392,385.721828 L655.405588,490.582909 C655.453109,512.324748 641.444985,531.605276 620.752583,538.278678 L520.952943,570.464556 C506.997546,574.965241 496.0589,585.903886 491.558216,599.859283 C483.830293,623.821465 496.990761,649.51137 520.952943,657.239293 L620.752583,689.425171 C632.719689,693.284622 642.451108,701.360771 648.520961,711.691065 C611.659126,736.598693 567.219158,751.139025 519.383113,751.139025 C394.144989,751.139025 292.184563,651.475345 288.486973,527.133121 L266.193017,496.299812 L65.2859657,562.064299 L189.915403,391.312683 L65.2859657,220.561067 L266.193017,286.325554 L390.074839,115.030765 Z" id="Combined-Shape"></path>
132
+
</g>
133
+
</g>
134
+
</svg>
135
+
)
136
+
}
137
+
138
+
export function WheyMadeBoubaKikiLarge(props: SVGProps<SVGSVGElement>) {
139
+
return (
140
+
<svg
141
+
viewBox="0 100 1047 847"
142
+
version="1.1"
143
+
xmlns="http://www.w3.org/2000/svg"
144
+
{...props}
145
+
>
146
+
<title>Logotype-Large1.5Nonequall15nonequal</title>
147
+
<g id="Page-1" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
148
+
<g id="Logotype-Large1.5Nonequal" transform="translate(0.6169, 0.861)" fill="currentColor">
149
+
<path d="M700.664553,340.034383 C715.327713,340.002333 729.11121,347.025376 737.704071,358.906959 L799.154445,443.876074 C811.895531,461.493523 834.561151,468.85803 855.224183,462.094237 L954.882173,429.472402 C978.810344,421.639806 1004.55753,434.687847 1012.39013,458.616018 C1016.95178,472.551607 1014.5318,487.830732 1005.88708,499.674639 L944.065863,584.374318 C931.247885,601.935903 931.247885,625.767946 944.065863,643.32953 L1005.88708,728.02921 C1020.73054,748.365847 1016.27743,776.884946 995.940794,791.7284 C984.096887,800.373117 968.817762,802.793093 954.882173,798.231446 L855.224183,765.609612 C834.561151,758.845819 811.895531,766.210325 799.154445,783.827774 L737.704071,868.796889 C722.949658,889.198219 694.450298,893.775951 674.048968,879.021538 C662.167385,870.428678 655.144342,856.64518 655.176392,841.982021 L655.405588,737.120939 C655.453109,715.379101 641.444985,696.098573 620.752583,689.425171 L520.952943,657.239293 C496.990761,649.51137 483.830293,623.821465 491.558216,599.859283 C496.0589,585.903886 506.997546,574.965241 520.952943,570.464556 L620.752583,538.278678 C641.444985,531.605276 655.453109,512.324748 655.405588,490.582909 L655.176392,385.721828 C655.121361,360.544379 675.487105,340.089413 700.664553,340.034383 Z M390.074839,115.030765 L389.612789,326.427069 L590.805403,391.312683 L389.612789,456.198297 L390.074839,667.594601 L266.193017,496.299812 L65.2859657,562.064299 L189.915403,391.312683 L65.2859657,220.561067 L266.193017,286.325554 L390.074839,115.030765 Z" id="Combined-Shape"></path>
150
+
</g>
151
+
</g>
152
+
</svg>
153
+
)
154
+
}
155
+
156
// defaultpfp
157
export function DefaultPFP(props: SVGProps<SVGSVGElement>) {
158
return (
+172
-86
src/components/UniversalPostRenderer.tsx
···
21
import { useAuth } from "~/providers/UnifiedAuthProvider";
22
import { renderSnack } from "~/routes/__root";
23
//import { ModerationInner } from "~/routes/moderation";
24
-
import {
25
-
FollowButton,
26
-
Mutual,
27
-
} from "~/routes/profile.$did";
28
import type { LightboxProps } from "~/routes/profile.$did/post.$rkey.image.$i";
29
import type { ContentLabel } from "~/types/moderation";
30
import {
···
580
const { isLoading: authorModLoading, labels: authorLabels } = useModeration(
581
post.author.did,
582
);
0
0
0
583
const hideAuthorLabels = authorLabels.filter(
584
-
label => label.preference === 'hide'
585
);
586
const warnAuthorLabels = authorLabels.filter(
587
-
label => label.preference === 'warn'
588
);
589
-
0
0
0
0
0
590
591
const parsed = new AtUri(post.uri);
592
const navigate = useNavigate();
···
671
const isMainItem = false;
672
const setMainItem = (any: any) => { };
673
674
-
if (hideAuthorLabels.length > 0 ) {
675
-
return null
0
0
0
0
0
676
}
677
678
return (
···
917
</div>
918
</div>
919
{/* <ModerationInner subject={post.author.did} /> */}
920
-
{authorModLoading ?
921
-
(
922
<div className="flex flex-wrap flex-row gap-1 my-1">
923
-
<div
924
-
className="text-xs bg-gray-100 dark:bg-gray-800 px-1 py-0.5 rounded-full flex flex-row items-center gap-1"
925
-
>
926
-
{/* <img
927
src={resolvedpfp || defaultpfp}
928
alt="avatar"
929
className={`rounded-full object-cover border border-gray-300 dark:border-gray-800 bg-gray-300 dark:bg-gray-600`}
···
932
height: 12,
933
}}
934
/> */}
935
-
<span className="font-medium">loading badges...</span>
936
-
</div>
937
</div>
938
-
)
939
-
:
940
-
(
941
-
<div className="flex flex-wrap flex-row gap-1 my-1">
942
-
{warnAuthorLabels.map((label, index) => (
943
-
<SmallAuthorLabelBadge label={label} key={label.cts + label.sourceDid + label.val} />
944
-
))}
945
-
</div>
946
-
)
947
-
}
0
948
{!!feedviewpostreplyhandle && (
949
<div
950
style={{
···
968
</div>
969
)}
970
{/* <ModerationInner subject={post.uri} /> */}
971
-
<div
972
-
style={{
973
-
fontSize: 16,
974
-
marginBottom: !post.embed || concise ? 0 : 8,
975
-
whiteSpace: "pre-wrap",
976
-
textAlign: "left",
977
-
overflowWrap: "anywhere",
978
-
wordBreak: "break-word",
979
-
...(concise && {
980
-
display: "-webkit-box",
981
-
WebkitBoxOrient: "vertical",
982
-
WebkitLineClamp: 2,
983
-
overflow: "hidden",
984
-
}),
985
-
}}
986
-
className="text-gray-900 dark:text-gray-100"
987
-
>
988
-
{fedi ? (
989
-
<>
990
-
<span
991
-
className="dangerousFediContent"
992
-
dangerouslySetInnerHTML={{
993
-
__html: DOMPurify.sanitize(fedi),
994
-
}}
995
-
/>
996
-
</>
997
-
) : (
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
998
<>
999
-
{renderTextWithFacets({
1000
-
text: (post.record as { text?: string }).text ?? "",
1001
-
facets: (post.record.facets as Facet[]) ?? [],
1002
-
navigate: navigate,
1003
-
})}
1004
</>
1005
)}
1006
-
</div>
1007
-
{post.embed && depth < 1 && !concise ? (
1008
-
<PostEmbeds
1009
-
embed={post.embed}
1010
-
viewContext={PostEmbedViewContext.Feed}
1011
-
salt={salt}
1012
-
navigate={navigate}
1013
-
postid={{ did: post.author.did, rkey: parsed.rkey }}
1014
-
nopics={nopics}
1015
-
lightboxCallback={lightboxCallback}
1016
-
constellationLinks={constellationLinks}
1017
-
/>
1018
-
) : null}
1019
-
{post.embed && depth > 0 && (
1020
-
<>
1021
-
<div className="border-gray-300 dark:border-gray-800 p-3 rounded-xl border italic text-gray-400 text-[14px]">
1022
-
(there is an embed here thats too deep to render)
1023
-
</div>
1024
-
</>
1025
-
)}
1026
<div
1027
style={{
1028
paddingTop: post.embed && !concise && depth < 1 ? 4 : 0,
···
1078
}}
1079
aria-label="Repost or quote post"
1080
>
1081
-
{hasRetweeted ? <IconMdiRepeat color="#5CEFAA" /> : <IconMdiRepeat />}
0
0
0
0
1082
{post.repostCount ?? 0}
1083
</div>
1084
</DropdownMenu.Trigger>
···
1123
...(liked ? { color: "#EC4899" } : {}),
1124
}}
1125
>
1126
-
{liked ? <IconMdiCardsHeart /> : <IconMdiCardsHeartOutline />}
0
0
0
0
1127
{(post.likeCount || 0) + (liked ? 1 : 0)}
1128
</HitSlopButton>
1129
<div style={{ display: "flex", gap: 8 }}>
···
1186
FeedEmbedRecordWithMedia = "FeedEmbedRecordWithMedia",
1187
}
1188
0
0
0
0
0
0
0
0
0
0
1189
1190
-
export function SmallAuthorLabelBadge({ label, large }: { label: ContentLabel, large?: boolean }) {
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1191
/*
1192
-{" "}
1193
{label.preference} (from {label.sourceDid})
···
1197
1198
const [imgcdn] = useAtom(imgCDNAtom);
1199
1200
-
1201
const { data: opProfile } = useQueryProfile(
1202
`at://${label.sourceDid}/app.bsky.actor.profile/self`,
1203
);
1204
1205
-
const resolvedpfp = getAvatarUrl(opProfile, label.sourceDid, imgcdn)
1206
1207
return (
1208
<div
···
1219
/>
1220
<span className="font-medium">{info.name || label.val}</span>
1221
</div>
1222
-
)
1223
-
}
···
21
import { useAuth } from "~/providers/UnifiedAuthProvider";
22
import { renderSnack } from "~/routes/__root";
23
//import { ModerationInner } from "~/routes/moderation";
24
+
import { FollowButton, Mutual } from "~/routes/profile.$did";
0
0
0
25
import type { LightboxProps } from "~/routes/profile.$did/post.$rkey.image.$i";
26
import type { ContentLabel } from "~/types/moderation";
27
import {
···
577
const { isLoading: authorModLoading, labels: authorLabels } = useModeration(
578
post.author.did,
579
);
580
+
const { isLoading: contentModLoading, labels: contentLabels } = useModeration(
581
+
post.uri,
582
+
);
583
const hideAuthorLabels = authorLabels.filter(
584
+
(label) => label.preference === "hide",
585
);
586
const warnAuthorLabels = authorLabels.filter(
587
+
(label) => label.preference === "warn",
588
);
589
+
const hideContentLabels = contentLabels.filter(
590
+
(label) => label.preference === "hide",
591
+
);
592
+
const warnContentLabels = contentLabels.filter(
593
+
(label) => label.preference === "warn",
594
+
);
595
596
const parsed = new AtUri(post.uri);
597
const navigate = useNavigate();
···
676
const isMainItem = false;
677
const setMainItem = (any: any) => { };
678
679
+
const showContentWarning = warnContentLabels.length > 0;
680
+
681
+
const [isOpen, setIsOpen] = useState(!showContentWarning);
682
+
683
+
684
+
if (hideAuthorLabels.length > 0 || hideContentLabels.length > 0) {
685
+
return null;
686
}
687
688
return (
···
927
</div>
928
</div>
929
{/* <ModerationInner subject={post.author.did} /> */}
930
+
{authorModLoading ? (
0
931
<div className="flex flex-wrap flex-row gap-1 my-1">
932
+
<div className="text-xs bg-gray-100 dark:bg-gray-800 px-1 py-0.5 rounded-full flex flex-row items-center gap-1">
933
+
{/* <img
0
0
934
src={resolvedpfp || defaultpfp}
935
alt="avatar"
936
className={`rounded-full object-cover border border-gray-300 dark:border-gray-800 bg-gray-300 dark:bg-gray-600`}
···
939
height: 12,
940
}}
941
/> */}
942
+
<span className="font-medium">loading badges...</span>
0
943
</div>
944
+
</div>
945
+
) : (
946
+
<div className="flex flex-wrap flex-row gap-1 my-1">
947
+
{warnAuthorLabels.map((label, index) => (
948
+
<SmallAuthorLabelBadge
949
+
label={label}
950
+
key={label.cts + label.sourceDid + label.val}
951
+
/>
952
+
))}
953
+
</div>
954
+
)}
955
{!!feedviewpostreplyhandle && (
956
<div
957
style={{
···
975
</div>
976
)}
977
{/* <ModerationInner subject={post.uri} /> */}
978
+
{showContentWarning && (
979
+
<ContentWarning
980
+
labels={warnContentLabels}
981
+
isOpen={isOpen}
982
+
onPress={(e) => {
983
+
e.stopPropagation();
984
+
setIsOpen(!isOpen)
985
+
}}
986
+
/>
987
+
)}
988
+
{isOpen && (<>
989
+
<div
990
+
style={{
991
+
fontSize: 16,
992
+
marginBottom: !post.embed || concise ? 0 : 8,
993
+
whiteSpace: "pre-wrap",
994
+
textAlign: "left",
995
+
overflowWrap: "anywhere",
996
+
wordBreak: "break-word",
997
+
...(concise && {
998
+
display: "-webkit-box",
999
+
WebkitBoxOrient: "vertical",
1000
+
WebkitLineClamp: 2,
1001
+
overflow: "hidden",
1002
+
}),
1003
+
}}
1004
+
className="text-gray-900 dark:text-gray-100"
1005
+
>
1006
+
{fedi ? (
1007
+
<>
1008
+
<span
1009
+
className="dangerousFediContent"
1010
+
dangerouslySetInnerHTML={{
1011
+
__html: DOMPurify.sanitize(fedi),
1012
+
}}
1013
+
/>
1014
+
</>
1015
+
) : (
1016
+
<>
1017
+
{renderTextWithFacets({
1018
+
text: (post.record as { text?: string }).text ?? "",
1019
+
facets: (post.record.facets as Facet[]) ?? [],
1020
+
navigate: navigate,
1021
+
})}
1022
+
</>
1023
+
)}
1024
+
</div>
1025
+
{post.embed && depth < 1 && !concise ? (
1026
+
<PostEmbeds
1027
+
embed={post.embed}
1028
+
viewContext={PostEmbedViewContext.Feed}
1029
+
salt={salt}
1030
+
navigate={navigate}
1031
+
postid={{ did: post.author.did, rkey: parsed.rkey }}
1032
+
nopics={nopics}
1033
+
lightboxCallback={lightboxCallback}
1034
+
constellationLinks={constellationLinks}
1035
+
/>
1036
+
) : null}
1037
+
{post.embed && depth > 0 && (
1038
<>
1039
+
<div className="border-gray-300 dark:border-gray-800 p-3 rounded-xl border italic text-gray-400 text-[14px]">
1040
+
(there is an embed here thats too deep to render)
1041
+
</div>
0
0
1042
</>
1043
)}
1044
+
</>)}
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
0
1045
<div
1046
style={{
1047
paddingTop: post.embed && !concise && depth < 1 ? 4 : 0,
···
1097
}}
1098
aria-label="Repost or quote post"
1099
>
1100
+
{hasRetweeted ? (
1101
+
<IconMdiRepeat color="#5CEFAA" />
1102
+
) : (
1103
+
<IconMdiRepeat />
1104
+
)}
1105
{post.repostCount ?? 0}
1106
</div>
1107
</DropdownMenu.Trigger>
···
1146
...(liked ? { color: "#EC4899" } : {}),
1147
}}
1148
>
1149
+
{liked ? (
1150
+
<IconMdiCardsHeart />
1151
+
) : (
1152
+
<IconMdiCardsHeartOutline />
1153
+
)}
1154
{(post.likeCount || 0) + (liked ? 1 : 0)}
1155
</HitSlopButton>
1156
<div style={{ display: "flex", gap: 8 }}>
···
1213
FeedEmbedRecordWithMedia = "FeedEmbedRecordWithMedia",
1214
}
1215
1216
+
export function ContentWarning({
1217
+
labels,
1218
+
isOpen,
1219
+
onPress,
1220
+
}: {
1221
+
labels: ContentLabel[];
1222
+
isOpen: boolean;
1223
+
onPress: React.MouseEventHandler<HTMLDivElement>;
1224
+
}) {
1225
+
const { getLabelInfo } = useLabelInfo();
1226
1227
+
// Pre-calculate text for cleaner JSX
1228
+
const labelText = labels
1229
+
.map((label) => getLabelInfo(label.sourceDid, label.val).name)
1230
+
.join(", ");
1231
+
1232
+
return (
1233
+
<div className="mb-2 w-full select-none" onClick={onPress}>
1234
+
<div
1235
+
className={`
1236
+
group flex items-center justify-between
1237
+
w-full px-4 py-3
1238
+
rounded-full
1239
+
border border-gray-200 dark:border-gray-700
1240
+
bg-gray-100 dark:bg-gray-800
1241
+
cursor-pointer
1242
+
transition-all duration-200 ease-out
1243
+
hover:bg-gray-200 dark:hover:bg-gray-700
1244
+
`}
1245
+
>
1246
+
<div className="flex items-center gap-3 overflow-hidden">
1247
+
{/* Icon Container */}
1248
+
<div className="flex items-center justify-center text-gray-500 dark:text-gray-400">
1249
+
<IconMdiWarning className="text-xl" />
1250
+
</div>
1251
+
1252
+
{/* Label Text */}
1253
+
<span className="text-sm font-semibold text-gray-900 dark:text-gray-100 truncate">
1254
+
{labelText}
1255
+
</span>
1256
+
</div>
1257
+
1258
+
{/* Chevron */}
1259
+
<div className="flex items-center justify-center text-gray-500 dark:text-gray-400 pl-2 gap-2 text-sm">
1260
+
{isOpen ? "hide" : "show"}
1261
+
<IconMdiChevronDown
1262
+
className={`text-xl transition-transform duration-300 ease-[cubic-bezier(0.2,0,0,1)] ${isOpen ? "rotate-180" : ""
1263
+
}`}
1264
+
/>
1265
+
</div>
1266
+
</div>
1267
+
</div>
1268
+
);
1269
+
}
1270
+
1271
+
export function SmallAuthorLabelBadge({
1272
+
label,
1273
+
large,
1274
+
}: {
1275
+
label: ContentLabel;
1276
+
large?: boolean;
1277
+
}) {
1278
/*
1279
-{" "}
1280
{label.preference} (from {label.sourceDid})
···
1284
1285
const [imgcdn] = useAtom(imgCDNAtom);
1286
0
1287
const { data: opProfile } = useQueryProfile(
1288
`at://${label.sourceDid}/app.bsky.actor.profile/self`,
1289
);
1290
1291
+
const resolvedpfp = getAvatarUrl(opProfile, label.sourceDid, imgcdn);
1292
1293
return (
1294
<div
···
1305
/>
1306
<span className="font-medium">{info.name || label.val}</span>
1307
</div>
1308
+
);
1309
+
}