feat: add music widget
This commit is contained in:
22
src/hooks/status.ts
Normal file
22
src/hooks/status.ts
Normal file
@ -0,0 +1,22 @@
|
||||
import { useMemo } from "react";
|
||||
|
||||
import { EventKind, ReplaceableNoteStore, RequestBuilder } from "@snort/system";
|
||||
import { useRequestBuilder } from "@snort/system-react";
|
||||
|
||||
type StatusTag = "general" | "music";
|
||||
|
||||
export function useStatus(tag: StatusTag, author?: string, leaveOpen = true) {
|
||||
const sub = useMemo(() => {
|
||||
if (!author) return null;
|
||||
const b = new RequestBuilder(`status:${tag}:${author.slice(0, 8)}`);
|
||||
b.withOptions({ leaveOpen });
|
||||
b.withFilter()
|
||||
.kinds([30315 as EventKind])
|
||||
.tag("d", [tag])
|
||||
.authors([author]);
|
||||
return b;
|
||||
}, [author]);
|
||||
|
||||
const { data } = useRequestBuilder(ReplaceableNoteStore, sub);
|
||||
return data;
|
||||
}
|
@ -110,3 +110,21 @@
|
||||
width: 24px;
|
||||
height: 24px;
|
||||
}
|
||||
|
||||
.music {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
gap: 4px;
|
||||
}
|
||||
|
||||
.music .cover {
|
||||
object-fit: cover;
|
||||
width: 120px;
|
||||
height: 120px;
|
||||
}
|
||||
|
||||
.music .track {
|
||||
margin: 0;
|
||||
}
|
||||
|
@ -5,6 +5,7 @@ import { useParams } from "react-router-dom";
|
||||
import { ZapAlerts } from "./widgets/zaps";
|
||||
import { Views } from "./widgets/views";
|
||||
import { TopZappersWidget } from "./widgets/top-zappers";
|
||||
import { Music } from "./widgets/music";
|
||||
|
||||
export function AlertsPage() {
|
||||
const params = useParams();
|
||||
@ -24,6 +25,9 @@ export function AlertsPage() {
|
||||
case "top-zappers": {
|
||||
return <TopZappersWidget link={link} />;
|
||||
}
|
||||
case "music": {
|
||||
return <Music link={link} />;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
@ -78,7 +78,11 @@ export function LayoutPage() {
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => navigate("/settings")}>
|
||||
<Icon name="settings" size={24} />
|
||||
Settings
|
||||
<FormattedMessage defaultMessage="Settings" />
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => navigate("/widgets")}>
|
||||
<Icon name="widget" size={24} />
|
||||
<FormattedMessage defaultMessage="Widgets" />
|
||||
</MenuItem>
|
||||
<MenuItem onClick={() => Login.logout()}>
|
||||
<Icon name="logout" size={24} />
|
||||
|
@ -12,6 +12,7 @@ import { eventToLink, hexToBech32 } from "utils";
|
||||
import { ZapAlertItem } from "./widgets/zaps";
|
||||
import { TopZappersWidget } from "./widgets/top-zappers";
|
||||
import { Views } from "./widgets/views";
|
||||
import { Music } from "./widgets/music";
|
||||
import groupBy from "lodash/groupBy";
|
||||
|
||||
interface ZapAlertConfigurationProps {
|
||||
@ -195,6 +196,13 @@ export function WidgetsPage() {
|
||||
<Copy text={`${baseUrl}/alert/${npub}/views`} />
|
||||
{currentLink && <Views link={currentLink} />}
|
||||
</div>
|
||||
<div className="flex f-col g8">
|
||||
<h3>
|
||||
<FormattedMessage defaultMessage="Music" />
|
||||
</h3>
|
||||
<Copy text={`${baseUrl}/alert/${npub}/music`} />
|
||||
{currentLink && <Music link={currentLink} />}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
22
src/pages/widgets/music.tsx
Normal file
22
src/pages/widgets/music.tsx
Normal file
@ -0,0 +1,22 @@
|
||||
import { NostrLink } from "@snort/system";
|
||||
import { unixNow } from "@snort/shared";
|
||||
import { useCurrentStreamFeed } from "hooks/current-stream-feed";
|
||||
import { useStatus } from "hooks/status";
|
||||
import { getHost, findTag } from "utils";
|
||||
|
||||
export function Music({ link }: { link: NostrLink }) {
|
||||
const currentEvent = useCurrentStreamFeed(link, true);
|
||||
const host = getHost(currentEvent);
|
||||
const nowPlaying = useStatus("music", host, true);
|
||||
const cover = nowPlaying && findTag(nowPlaying, "cover");
|
||||
const expiry = nowPlaying && findTag(nowPlaying, "expiration");
|
||||
const isExpired = expiry && Number(expiry) > unixNow();
|
||||
return (
|
||||
!isExpired && (
|
||||
<div className="music">
|
||||
{cover && <img className="cover" src={cover} alt={nowPlaying.content} />}
|
||||
{nowPlaying && <p className="track">🎵 {nowPlaying.content}</p>}
|
||||
</div>
|
||||
)
|
||||
);
|
||||
}
|
Reference in New Issue
Block a user