A decentralized music tracking and discovery platform built on AT Protocol 🎵

display spotify link

+83 -24
+15
rockskyweb/src/atoms/artist.ts
··· 1 + import { atom } from "jotai"; 2 + 3 + export const artistAtom = atom<{ 4 + id: string; 5 + name: string; 6 + born?: string; 7 + bornIn?: string; 8 + died?: string; 9 + listeners: number; 10 + scrobbles: number; 11 + picture?: string; 12 + tags: string[]; 13 + uri: string; 14 + spotifyLink?: string; 15 + } | null>(null);
+14
rockskyweb/src/atoms/song.ts
··· 1 + import { atom } from "jotai"; 2 + 3 + export const songAtom = atom<{ 4 + title: string; 5 + albumArtist: string; 6 + cover: string; 7 + listeners: number; 8 + scrobbles: number; 9 + tags: string[]; 10 + lyrics?: string; 11 + artistUri?: string; 12 + albumUri?: string; 13 + spotifyLink?: string; 14 + } | null>(null);
+38
rockskyweb/src/layouts/ExternalLinks/ExternalLinks.tsx
··· 1 + import styled from "@emotion/styled"; 2 + import { Spotify } from "@styled-icons/boxicons-logos"; 3 + import { LabelLarge } from "baseui/typography"; 4 + import { useAtomValue } from "jotai"; 5 + import { useLocation } from "react-router"; 6 + import { artistAtom } from "../../atoms/artist"; 7 + 8 + const Link = styled.a` 9 + text-decoration: none; 10 + color: #000; 11 + &:hover { 12 + text-decoration: underline; 13 + } 14 + `; 15 + 16 + function ExternalLinks() { 17 + const artist = useAtomValue(artistAtom); 18 + const location = useLocation(); 19 + const { pathname } = location; 20 + const display = 21 + pathname.includes("app.rocksky.scrobble") || 22 + pathname.includes("app.rocksky.song"); 23 + return ( 24 + <> 25 + {display && artist?.spotifyLink && ( 26 + <div style={{ marginTop: 50 }}> 27 + <LabelLarge marginBottom={"10px"}>External Links</LabelLarge> 28 + <Link href={artist?.spotifyLink} target="_blank"> 29 + <Spotify size={25} color="#1dd05d" /> 30 + <span style={{ marginLeft: 10 }}>Spotify</span> 31 + </Link> 32 + </div> 33 + )} 34 + </> 35 + ); 36 + } 37 + 38 + export default ExternalLinks;
+3
rockskyweb/src/layouts/ExternalLinks/index.tsx
··· 1 + import ExternalLinks from "./ExternalLinks"; 2 + 3 + export default ExternalLinks;
+3
rockskyweb/src/layouts/Main.tsx
··· 9 9 import { profileAtom } from "../atoms/profile"; 10 10 import { API_URL } from "../consts"; 11 11 import useProfile from "../hooks/useProfile"; 12 + import ExternalLinks from "./ExternalLinks"; 12 13 import Navbar from "./Navbar"; 13 14 import Search from "./Search"; 14 15 import SpotifyLogin from "./SpotifyLogin"; ··· 202 203 </div> 203 204 </div> 204 205 )} 206 + 207 + <ExternalLinks /> 205 208 </div> 206 209 </RightPane> 207 210 </Container>
+5 -12
rockskyweb/src/pages/artist/Artist.tsx
··· 1 1 import styled from "@emotion/styled"; 2 2 import { Avatar } from "baseui/avatar"; 3 3 import { HeadingMedium, HeadingXSmall, LabelMedium } from "baseui/typography"; 4 + import { useAtomValue, useSetAtom } from "jotai"; 4 5 import numeral from "numeral"; 5 6 import { useEffect, useState } from "react"; 6 7 import { useParams } from "react-router"; 8 + import { artistAtom } from "../../atoms/artist"; 7 9 import ArtistIcon from "../../components/Icons/Artist"; 8 10 import Shout from "../../components/Shout/Shout"; 9 11 import useLibrary from "../../hooks/useLibrary"; ··· 21 23 const Artist = () => { 22 24 const { did, rkey } = useParams<{ did: string; rkey: string }>(); 23 25 const { getArtist, getArtistTracks, getArtistAlbums } = useLibrary(); 24 - const [artist, setArtist] = useState<{ 25 - id: string; 26 - name: string; 27 - born?: string; 28 - bornIn?: string; 29 - died?: string; 30 - listeners: number; 31 - scrobbles: number; 32 - picture?: string; 33 - tags: string[]; 34 - uri: string; 35 - } | null>(null); 26 + const artist = useAtomValue(artistAtom); 27 + const setArtist = useSetAtom(artistAtom); 36 28 const [topTracks, setTopTracks] = useState< 37 29 { 38 30 id: string; ··· 74 66 picture: data.picture, 75 67 tags: data.tags, 76 68 uri: data.uri, 69 + spotifyLink: data.spotify_link, 77 70 }); 78 71 }; 79 72 fetchArtist();
+5 -12
rockskyweb/src/pages/song/Song.tsx
··· 6 6 LabelLarge, 7 7 LabelMedium, 8 8 } from "baseui/typography"; 9 + import { useAtomValue, useSetAtom } from "jotai"; 9 10 import numeral from "numeral"; 10 - import { useEffect, useState } from "react"; 11 + import { useEffect } from "react"; 11 12 import ContentLoader from "react-content-loader"; 12 13 import { Link as DefaultLink, useParams } from "react-router"; 14 + import { songAtom } from "../../atoms/song"; 13 15 import Disc from "../../components/Icons/Disc"; 14 16 import Shout from "../../components/Shout/Shout"; 15 17 import SongCover from "../../components/SongCover"; ··· 35 37 const { did, rkey } = useParams<{ did: string; rkey: string }>(); 36 38 const { getFeedByUri } = useFeed(); 37 39 const { getSongByUri } = useLibrary(); 38 - const [song, setSong] = useState<{ 39 - title: string; 40 - albumArtist: string; 41 - cover: string; 42 - listeners: number; 43 - scrobbles: number; 44 - tags: string[]; 45 - lyrics?: string; 46 - artistUri?: string; 47 - albumUri?: string; 48 - } | null>(null); 40 + const song = useAtomValue(songAtom); 41 + const setSong = useSetAtom(songAtom); 49 42 useEffect(() => { 50 43 const getSong = async () => { 51 44 // if path contains app.rocksky.scrobble, get the song