tangled
alpha
login
or
join now
t1c.dev
/
rocksky
forked from
rocksky.app/rocksky
2
fork
atom
A decentralized music tracking and discovery platform built on AT Protocol 🎵
2
fork
atom
overview
issues
pulls
pipelines
[web] start using rocksky xrpc api
tsiry-sandratraina.com
8 months ago
dd7a78d8
eb25963b
+93
-58
8 changed files
expand all
collapse all
unified
split
apps
web
src
api
charts.ts
index.ts
profile.ts
hooks
useChart.tsx
useFeed.tsx
useNowPlaying.tsx
pages
home
nowplayings
NowPlayings.tsx
turbo.json
+4
-4
apps/web/src/api/charts.ts
···
7
7
8
8
export const getSongChart = async (uri: string) => {
9
9
const response = await axios.get(
10
10
-
`${API_URL}/public/scrobbleschart?songuri=${uri}`
10
10
+
`${API_URL}/xrpc/app.rocksky.charts.getScrobblesChart?songuri=${uri}`
11
11
);
12
12
if (response.status !== 200) {
13
13
return [];
···
17
17
18
18
export const getArtistChart = async (uri: string) => {
19
19
const response = await axios.get(
20
20
-
`${API_URL}/public/scrobbleschart?artisturi=${uri}`
20
20
+
`${API_URL}/xrpc/app.rocksky.charts.getScrobblesChart?artisturi=${uri}`
21
21
);
22
22
if (response.status !== 200) {
23
23
return [];
···
27
27
28
28
export const getAlbumChart = async (uri: string) => {
29
29
const response = await axios.get(
30
30
-
`${API_URL}/public/scrobbleschart?albumuri=${uri}`
30
30
+
`${API_URL}/xrpc/app.rocksky.charts.getScrobblesChart?albumuri=${uri}`
31
31
);
32
32
if (response.status !== 200) {
33
33
return [];
···
37
37
38
38
export const getProfileChart = async (did: string) => {
39
39
const response = await axios.get(
40
40
-
`${API_URL}/public/scrobbleschart?did=${did}`
40
40
+
`${API_URL}/xrpc/app.rocksky.charts.getScrobblesChart?did=${did}`
41
41
);
42
42
if (response.status !== 200) {
43
43
return [];
+6
apps/web/src/api/index.ts
···
1
1
+
import axios from "axios";
2
2
+
import { API_URL } from "../consts";
3
3
+
4
4
+
export const client = axios.create({
5
5
+
baseURL: API_URL,
6
6
+
});
+6
-2
apps/web/src/api/profile.ts
···
8
8
};
9
9
10
10
export const getProfileStatsByDid = async (did: string) => {
11
11
-
const response = await axios.get(`${API_URL}/users/${did}/stats`);
11
11
+
const response = await axios.get(
12
12
+
`${API_URL}/xrpc/app.rocksky.stats.getStats`,
13
13
+
{ params: { did } }
14
14
+
);
12
15
return response.data;
13
16
};
14
17
···
18
21
size = 10
19
22
): Promise<Scrobble[]> => {
20
23
const response = await axios.get<Scrobble[]>(
21
21
-
`${API_URL}/users/${did}/scrobbles?size=${size}&offset=${offset}`
24
24
+
`${API_URL}/users/${did}/scrobbles`,
25
25
+
{ params: { size, offset } }
22
26
);
23
27
return response.data;
24
28
};
+36
-22
apps/web/src/hooks/useChart.tsx
···
1
1
import { useQuery } from "@tanstack/react-query";
2
2
-
import axios from "axios";
3
2
import useSWR from "swr";
4
4
-
import { getArtistChart, getSongChart } from "../api/charts";
3
3
+
import { client } from "../api";
4
4
+
import {
5
5
+
getAlbumChart,
6
6
+
getArtistChart,
7
7
+
getProfileChart,
8
8
+
getSongChart,
9
9
+
} from "../api/charts";
5
10
import { API_URL } from "../consts";
6
11
7
12
export const useScrobblesChartQuery = () =>
8
13
useQuery({
9
14
queryKey: ["scrobblesChart"],
10
10
-
queryFn: () =>
11
11
-
fetch(`${API_URL}/public/scrobbleschart`, {
12
12
-
method: "GET",
13
13
-
}).then((res) => res.json()),
15
15
+
queryFn: () => client.get("/xrpc/app.rocksky.charts.getScrobblesChart"),
16
16
+
select: ({ data }) => data.scrobbles || [],
14
17
});
15
18
16
19
export const useSongChartQuery = (uri: string) =>
17
20
useQuery({
18
21
queryKey: ["songChart", uri],
19
22
queryFn: () => getSongChart(uri),
23
23
+
select: (data) => data.scrobbles || [],
20
24
});
21
25
22
26
export const useArtistChartQuery = (uri: string) =>
23
27
useQuery({
24
28
queryKey: ["artistChart", uri],
25
29
queryFn: () => getArtistChart(uri),
30
30
+
select: (data) => data.scrobbles || [],
26
31
});
27
32
28
33
export const useAlbumChartQuery = (uri: string) =>
29
34
useQuery({
30
35
queryKey: ["albumChart", uri],
31
31
-
queryFn: () => getArtistChart(uri),
36
36
+
queryFn: () => getAlbumChart(uri),
37
37
+
select: (data) => data.scrobbles || [],
32
38
});
33
39
34
40
export const useProfileChartQuery = (did: string) =>
35
41
useQuery({
36
42
queryKey: ["profileChart", did],
37
37
-
queryFn: () => getArtistChart(did),
43
43
+
queryFn: () => getProfileChart(did),
44
44
+
select: (data) => data.scrobbles || [],
38
45
});
39
46
40
47
function useChart() {
···
43
50
method: "GET",
44
51
}).then((res) => res.json());
45
52
46
46
-
const { data: scrobblesChart } = useSWR("/public/scrobbleschart", fetcher);
53
53
+
const { data: scrobblesChart } = useSWR(
54
54
+
"/xrpc/app.rocksky.charts.getScrobblesChart",
55
55
+
fetcher
56
56
+
);
47
57
48
58
const getScrobblesChart = () => {
49
49
-
return scrobblesChart || [];
59
59
+
return scrobblesChart?.scrobbles || [];
50
60
};
51
61
52
62
const getSongChart = async (uri: string) => {
53
53
-
const response = await axios.get(
54
54
-
`${API_URL}/public/scrobbleschart?songuri=${uri}`
63
63
+
const response = await client.get(
64
64
+
"/xrpc/app.rocksky.charts.getScrobblesChart",
65
65
+
{ params: { songuri: uri } }
55
66
);
56
67
if (response.status !== 200) {
57
68
return [];
58
69
}
59
59
-
return response.data;
70
70
+
return response.data.scrobbles;
60
71
};
61
72
62
73
const getArtistChart = async (uri: string) => {
63
63
-
const response = await axios.get(
64
64
-
`${API_URL}/public/scrobbleschart?artisturi=${uri}`
74
74
+
const response = await client.get(
75
75
+
"/xrpc/app.rocksky.charts.getScrobblesChart",
76
76
+
{ params: { artisturi: uri } }
65
77
);
66
78
if (response.status !== 200) {
67
79
return [];
68
80
}
69
69
-
return response.data;
81
81
+
return response.data.scrobbles;
70
82
};
71
83
72
84
const getAlbumChart = async (uri: string) => {
73
73
-
const response = await axios.get(
74
74
-
`${API_URL}/public/scrobbleschart?albumuri=${uri}`
85
85
+
const response = await client.get(
86
86
+
"/xrpc/app.rocksky.charts.getScrobblesChart",
87
87
+
{ params: { albumuri: uri } }
75
88
);
76
89
if (response.status !== 200) {
77
90
return [];
78
91
}
79
79
-
return response.data;
92
92
+
return response.data.scrobbles;
80
93
};
81
94
82
95
const getProfileChart = async (did: string) => {
83
83
-
const response = await axios.get(
84
84
-
`${API_URL}/public/scrobbleschart?did=${did}`
96
96
+
const response = await client.get(
97
97
+
"/xrpc/app.rocksky.charts.getScrobblesChart",
98
98
+
{ params: { did } }
85
99
);
86
100
if (response.status !== 200) {
87
101
return [];
88
102
}
89
89
-
return response.data;
103
103
+
return response.data.scrobbles;
90
104
};
91
105
92
106
return {
+6
-5
apps/web/src/hooks/useFeed.tsx
···
1
1
import { useQuery } from "@tanstack/react-query";
2
2
+
import { client } from "../api";
2
3
import { getFeedByUri } from "../api/feed";
3
3
-
import { API_URL } from "../consts";
4
4
5
5
-
export const useFeedQuery = (size = 114) =>
5
5
+
export const useFeedQuery = (limit = 114) =>
6
6
useQuery({
7
7
queryKey: ["feed"],
8
8
queryFn: () =>
9
9
-
fetch(`${API_URL}/public/scrobbles?size=${size}`, {
10
10
-
method: "GET",
11
11
-
}).then((res) => res.json()),
9
9
+
client.get("/xrpc/app.rocksky.scrobble.getScrobbles", {
10
10
+
params: { limit },
11
11
+
}),
12
12
refetchInterval: 5000,
13
13
+
select: (res) => res.data.scrobbles || [],
13
14
});
14
15
15
16
export const useFeedByUriQuery = (uri: string) =>
+12
-10
apps/web/src/hooks/useNowPlaying.tsx
···
1
1
import { useQuery } from "@tanstack/react-query";
2
2
-
import { API_URL } from "../consts";
2
2
+
import { client } from "../api";
3
3
4
4
export type NowPlayings = {
5
5
id: string;
6
6
title: string;
7
7
artist: string;
8
8
-
album_art: string;
9
9
-
artist_uri?: string;
8
8
+
albumArt: string;
9
9
+
artistUri?: string;
10
10
uri: string;
11
11
avatar: string;
12
12
handle: string;
13
13
did: string;
14
14
-
created_at: string;
15
15
-
track_id: string;
16
16
-
track_uri: string;
14
14
+
createdAt: string;
15
15
+
trackId: string;
16
16
+
trackUri: string;
17
17
}[];
18
18
19
19
export const useNowPlayingsQuery = () =>
20
20
-
useQuery<NowPlayings>({
20
20
+
useQuery({
21
21
queryKey: ["now-playings"],
22
22
queryFn: () =>
23
23
-
fetch(`${API_URL}/now-playings?size=7`, {
24
24
-
method: "GET",
25
25
-
}).then((res) => res.json()),
23
23
+
client.get<{ nowPlayings: NowPlayings }>(
24
24
+
"/xrpc/app.rocksky.feed.getNowPlayings",
25
25
+
{ params: { size: 7 } }
26
26
+
),
26
27
refetchInterval: 5000,
28
28
+
select: (res) => res.data.nowPlayings || [],
27
29
});
+15
-15
apps/web/src/pages/home/nowplayings/NowPlayings.tsx
···
94
94
id: string;
95
95
title: string;
96
96
artist: string;
97
97
-
album_art: string;
98
98
-
artist_uri?: string;
97
97
+
albumArt: string;
98
98
+
artistUri?: string;
99
99
uri: string;
100
100
avatar: string;
101
101
handle: string;
102
102
did: string;
103
103
-
created_at: string;
104
104
-
track_id: string;
105
105
-
track_uri: string;
103
103
+
createdAt: string;
104
104
+
trackId: string;
105
105
+
trackUri: string;
106
106
} | null>(null);
107
107
const [currentIndex, setCurrentIndex] = useState(0);
108
108
const [progress, setProgress] = useState(0);
···
211
211
</div>
212
212
</Link>
213
213
<span className="ml-[10px] text-[15px] text-[var(--color-text-muted)]">
214
214
-
{dayjs.utc(currentlyPlaying?.created_at).local().fromNow()}
214
214
+
{dayjs.utc(currentlyPlaying?.createdAt).local().fromNow()}
215
215
</span>
216
216
</div>
217
217
</ModalHeader>
···
225
225
)}
226
226
</div>
227
227
<div className="flex flex-col items-center flex-1">
228
228
-
{currentlyPlaying?.track_uri && (
228
228
+
{currentlyPlaying?.trackUri && (
229
229
<Link
230
230
-
to={`/${currentlyPlaying?.track_uri.split("at://")[1]}`}
230
230
+
to={`/${currentlyPlaying?.trackUri.split("at://")[1]}`}
231
231
>
232
232
<Cover
233
233
-
src={currentlyPlaying?.album_art}
233
233
+
src={currentlyPlaying?.albumArt}
234
234
key={currentlyPlaying?.id}
235
235
/>
236
236
</Link>
237
237
)}
238
238
-
{currentlyPlaying?.track_uri && (
238
238
+
{currentlyPlaying?.trackUri && (
239
239
<Link
240
240
-
to={`/${currentlyPlaying?.track_uri.split("at://")[1]}`}
240
240
+
to={`/${currentlyPlaying?.trackUri.split("at://")[1]}`}
241
241
>
242
242
<TrackTitle>{currentlyPlaying?.title}</TrackTitle>
243
243
</Link>
244
244
)}
245
245
-
{!currentlyPlaying?.track_uri && (
245
245
+
{!currentlyPlaying?.trackUri && (
246
246
<Cover
247
247
-
src={currentlyPlaying?.album_art}
247
247
+
src={currentlyPlaying?.albumArt}
248
248
key={currentlyPlaying?.id}
249
249
/>
250
250
)}
···
261
261
</div>
262
262
</div>
263
263
264
264
-
{!currentlyPlaying?.track_uri && (
264
264
+
{!currentlyPlaying?.trackUri && (
265
265
<TrackTitle>{currentlyPlaying?.title}</TrackTitle>
266
266
)}
267
267
-
<Link to={`/${currentlyPlaying?.artist_uri?.split("at://")[1]}`}>
267
267
+
<Link to={`/${currentlyPlaying?.artistUri?.split("at://")[1]}`}>
268
268
<TrackArtist>{currentlyPlaying?.artist}</TrackArtist>
269
269
</Link>
270
270
</ModalBody>
+8
turbo.json
···
14
14
"./dist/**"
15
15
]
16
16
},
17
17
+
"build:prod": {
18
18
+
"dependsOn": [
19
19
+
"^build:prod"
20
20
+
],
21
21
+
"outputs": [
22
22
+
"./dist/**"
23
23
+
]
24
24
+
},
17
25
"dev": {
18
26
"persistent": true,
19
27
"cache": false