feature/version-1 #1
@ -1,13 +1,20 @@
|
||||
import { useNavigate } from "@remix-run/react";
|
||||
import type { ReactNode} from "react";
|
||||
import { useEffect, useState } from "react";
|
||||
import type { StationWithTagsClientSide } from "~/models/station.server";
|
||||
import { getStationUrl } from "~/utils";
|
||||
|
||||
export type StationPlayerProps = {
|
||||
station: StationWithTagsClientSide | null
|
||||
station: StationWithTagsClientSide | null,
|
||||
nextPrevStationIds: {
|
||||
prev?: string;
|
||||
next?: string;
|
||||
},
|
||||
};
|
||||
|
||||
export function StationPlayer({ station }: StationPlayerProps) {
|
||||
export function StationPlayer({ station, nextPrevStationIds }: StationPlayerProps) {
|
||||
const [player, setPlayer] = useState<ReactNode | null>(null);
|
||||
const route = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (typeof window === 'undefined') return;
|
||||
@ -18,10 +25,20 @@ export function StationPlayer({ station }: StationPlayerProps) {
|
||||
const module = await import('react-radio-player');
|
||||
const RadioBottomBarPlayer = module.RadioBottomBarPlayer;
|
||||
setPlayer(<RadioBottomBarPlayer
|
||||
streamUrl={station.streamUrl}
|
||||
streamUrl={"http://91.223.70.109:8000/radio.mp3"}
|
||||
title={station.name}
|
||||
description={station.description || undefined}
|
||||
image={station.imgUrl}
|
||||
isNextButtonDisabled={!nextPrevStationIds.next}
|
||||
isPrevButtonDisabled={!nextPrevStationIds.prev}
|
||||
onNextButtonClicked={() => {
|
||||
if (!nextPrevStationIds.next) return;
|
||||
route(getStationUrl(nextPrevStationIds.next))
|
||||
}}
|
||||
onPrevButtonClicked={() => {
|
||||
if (!nextPrevStationIds.prev) return;
|
||||
route(getStationUrl(nextPrevStationIds.prev))
|
||||
}}
|
||||
secondDescription={<>★ {station.popularity}</>}
|
||||
/>);
|
||||
} catch (error) {
|
||||
|
@ -3,7 +3,7 @@ import type { Tag } from "@prisma/client";
|
||||
import { Link } from "@remix-run/react";
|
||||
import { ListenLink } from "~/components/page-layout";
|
||||
import type { StationWithTagsClientSide } from "~/models/station.server";
|
||||
import type { ConvertDatesToStrings } from "~/utils";
|
||||
import { getStationUrl, type ConvertDatesToStrings } from "~/utils";
|
||||
|
||||
export type StationsGalleryProps = {
|
||||
stations: StationWithTagsClientSide[];
|
||||
@ -11,14 +11,6 @@ export type StationsGalleryProps = {
|
||||
};
|
||||
|
||||
export function StationsGallery({ stations, tag }: StationsGalleryProps) {
|
||||
|
||||
function getStationUrl(id: string): string {
|
||||
if (tag) {
|
||||
return `/listen/tag/${tag?.slug}?station=${id}`;
|
||||
}
|
||||
return `/listen?station=${id}`;
|
||||
}
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-1 md:grid-cols-3 xl:grid-cols-4 gap-4">
|
||||
{stations.map((station) => {
|
||||
@ -37,7 +29,7 @@ export function StationsGallery({ stations, tag }: StationsGalleryProps) {
|
||||
</h2>
|
||||
<p>{station.description}</p>
|
||||
<div className="card-actions justify-end">
|
||||
<Link preventScrollReset to={getStationUrl(station.id)}
|
||||
<Link preventScrollReset to={getStationUrl(station.id, tag)}
|
||||
className={`btn btn-primary gap-2 plausible-event-name=play-station plausible-event-station=${station.slug}`}>
|
||||
<PlayIcon className="h-6 w-6" />
|
||||
Listen Now
|
||||
|
@ -37,6 +37,34 @@ export function getStations(reliability: number = 80) {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param stationId current station id that we want to get next and prev
|
||||
* @returns
|
||||
*/
|
||||
export const getPrevNextStations = async (stationId?: string) => {
|
||||
const defaultData = {
|
||||
prev: undefined,
|
||||
next: undefined
|
||||
}
|
||||
if (!stationId) return defaultData;
|
||||
|
||||
const stations = await getStations();
|
||||
|
||||
return stations.reduce((prev, currStation, index, array) => {
|
||||
if (currStation.id === stationId) {
|
||||
return {
|
||||
prev: array[index - 1]?.id,
|
||||
next: array[index + 1]?.id,
|
||||
}
|
||||
}
|
||||
return prev
|
||||
}, defaultData as {
|
||||
prev?: string,
|
||||
next?: string,
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch stations tagged with `tags` and a reliability score GTE to the `reliability` parameter.
|
||||
*/
|
||||
|
@ -4,7 +4,7 @@ import { Outlet, useLoaderData } from "@remix-run/react";
|
||||
import { PageLayout } from "~/components/page-layout";
|
||||
import { StationPlayer } from "~/components/station-player";
|
||||
import type { StationWithTags } from "~/models/station.server";
|
||||
import { getStationById } from "~/models/station.server";
|
||||
import { getPrevNextStations, getStationById } from "~/models/station.server";
|
||||
import type { TagWithStations } from "~/models/tag.server";
|
||||
import { getTags } from "~/models/tag.server";
|
||||
import { getUser } from "~/session.server";
|
||||
@ -15,15 +15,18 @@ export async function loader({ request }: LoaderArgs) {
|
||||
const url = new URL(request.url);
|
||||
const stationId = url.searchParams.get("station");
|
||||
const station: StationWithTags | null = stationId ? await getStationById(stationId) : null;
|
||||
return json({ user, tags, station });
|
||||
const prevNextStationIds = await getPrevNextStations(station?.id)
|
||||
return json({ user, tags, station, prevNextStationIds });
|
||||
}
|
||||
|
||||
export default function ListenLayout() {
|
||||
const { tags, user, station } = useLoaderData<typeof loader>();
|
||||
const { tags, user, station, prevNextStationIds } = useLoaderData<typeof loader>();
|
||||
|
||||
console.log(prevNextStationIds)
|
||||
return (
|
||||
<PageLayout tags={tags} user={user} station={station}>
|
||||
<Outlet />
|
||||
<StationPlayer station={station} />
|
||||
<StationPlayer station={station} nextPrevStationIds={prevNextStationIds} />
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
@ -27,6 +27,13 @@ export function safeRedirect(
|
||||
return to;
|
||||
}
|
||||
|
||||
export function getStationUrl(id: string, tag?: {slug: string}): string {
|
||||
if (tag) {
|
||||
return `/listen/tag/${tag?.slug}?station=${id}`;
|
||||
}
|
||||
return `/listen?station=${id}`;
|
||||
}
|
||||
|
||||
/**
|
||||
* This base hook is used in other hooks to quickly search for specific data
|
||||
* across all loader data using useMatches.
|
||||
|
@ -39,7 +39,7 @@
|
||||
"isbot": "^3.6.8",
|
||||
"react": "^18.2.0",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-radio-player": "^0.1.4",
|
||||
"react-radio-player": "^0.1.8",
|
||||
"tiny-invariant": "^1.3.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
|
@ -7712,10 +7712,10 @@ react-is@^18.0.0, react-is@^18.2.0:
|
||||
resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b"
|
||||
integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==
|
||||
|
||||
react-radio-player@^0.1.4:
|
||||
version "0.1.5"
|
||||
resolved "https://registry.yarnpkg.com/react-radio-player/-/react-radio-player-0.1.5.tgz#5fe89392c539997b090f7101797ad0f6e0acd328"
|
||||
integrity sha512-8lA309mOq2vT+JIznfimEJsWliIvJzxmvSXK8SA4BfRN9iXyd8oqm9VtI4311JPFgwYnG5ymvRXxp7GUj/bluw==
|
||||
react-radio-player@^0.1.8:
|
||||
version "0.1.8"
|
||||
resolved "https://registry.yarnpkg.com/react-radio-player/-/react-radio-player-0.1.8.tgz#85ad58adab1fd7f846ba39d79ef1a115eb50bca4"
|
||||
integrity sha512-PWCDBWfemSfMY7hoAeLBYwE8o49dEBg+PMIuIZDe3ZTpHqNIuPaL54SFmYHW4iMqSaE+9bToziXxpid9izberw==
|
||||
dependencies:
|
||||
rc-slider "^10.5.0"
|
||||
styled-components "^6.1.1"
|
||||
|
Loading…
x
Reference in New Issue
Block a user