Skip to content

Commit adeb4b6

Browse files
committed
Implement collections
1 parent 81694f6 commit adeb4b6

6 files changed

Lines changed: 414 additions & 69 deletions

File tree

src/ClaimPage.tsx

Lines changed: 9 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,7 @@ function ClaimPage(): JSX.Element {
1212
const params: Params<string> = useParams();
1313
const claim: string = params["*"];
1414

15-
const [claimResolveData, setClaimResolveData]: [] = useState(null);
16-
17-
const [recommendedIsChannelItems, setRecommendedIsChannelItems] =
18-
useState(false);
15+
const [claimResolveData, setClaimResolveData] = useState(null);
1916

2017
useEffect((): void => {
2118
LBRY.rpc(
@@ -31,66 +28,14 @@ function ClaimPage(): JSX.Element {
3128
});
3229
}, [claim, daemonRPC]);
3330

34-
return (
35-
<div style={{ display: "flex" }}>
36-
<div style={{ flex: "1" }}>
37-
<div id="claim">
38-
{claimResolveData ? (
39-
claimResolveData.type === "claim" ? (
40-
<Claim data={claimResolveData} />
41-
) : (
42-
<Error message="Type isn't a claim." />
43-
)
44-
) : (
45-
<Loader />
46-
)}
47-
</div>
48-
<div id="comments" style={{ paddingTop: "16px", textAlign: "center" }}>
49-
Cannot load comments
50-
</div>
51-
</div>
52-
<div id="recommended" style={{ width: "375px" }}>
53-
<div>
54-
<span
55-
onClick={() => setRecommendedIsChannelItems(false)}
56-
style={{
57-
backgroundColor: recommendedIsChannelItems
58-
? "rgba(17, 17, 17, 0.4)"
59-
: "rgb(17, 17, 17)",
60-
borderRadius: "16px",
61-
cursor: "pointer",
62-
display: "inline-block",
63-
fontSize: "14px",
64-
lineHeight: "32px",
65-
padding: "0 12px",
66-
}}
67-
>
68-
Related
69-
</span>
70-
&nbsp;
71-
<span
72-
onClick={() => setRecommendedIsChannelItems(true)}
73-
style={{
74-
backgroundColor: recommendedIsChannelItems
75-
? "rgb(17, 17, 17)"
76-
: "rgba(17, 17, 17, 0.4)",
77-
borderRadius: "16px",
78-
cursor: "pointer",
79-
display: "inline-block",
80-
fontSize: "14px",
81-
lineHeight: "32px",
82-
padding: "0 12px",
83-
}}
84-
>
85-
More from this channel
86-
</span>
87-
</div>
88-
<div style={{ padding: "16px", textAlign: "center" }}>
89-
Cannot load recommendations.
90-
</div>
91-
</div>
92-
</div>
93-
);
31+
if (!claimResolveData) {
32+
return <Loader />;
33+
}
34+
35+
if (claimResolveData.type === "claim") {
36+
return <Claim data={claimResolveData} />;
37+
}
38+
return <Error message="Type isn't a claim." />;
9439
}
9540

9641
export default ClaimPage;

src/components/ChannelClaim.tsx

Lines changed: 280 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,285 @@
1-
import Props, { JSX } from "react";
1+
import Props, { JSX, useEffect, useState } from "react";
2+
import { Link } from "react-router";
3+
import { NOT_TAGS } from "~/Constants";
4+
import useDaemonRPC from "~/DaemonRPC";
5+
import LBRY from "~/LBRY";
6+
import ClaimPreviewTile from "~/components/ClaimPreviewTile";
7+
import CustomSVG from "~/components/CustomSVG";
8+
import Error from "~/components/Error";
29

310
function ChannelClaim({ data }: Props & { data: Channel }): JSX.Element {
4-
return <div>TODO Channel</div>;
11+
const daemonRPC: string = useDaemonRPC();
12+
13+
const [tab, setTab] = useState("content");
14+
const [content, setContent] = useState([]);
15+
const [playlists, setPlaylists] = useState([]);
16+
17+
useEffect((): void => {
18+
LBRY.rpc(
19+
daemonRPC,
20+
"claim_search",
21+
{
22+
page_size: 20,
23+
page: 1,
24+
claim_type: ["stream", "repost"],
25+
no_totals: true,
26+
not_tags: NOT_TAGS,
27+
order_by: ["release_time"],
28+
has_source: true,
29+
fee_amount: ">=0",
30+
channel_ids: [data.claim_id],
31+
release_time: "<1765038660",
32+
include_purchase_receipt: true,
33+
},
34+
null,
35+
import.meta.env.VITE_DAEMON_PROXY === "true",
36+
).then(async (json: object) => {
37+
setContent(json.result.items);
38+
});
39+
}, [data.claim_id, daemonRPC]);
40+
41+
useEffect((): void => {
42+
LBRY.rpc(
43+
daemonRPC,
44+
"claim_search",
45+
{
46+
page_size: 20,
47+
page: 1,
48+
claim_type: ["collection"],
49+
no_totals: true,
50+
not_tags: NOT_TAGS,
51+
order_by: ["release_time"],
52+
has_source: true,
53+
fee_amount: ">=0",
54+
channel_ids: [data.claim_id],
55+
release_time: "<1765037880",
56+
include_purchase_receipt: true,
57+
},
58+
null,
59+
import.meta.env.VITE_DAEMON_PROXY === "true",
60+
).then(async (json: object) => {
61+
setPlaylists(json.result.items);
62+
});
63+
}, [data.claim_id, daemonRPC]);
64+
65+
return (
66+
<div>
67+
<div id="channel-header">
68+
<div
69+
style={{
70+
backgroundImage: `url(${data.value.cover.url})`,
71+
backgroundSize: "cover",
72+
borderTopLeftRadius: "6px",
73+
borderTopRightRadius: "6px",
74+
height: "210px",
75+
}}
76+
>
77+
<div
78+
style={{
79+
backgroundImage:
80+
"linear-gradient(to right, black,transparent 50%)",
81+
}}
82+
>
83+
<img
84+
alt="Channel Logo"
85+
src={data.value.thumbnail.url}
86+
style={{
87+
borderRadius: "100%",
88+
height: "160px",
89+
padding: "25px",
90+
verticalAlign: "middle",
91+
}}
92+
/>
93+
<div style={{ display: "inline-block", verticalAlign: "middle" }}>
94+
<span style={{ fontSize: "32px", fontWeight: "700" }}>
95+
{data.value.title}
96+
</span>
97+
</div>
98+
</div>
99+
</div>
100+
<div
101+
style={{
102+
backgroundColor: "rgba(17, 17, 17, 0.9)",
103+
borderBottomLeftRadius: "6px",
104+
borderBottomRightRadius: "6px",
105+
}}
106+
>
107+
<Link
108+
onClick={(): void => setTab("content")}
109+
style={{
110+
color: "white",
111+
display: "inline-block",
112+
fontSize: "16px",
113+
fontWeight: "700",
114+
lineHeight: "24px",
115+
padding: "16px",
116+
textDecoration: "none",
117+
}}
118+
to={null}
119+
>
120+
Content
121+
</Link>
122+
<Link
123+
onClick={(): void => setTab("playlists")}
124+
style={{
125+
color: "white",
126+
display: "inline-block",
127+
fontSize: "16px",
128+
fontWeight: "700",
129+
lineHeight: "24px",
130+
padding: "16px",
131+
textDecoration: "none",
132+
}}
133+
to={null}
134+
>
135+
Playlists
136+
</Link>
137+
<Link
138+
onClick={(): void => setTab("about")}
139+
style={{
140+
color: "white",
141+
display: "inline-block",
142+
fontSize: "16px",
143+
fontWeight: "700",
144+
lineHeight: "24px",
145+
padding: "16px",
146+
textDecoration: "none",
147+
}}
148+
to={null}
149+
>
150+
About
151+
</Link>
152+
<Link
153+
onClick={(): void => setTab("community")}
154+
style={{
155+
color: "white",
156+
display: "inline-block",
157+
fontSize: "16px",
158+
fontWeight: "700",
159+
lineHeight: "24px",
160+
padding: "16px",
161+
textDecoration: "none",
162+
}}
163+
to={null}
164+
>
165+
Community
166+
</Link>
167+
</div>
168+
</div>
169+
<div style={{ paddingTop: "32px" }}>
170+
{tab === "content" ? (
171+
<div style={{ textAlign: "center" }}>
172+
{content.map((item, i: number) => (
173+
<ClaimPreviewTile claim={item} key={i} />
174+
))}
175+
</div>
176+
) : null}
177+
{tab === "playlists"
178+
? playlists.map((item, i: number) => (
179+
<ClaimPreviewTile claim={item} key={i} />
180+
))
181+
: null}
182+
{tab === "about" ? (
183+
<section>
184+
{data.value.email ? (
185+
<div style={{ padding: "16px 8px" }}>
186+
<label style={{ display: "block", fontWeight: "bold" }}>
187+
Contact
188+
</label>
189+
<Link
190+
style={{ display: "block" }}
191+
to={`mailto:${data.value.email}`}
192+
>
193+
{data.value.email}
194+
</Link>
195+
</div>
196+
) : null}
197+
{data.value.website_url ? (
198+
<div style={{ padding: "16px 8px" }}>
199+
<label style={{ display: "block", fontWeight: "bold" }}>
200+
Site
201+
</label>
202+
{data.value.website_url}
203+
</div>
204+
) : null}
205+
{data.value.tags?.length > 0 ? (
206+
<div style={{ padding: "16px 8px" }}>
207+
<label style={{ display: "block", fontWeight: "bold" }}>
208+
Tags
209+
</label>
210+
{data.value.tags.map((tag: string, i: number) => (
211+
// TODO Make links
212+
<span
213+
key={i}
214+
style={{
215+
backgroundColor: "red",
216+
borderRadius: "6px",
217+
margin: "0 2px",
218+
padding: "0 4px",
219+
}}
220+
>
221+
{tag}
222+
</span>
223+
))}
224+
</div>
225+
) : null}
226+
{data.meta.claims_in_channel ? (
227+
<div style={{ padding: "16px 8px" }}>
228+
<label style={{ display: "block", fontWeight: "bold" }}>
229+
Total Uploads
230+
</label>
231+
<span>{data.meta.claims_in_channel}</span>
232+
</div>
233+
) : null}
234+
{data.timestamp ? (
235+
<div style={{ padding: "16px 8px" }}>
236+
<label style={{ display: "block", fontWeight: "bold" }}>
237+
Last Updated
238+
</label>
239+
<span>{/*TODO*/}</span>
240+
</div>
241+
) : null}
242+
{data.canonical_url ? (
243+
<div style={{ padding: "16px 8px" }}>
244+
<label style={{ display: "block", fontWeight: "bold" }}>
245+
URL
246+
</label>
247+
<span>{data.canonical_url}</span>
248+
</div>
249+
) : null}
250+
{data.claim_id ? (
251+
<div style={{ padding: "16px 8px" }}>
252+
<label style={{ display: "block", fontWeight: "bold" }}>
253+
Claim ID
254+
</label>
255+
<span>{data.claim_id}</span>
256+
</div>
257+
) : null}
258+
{data.meta.effective_amount ? (
259+
<div style={{ padding: "16px 8px" }}>
260+
<label style={{ display: "block", fontWeight: "bold" }}>
261+
Staked LBRY Credits
262+
</label>
263+
<div>
264+
<CustomSVG
265+
icon="lbc"
266+
style={{ height: "16px", verticalAlign: "middle" }}
267+
viewBox="0 0 24 24"
268+
/>
269+
&nbsp;
270+
<span style={{ verticalAlign: "middle" }}>
271+
{Math.floor(data.meta.effective_amount * 100000)}
272+
</span>
273+
</div>
274+
</div>
275+
) : null}
276+
</section>
277+
) : null}
278+
{tab === "community" ? <Error message="Cannot load comments" /> : null}
279+
</div>
280+
{/*<div style={{paddingTop:'32px'}}>{JSON.stringify(data)}</div>*/}
281+
</div>
282+
);
5283
}
6284

7285
export default ChannelClaim;

src/components/Claim.tsx

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,19 @@
11
import Props, { JSX } from "react";
22
import ChannelClaim from "~/components/ChannelClaim";
3+
import CollectionClaim from "~/components/CollectionClaim";
34
import Error from "~/components/Error";
45
import ReportClaim from "~/components/ReportClaim";
56
import StreamClaim from "~/components/StreamClaim";
67

78
function Claim({
89
data,
9-
}: Props & { data: Channel | Repost | Stream }): JSX.Element {
10-
console.log(JSON.stringify(data));
10+
}: Props & { data: Channel | Collection | Repost | Stream }): JSX.Element {
1111
if (data.value_type === "channel") {
1212
return <ChannelClaim data={data} />;
1313
}
14+
if (data.value_type === "collection") {
15+
return <CollectionClaim data={data} />;
16+
}
1417
if (data.value_type === "stream") {
1518
return <StreamClaim data={data} />;
1619
}

0 commit comments

Comments
 (0)