tangled
alpha
login
or
join now
leaflet.pub
/
leaflet
289
fork
atom
a tool for shared writing and social publishing
289
fork
atom
overview
issues
28
pulls
pipelines
use bluesky api for profile data
awarm.space
3 months ago
6b62f1f2
c2395286
+29
-34
4 changed files
expand all
collapse all
unified
split
app
(home-pages)
p
[didOrHandle]
ProfileHeader.tsx
layout.tsx
api
rpc
[command]
get_profile_data.ts
components
ProfilePopover.tsx
+5
-6
app/(home-pages)/p/[didOrHandle]/ProfileHeader.tsx
···
8
import { PubIcon } from "components/ActionBar/Publications";
9
import { Json } from "supabase/database.types";
10
import { BlueskyTiny } from "components/Icons/BlueskyTiny";
0
11
12
export const ProfileHeader = (props: {
13
-
profile: ProfileData;
14
publications: { record: Json; uri: string }[];
15
}) => {
16
-
let profileRecord = props.profile.record as AppBskyActorProfile.Record;
0
17
18
return (
19
<div className="flex flex-col relative" id="profile-header">
20
<Avatar
21
-
src={
22
-
profileRecord.avatar?.ref &&
23
-
blobRefToSrc(profileRecord.avatar?.ref, props.profile.did)
24
-
}
25
displayName={profileRecord.displayName}
26
className="mx-auto mt-3 sm:mt-4"
27
giant
···
8
import { PubIcon } from "components/ActionBar/Publications";
9
import { Json } from "supabase/database.types";
10
import { BlueskyTiny } from "components/Icons/BlueskyTiny";
11
+
import { ProfileViewDetailed } from "@atproto/api/dist/client/types/app/bsky/actor/defs";
12
13
export const ProfileHeader = (props: {
14
+
profile: ProfileViewDetailed;
15
publications: { record: Json; uri: string }[];
16
}) => {
17
+
console.log(props.profile);
18
+
let profileRecord = props.profile;
19
20
return (
21
<div className="flex flex-col relative" id="profile-header">
22
<Avatar
23
+
src={profileRecord.avatar}
0
0
0
24
displayName={profileRecord.displayName}
25
className="mx-auto mt-3 sm:mt-4"
26
giant
+12
-6
app/(home-pages)/p/[didOrHandle]/layout.tsx
···
6
import { ProfileTabs } from "./ProfileTabs";
7
import { DashboardLayout } from "components/PageLayouts/DashboardLayout";
8
import { ProfileLayout } from "./ProfileLayout";
0
9
10
export default async function ProfilePageLayout(props: {
11
params: Promise<{ didOrHandle: string }>;
···
33
did = resolved;
34
}
35
36
-
let { data: profile } = await supabaseServerClient
37
-
.from("bsky_profiles")
38
-
.select(`*`)
39
-
.eq("did", did)
40
-
.single();
41
-
let { data: publications } = await supabaseServerClient
42
.from("publications")
43
.select("*")
44
.eq("identity_did", did);
0
0
0
0
0
45
46
if (!profile) return null;
47
···
6
import { ProfileTabs } from "./ProfileTabs";
7
import { DashboardLayout } from "components/PageLayouts/DashboardLayout";
8
import { ProfileLayout } from "./ProfileLayout";
9
+
import { Agent } from "@atproto/api";
10
11
export default async function ProfilePageLayout(props: {
12
params: Promise<{ didOrHandle: string }>;
···
34
did = resolved;
35
}
36
37
+
let agent = new Agent({
38
+
service: "https://public.api.bsky.app",
39
+
});
40
+
let profileReq = agent.app.bsky.actor.getProfile({ actor: did });
41
+
42
+
let publicationsReq = supabaseServerClient
43
.from("publications")
44
.select("*")
45
.eq("identity_did", did);
46
+
47
+
let [{ data: profile }, { data: publications }] = await Promise.all([
48
+
profileReq,
49
+
publicationsReq,
50
+
]);
51
52
if (!profile) return null;
53
+11
-21
app/api/rpc/[command]/get_profile_data.ts
···
2
import { makeRoute } from "../lib";
3
import type { Env } from "./route";
4
import { idResolver } from "app/(home-pages)/reader/idResolver";
0
0
5
6
export type GetProfileDataReturnType = Awaited<
7
ReturnType<(typeof get_profile_data)["handler"]>
···
24
did = resolved;
25
}
26
27
-
// Fetch profile
28
-
const { data: profile, error: profileError } = await supabase
29
-
.from("bsky_profiles")
30
-
.select("*")
31
-
.eq("did", did)
32
-
.single();
33
-
34
-
if (profileError) {
35
-
throw new Error(`Failed to fetch profile: ${profileError.message}`);
36
-
}
37
-
38
-
if (!profile) {
39
-
throw new Error("Profile not found");
40
-
}
41
42
-
// Fetch publications for the DID
43
-
const { data: publications, error: publicationsError } = await supabase
44
.from("publications")
45
.select("*")
46
.eq("identity_did", did);
47
48
-
if (publicationsError) {
49
-
throw new Error(
50
-
`Failed to fetch publications: ${publicationsError.message}`,
51
-
);
52
-
}
53
54
return {
55
result: {
···
2
import { makeRoute } from "../lib";
3
import type { Env } from "./route";
4
import { idResolver } from "app/(home-pages)/reader/idResolver";
5
+
import { supabaseServerClient } from "supabase/serverClient";
6
+
import { Agent } from "@atproto/api";
7
8
export type GetProfileDataReturnType = Awaited<
9
ReturnType<(typeof get_profile_data)["handler"]>
···
26
did = resolved;
27
}
28
29
+
let agent = new Agent({
30
+
service: "https://public.api.bsky.app",
31
+
});
32
+
let profileReq = agent.app.bsky.actor.getProfile({ actor: did });
0
0
0
0
0
0
0
0
0
0
33
34
+
let publicationsReq = supabaseServerClient
0
35
.from("publications")
36
.select("*")
37
.eq("identity_did", did);
38
39
+
let [{ data: profile }, { data: publications }] = await Promise.all([
40
+
profileReq,
41
+
publicationsReq,
42
+
]);
0
43
44
return {
45
result: {
+1
-1
components/ProfilePopover.tsx
···
1
"use client";
2
-
import { ProfileHeader } from "app/p/[didOrHandle]/(profile)/ProfileHeader";
3
import { Popover } from "./Popover";
4
import useSWR from "swr";
5
import { callRPC } from "app/api/rpc/client";
6
import { useState } from "react";
0
7
8
export const ProfilePopover = (props: {
9
trigger: React.ReactNode;
···
1
"use client";
0
2
import { Popover } from "./Popover";
3
import useSWR from "swr";
4
import { callRPC } from "app/api/rpc/client";
5
import { useState } from "react";
6
+
import { ProfileHeader } from "app/(home-pages)/p/[didOrHandle]/ProfileHeader";
7
8
export const ProfilePopover = (props: {
9
trigger: React.ReactNode;