mirror of
https://github.com/tsirysndr/music-player.git
synced 2026-01-10 13:47:59 -05:00
feat(webui): show current cast device on top of the page
This commit is contained in:
@@ -256,7 +256,21 @@ impl Player for Chromecast {
|
||||
if self.host.is_none() || self.port.is_none() {
|
||||
return Err(Error::msg("No device connected"));
|
||||
}
|
||||
let (cast_device, _, _, _) = self.connect_without_host_verification(None)?;
|
||||
|
||||
let cast_device = match CastDevice::connect_without_host_verification(
|
||||
self.host.as_ref().unwrap(),
|
||||
self.port.unwrap(),
|
||||
) {
|
||||
Ok(cast_device) => cast_device,
|
||||
Err(err) => panic!("Could not establish connection with Cast Device: {:?}", err),
|
||||
};
|
||||
|
||||
cast_device
|
||||
.connection
|
||||
.connect(DEFAULT_DESTINATION_ID.to_string())
|
||||
.unwrap();
|
||||
cast_device.heartbeat.ping().unwrap();
|
||||
|
||||
let status = cast_device.receiver.get_status().unwrap();
|
||||
|
||||
let current_app = &CastDeviceApp::from_str(DEFAULT_APP_ID).unwrap();
|
||||
|
||||
@@ -1121,6 +1121,39 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "connectToCastDevice",
|
||||
"description": null,
|
||||
"args": [
|
||||
{
|
||||
"name": "id",
|
||||
"description": null,
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "SCALAR",
|
||||
"name": "ID",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"defaultValue": null,
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
}
|
||||
],
|
||||
"type": {
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Device",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "connectToDevice",
|
||||
"description": null,
|
||||
@@ -1310,6 +1343,18 @@
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "disconnectFromCastDevice",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Device",
|
||||
"ofType": null
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "disconnectFromDevice",
|
||||
"description": null,
|
||||
@@ -2511,7 +2556,7 @@
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "connectedDevice",
|
||||
"name": "connectedCastDevice",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
@@ -2527,13 +2572,17 @@
|
||||
"deprecationReason": null
|
||||
},
|
||||
{
|
||||
"name": "currentCastDevice",
|
||||
"name": "connectedDevice",
|
||||
"description": null,
|
||||
"args": [],
|
||||
"type": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Device",
|
||||
"ofType": null
|
||||
"kind": "NON_NULL",
|
||||
"name": null,
|
||||
"ofType": {
|
||||
"kind": "OBJECT",
|
||||
"name": "Device",
|
||||
"ofType": null
|
||||
}
|
||||
},
|
||||
"isDeprecated": false,
|
||||
"deprecationReason": null
|
||||
|
||||
@@ -15,6 +15,7 @@ import { Track } from "../../Types";
|
||||
import { resourceUriResolver } from "../../ResourceUriResolver";
|
||||
import { Device } from "../../Types/Device";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import ListeningOn from "../ListeningOn";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
@@ -166,8 +167,11 @@ export type AlbumDetailsProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const AlbumDetails: FC<AlbumDetailsProps> = (props) => {
|
||||
@@ -180,6 +184,7 @@ const AlbumDetails: FC<AlbumDetailsProps> = (props) => {
|
||||
onCreatePlaylist,
|
||||
onAddTrackToPlaylist,
|
||||
recentPlaylists,
|
||||
currentCastDevice,
|
||||
} = props;
|
||||
const coverUrl = _.startsWith(album.cover, "https://")
|
||||
? album.cover
|
||||
@@ -187,71 +192,74 @@ const AlbumDetails: FC<AlbumDetailsProps> = (props) => {
|
||||
const { cover } = useCover(coverUrl);
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Container>
|
||||
<Sidebar active="albums" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
<BackButton onClick={onBack}>
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<ArrowBack color={theme.colors.text} />
|
||||
</div>
|
||||
</BackButton>
|
||||
<Album>
|
||||
{cover && <AlbumCover src={cover} />}
|
||||
{!cover && (
|
||||
<NoAlbumCover>
|
||||
<AlbumIcon />
|
||||
</NoAlbumCover>
|
||||
)}
|
||||
<Metadata>
|
||||
<MetadataContainer>
|
||||
<Title>{album.title}</Title>
|
||||
<Artist>{album.artist}</Artist>
|
||||
<Tracks>{album.tracks.length} TRACKS</Tracks>
|
||||
</MetadataContainer>
|
||||
<Buttons>
|
||||
<Button
|
||||
onClick={() => onPlayAlbum(album.id, false)}
|
||||
kind="primary"
|
||||
>
|
||||
<Label>
|
||||
<Icon>
|
||||
<Play small color="#fff" />
|
||||
</Icon>
|
||||
<div style={{ marginLeft: 7 }}>Play</div>
|
||||
</Label>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button
|
||||
onClick={() => onPlayAlbum(album.id, true)}
|
||||
kind="secondary"
|
||||
>
|
||||
<Label>
|
||||
<Shuffle color="#ab28fc" />
|
||||
<div style={{ marginLeft: 7 }}>Shuffle</div>
|
||||
</Label>
|
||||
</Button>
|
||||
</Buttons>
|
||||
</Metadata>
|
||||
</Album>
|
||||
<TracksTable
|
||||
tracks={album.tracks.map((track: any) => ({ ...track, cover }))}
|
||||
currentTrackId={nowPlaying.id}
|
||||
isPlaying={nowPlaying.isPlaying}
|
||||
header={["#", "Title", "Artist", "Time"]}
|
||||
maxHeight={"initial"}
|
||||
onPlayTrack={(id, position) => onPlayAlbum(id, false, position)}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
<>
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active="albums" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
<BackButton onClick={onBack}>
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<ArrowBack color={theme.colors.text} />
|
||||
</div>
|
||||
</BackButton>
|
||||
<Album>
|
||||
{cover && <AlbumCover src={cover} />}
|
||||
{!cover && (
|
||||
<NoAlbumCover>
|
||||
<AlbumIcon />
|
||||
</NoAlbumCover>
|
||||
)}
|
||||
<Metadata>
|
||||
<MetadataContainer>
|
||||
<Title>{album.title}</Title>
|
||||
<Artist>{album.artist}</Artist>
|
||||
<Tracks>{album.tracks.length} TRACKS</Tracks>
|
||||
</MetadataContainer>
|
||||
<Buttons>
|
||||
<Button
|
||||
onClick={() => onPlayAlbum(album.id, false)}
|
||||
kind="primary"
|
||||
>
|
||||
<Label>
|
||||
<Icon>
|
||||
<Play small color="#fff" />
|
||||
</Icon>
|
||||
<div style={{ marginLeft: 7 }}>Play</div>
|
||||
</Label>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button
|
||||
onClick={() => onPlayAlbum(album.id, true)}
|
||||
kind="secondary"
|
||||
>
|
||||
<Label>
|
||||
<Shuffle color="#ab28fc" />
|
||||
<div style={{ marginLeft: 7 }}>Shuffle</div>
|
||||
</Label>
|
||||
</Button>
|
||||
</Buttons>
|
||||
</Metadata>
|
||||
</Album>
|
||||
<TracksTable
|
||||
tracks={album.tracks.map((track: any) => ({ ...track, cover }))}
|
||||
currentTrackId={nowPlaying.id}
|
||||
isPlaying={nowPlaying.isPlaying}
|
||||
header={["#", "Title", "Artist", "Time"]}
|
||||
maxHeight={"initial"}
|
||||
onPlayTrack={(id, position) => onPlayAlbum(id, false, position)}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -102,8 +102,11 @@ export type AlbumsProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
export type AlbumProps = {
|
||||
@@ -128,10 +131,10 @@ const Album: FC<AlbumProps> = ({ onClick, album }) => {
|
||||
};
|
||||
|
||||
const Albums: FC<AlbumsProps> = (props) => {
|
||||
const { albums, onClickAlbum } = props;
|
||||
const { albums, onClickAlbum, currentCastDevice } = props;
|
||||
return (
|
||||
<>
|
||||
{false && <ListeningOn />}
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active="albums" {...props} />
|
||||
<Content>
|
||||
|
||||
@@ -14,6 +14,7 @@ import AlbumIcon from "../Icons/AlbumCover";
|
||||
import { Track } from "../../Types";
|
||||
import { Device } from "../../Types/Device";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import ListeningOn from "../ListeningOn";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
@@ -185,8 +186,11 @@ export type ArtistDetailsProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const ArtistDetails: FC<ArtistDetailsProps> = (props) => {
|
||||
@@ -200,89 +204,93 @@ const ArtistDetails: FC<ArtistDetailsProps> = (props) => {
|
||||
onCreatePlaylist,
|
||||
recentPlaylists,
|
||||
onAddTrackToPlaylist,
|
||||
currentCastDevice,
|
||||
} = props;
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
<BackButton onClick={onBack}>
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<ArrowBack color={theme.colors.text} />
|
||||
</div>
|
||||
</BackButton>
|
||||
<Artist>{artist.name}</Artist>
|
||||
<Buttons>
|
||||
<Button
|
||||
onClick={() => onPlayArtistTracks(artist.id, false)}
|
||||
kind="primary"
|
||||
>
|
||||
<Label>
|
||||
<Icon>
|
||||
<Play small color="#fff" />
|
||||
</Icon>
|
||||
<div style={{ marginLeft: 7 }}>Play</div>
|
||||
</Label>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button
|
||||
onClick={() => onPlayArtistTracks(artist.id, true)}
|
||||
kind="secondary"
|
||||
>
|
||||
<Label>
|
||||
<Shuffle color="#ab28fc" />
|
||||
<div style={{ marginLeft: 7 }}>Shuffle</div>
|
||||
</Label>
|
||||
</Button>
|
||||
</Buttons>
|
||||
<Tracks>
|
||||
<TracksTable
|
||||
tracks={tracks}
|
||||
title={
|
||||
<Row>
|
||||
<Title>Tracks</Title>
|
||||
<SeeMore>See all</SeeMore>
|
||||
</Row>
|
||||
}
|
||||
maxHeight={"initial"}
|
||||
onPlayTrack={(id, position) =>
|
||||
onPlayArtistTracks(id, false, position)
|
||||
}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
</Tracks>
|
||||
<Row>
|
||||
<Title>Albums</Title>
|
||||
<SeeMore>See all</SeeMore>
|
||||
</Row>
|
||||
<Grid gridColumns={[3, 4, 5]} gridMargins={[8, 16, 18]}>
|
||||
{albums.map((item) => (
|
||||
<Cell key={item.id}>
|
||||
<Link to={`/albums/${item.id}`}>
|
||||
{item.cover && <AlbumCover src={item.cover} />}
|
||||
{!item.cover && (
|
||||
<NoAlbumCover>
|
||||
<AlbumIcon size={120} />
|
||||
</NoAlbumCover>
|
||||
)}
|
||||
</Link>
|
||||
<Link to={`/albums/${item.id}`}>
|
||||
<AlbumTitle>{item.title}</AlbumTitle>
|
||||
</Link>
|
||||
<AlbumArtist>{item.artist}</AlbumArtist>
|
||||
</Cell>
|
||||
))}
|
||||
</Grid>
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
<>
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
<BackButton onClick={onBack}>
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<ArrowBack color={theme.colors.text} />
|
||||
</div>
|
||||
</BackButton>
|
||||
<Artist>{artist.name}</Artist>
|
||||
<Buttons>
|
||||
<Button
|
||||
onClick={() => onPlayArtistTracks(artist.id, false)}
|
||||
kind="primary"
|
||||
>
|
||||
<Label>
|
||||
<Icon>
|
||||
<Play small color="#fff" />
|
||||
</Icon>
|
||||
<div style={{ marginLeft: 7 }}>Play</div>
|
||||
</Label>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button
|
||||
onClick={() => onPlayArtistTracks(artist.id, true)}
|
||||
kind="secondary"
|
||||
>
|
||||
<Label>
|
||||
<Shuffle color="#ab28fc" />
|
||||
<div style={{ marginLeft: 7 }}>Shuffle</div>
|
||||
</Label>
|
||||
</Button>
|
||||
</Buttons>
|
||||
<Tracks>
|
||||
<TracksTable
|
||||
tracks={tracks}
|
||||
title={
|
||||
<Row>
|
||||
<Title>Tracks</Title>
|
||||
<SeeMore>See all</SeeMore>
|
||||
</Row>
|
||||
}
|
||||
maxHeight={"initial"}
|
||||
onPlayTrack={(id, position) =>
|
||||
onPlayArtistTracks(id, false, position)
|
||||
}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
</Tracks>
|
||||
<Row>
|
||||
<Title>Albums</Title>
|
||||
<SeeMore>See all</SeeMore>
|
||||
</Row>
|
||||
<Grid gridColumns={[3, 4, 5]} gridMargins={[8, 16, 18]}>
|
||||
{albums.map((item) => (
|
||||
<Cell key={item.id}>
|
||||
<Link to={`/albums/${item.id}`}>
|
||||
{item.cover && <AlbumCover src={item.cover} />}
|
||||
{!item.cover && (
|
||||
<NoAlbumCover>
|
||||
<AlbumIcon size={120} />
|
||||
</NoAlbumCover>
|
||||
)}
|
||||
</Link>
|
||||
<Link to={`/albums/${item.id}`}>
|
||||
<AlbumTitle>{item.title}</AlbumTitle>
|
||||
</Link>
|
||||
<AlbumArtist>{item.artist}</AlbumArtist>
|
||||
</Cell>
|
||||
))}
|
||||
</Grid>
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -5,6 +5,7 @@ import { Track } from "../../Types";
|
||||
import { Device } from "../../Types/Device";
|
||||
import ControlBar from "../ControlBar";
|
||||
import Artist from "../Icons/Artist";
|
||||
import ListeningOn from "../ListeningOn";
|
||||
import MainContent from "../MainContent";
|
||||
import Sidebar from "../Sidebar";
|
||||
|
||||
@@ -93,43 +94,49 @@ export type ArtistsProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const Artists: FC<ArtistsProps> = (props) => {
|
||||
const { onClickArtist, artists } = props;
|
||||
const { onClickArtist, artists, currentCastDevice } = props;
|
||||
return (
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<Scrollable>
|
||||
<MainContent title="Artists" placeholder="Filter Artists">
|
||||
<Wrapper>
|
||||
<Grid gridColumns={[2, 3, 4]} gridMargins={[8, 16, 18]}>
|
||||
{artists.map((item) => (
|
||||
<Cell key={item.id}>
|
||||
{item.cover && (
|
||||
<ArtistCover
|
||||
src={item.cover}
|
||||
onClick={() => onClickArtist(item)}
|
||||
/>
|
||||
)}
|
||||
{!item.cover && (
|
||||
<NoArtistCover onClick={() => onClickArtist(item)}>
|
||||
<Artist width={75} height={75} color="#a4a3a3" />
|
||||
</NoArtistCover>
|
||||
)}
|
||||
<ArtistName>{item.name}</ArtistName>
|
||||
</Cell>
|
||||
))}
|
||||
</Grid>
|
||||
</Wrapper>
|
||||
</MainContent>
|
||||
</Scrollable>
|
||||
</Content>
|
||||
</Container>
|
||||
<>
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<Scrollable>
|
||||
<MainContent title="Artists" placeholder="Filter Artists">
|
||||
<Wrapper>
|
||||
<Grid gridColumns={[2, 3, 4]} gridMargins={[8, 16, 18]}>
|
||||
{artists.map((item) => (
|
||||
<Cell key={item.id}>
|
||||
{item.cover && (
|
||||
<ArtistCover
|
||||
src={item.cover}
|
||||
onClick={() => onClickArtist(item)}
|
||||
/>
|
||||
)}
|
||||
{!item.cover && (
|
||||
<NoArtistCover onClick={() => onClickArtist(item)}>
|
||||
<Artist width={75} height={75} color="#a4a3a3" />
|
||||
</NoArtistCover>
|
||||
)}
|
||||
<ArtistName>{item.name}</ArtistName>
|
||||
</Cell>
|
||||
))}
|
||||
</Grid>
|
||||
</Wrapper>
|
||||
</MainContent>
|
||||
</Scrollable>
|
||||
</Content>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -68,6 +68,7 @@ export type ControlBarProps = {
|
||||
albumId: string;
|
||||
};
|
||||
castDevices: Device[];
|
||||
currentCastDevice?: Device;
|
||||
onPlay: () => void;
|
||||
onPause: () => void;
|
||||
onNext: () => void;
|
||||
@@ -78,6 +79,8 @@ export type ControlBarProps = {
|
||||
previousTracks?: Track[];
|
||||
onPlayTrackAt: (position: number) => void;
|
||||
onRemoveTrackAt: (position: number) => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const ControlBar: FC<ControlBarProps> = (props) => {
|
||||
@@ -147,7 +150,7 @@ const ControlBar: FC<ControlBarProps> = (props) => {
|
||||
<ButtonGroup>
|
||||
<StatefulPopover
|
||||
placement="bottom"
|
||||
content={() => <DeviceList {...props} />}
|
||||
content={({ close }) => <DeviceList {...props} close={close} />}
|
||||
overrides={{
|
||||
Body: {
|
||||
style: {
|
||||
|
||||
@@ -65,6 +65,22 @@ const IconWrapper = styled.div`
|
||||
margin-right: 16px;
|
||||
`;
|
||||
|
||||
const Disconnect = styled.button`
|
||||
background-color: #000;
|
||||
border: none;
|
||||
color: #fff;
|
||||
height: 21px;
|
||||
border-radius: 12px;
|
||||
font-family: "RockfordSansRegular";
|
||||
font-size: 12px;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
width: 80px;
|
||||
padding-bottom: 4px;
|
||||
cursor: pointer;
|
||||
`;
|
||||
|
||||
export type ArtworkProps = {
|
||||
icon?: string;
|
||||
color?: string;
|
||||
@@ -94,10 +110,20 @@ const DeviceName = styled.div`
|
||||
`;
|
||||
|
||||
export type DeviceListProps = {
|
||||
currentCastDevice?: Device;
|
||||
castDevices: Device[];
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
close: () => void;
|
||||
};
|
||||
|
||||
const DeviceList: FC<DeviceListProps> = ({ castDevices }) => {
|
||||
const DeviceList: FC<DeviceListProps> = ({
|
||||
castDevices,
|
||||
close,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
currentCastDevice,
|
||||
}) => {
|
||||
const theme = useTheme();
|
||||
const colors: {
|
||||
[key: string]: string;
|
||||
@@ -106,46 +132,66 @@ const DeviceList: FC<DeviceListProps> = ({ castDevices }) => {
|
||||
xbmc: "rgba(40, 203, 252, 0.082)",
|
||||
airplay: "rgba(255, 0, 195, 0.063)",
|
||||
};
|
||||
|
||||
const _onConnectToCastDevice = (deviceId: string) => {
|
||||
connectToCastDevice(deviceId);
|
||||
close();
|
||||
};
|
||||
|
||||
const _onDisconnectFromCastDevice = () => {
|
||||
disconnectFromCastDevice();
|
||||
close();
|
||||
};
|
||||
|
||||
return (
|
||||
<Container>
|
||||
<CurrentDeviceWrapper>
|
||||
<IconWrapper>
|
||||
<Laptop size={30} color={"#ab28fc"} />
|
||||
</IconWrapper>
|
||||
<div>
|
||||
<div style={{ flex: 1 }}>
|
||||
<CurrentDevice>Current device</CurrentDevice>
|
||||
<CurrentDeviceName>Music Player</CurrentDeviceName>
|
||||
<CurrentDeviceName>
|
||||
{currentCastDevice ? currentCastDevice.name : "Music Player"}
|
||||
</CurrentDeviceName>
|
||||
</div>
|
||||
{currentCastDevice && (
|
||||
<Disconnect onClick={_onDisconnectFromCastDevice}>
|
||||
disconnect
|
||||
</Disconnect>
|
||||
)}
|
||||
</CurrentDeviceWrapper>
|
||||
<Title>Select another output device</Title>
|
||||
<List>
|
||||
{castDevices.map((device) => (
|
||||
<ListItem
|
||||
key={device.id}
|
||||
artwork={() => (
|
||||
<Artwork icon={device.type} color={colors[device.type]} />
|
||||
)}
|
||||
overrides={{
|
||||
Root: {
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
":hover": {
|
||||
backgroundColor: theme.colors.hover,
|
||||
<div onClick={() => _onConnectToCastDevice(device.id)}>
|
||||
<ListItem
|
||||
key={device.id}
|
||||
artwork={() => (
|
||||
<Artwork icon={device.type} color={colors[device.type]} />
|
||||
)}
|
||||
overrides={{
|
||||
Root: {
|
||||
style: {
|
||||
cursor: "pointer",
|
||||
":hover": {
|
||||
backgroundColor: theme.colors.hover,
|
||||
},
|
||||
borderRadius: "5px",
|
||||
},
|
||||
borderRadius: "5px",
|
||||
},
|
||||
},
|
||||
Content: {
|
||||
style: {
|
||||
borderBottom: "none",
|
||||
Content: {
|
||||
style: {
|
||||
borderBottom: "none",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<ListItemLabel>
|
||||
<DeviceName>{device.name}</DeviceName>
|
||||
</ListItemLabel>
|
||||
</ListItem>
|
||||
}}
|
||||
>
|
||||
<ListItemLabel>
|
||||
<DeviceName>{device.name}</DeviceName>
|
||||
</ListItemLabel>
|
||||
</ListItem>
|
||||
</div>
|
||||
))}
|
||||
</List>
|
||||
</Container>
|
||||
|
||||
@@ -14,6 +14,7 @@ import { Track } from "../../Types";
|
||||
import { Folder as FolderIcon } from "@styled-icons/bootstrap";
|
||||
import MovePlaylistsModal from "./MovePlaylistsModal";
|
||||
import { Device } from "../../Types/Device";
|
||||
import ListeningOn from "../ListeningOn";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
@@ -194,8 +195,11 @@ export type FolderProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const Folder: FC<FolderProps> = (props) => {
|
||||
@@ -206,53 +210,60 @@ const Folder: FC<FolderProps> = (props) => {
|
||||
mainPlaylists,
|
||||
folder,
|
||||
onMovePlaylists,
|
||||
currentCastDevice,
|
||||
} = props;
|
||||
const [isMovePlaylistsModalOpen, setIsMovePlaylistsModalOpen] =
|
||||
useState(false);
|
||||
return (
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} playlists={mainPlaylists} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
{folder?.playlists?.length > 0 && (
|
||||
<Scrollable>
|
||||
<MainContent title="Playlists" placeholder="Filter Playlists">
|
||||
<Wrapper>
|
||||
<Grid gridColumns={[2, 3, 4, 6]} gridMargins={[8, 16, 18]}>
|
||||
{folder?.playlists.map((item: any) => (
|
||||
<Cell key={item.id}>
|
||||
<Playlist playlist={item} />
|
||||
</Cell>
|
||||
))}
|
||||
</Grid>
|
||||
</Wrapper>
|
||||
</MainContent>
|
||||
</Scrollable>
|
||||
)}
|
||||
{folder?.playlists?.length === 0 && (
|
||||
<PlaceholderWrapper>
|
||||
<FolderIcon size={100} color="rgb(70, 70, 70)" />
|
||||
<Placeholder>
|
||||
Start moving playlists to your folder.
|
||||
</Placeholder>
|
||||
<Button onClick={() => setIsMovePlaylistsModalOpen(true)}>
|
||||
Move Playlists
|
||||
</Button>
|
||||
</PlaceholderWrapper>
|
||||
)}
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
<MovePlaylistsModal
|
||||
isOpen={isMovePlaylistsModalOpen}
|
||||
onClose={() => setIsMovePlaylistsModalOpen(false)}
|
||||
onMovePlaylists={onMovePlaylists}
|
||||
playlists={playlists}
|
||||
folderId={folder?.id}
|
||||
/>
|
||||
</Container>
|
||||
<>
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} playlists={mainPlaylists} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
{folder?.playlists?.length > 0 && (
|
||||
<Scrollable>
|
||||
<MainContent title="Playlists" placeholder="Filter Playlists">
|
||||
<Wrapper>
|
||||
<Grid
|
||||
gridColumns={[2, 3, 4, 6]}
|
||||
gridMargins={[8, 16, 18]}
|
||||
>
|
||||
{folder?.playlists.map((item: any) => (
|
||||
<Cell key={item.id}>
|
||||
<Playlist playlist={item} />
|
||||
</Cell>
|
||||
))}
|
||||
</Grid>
|
||||
</Wrapper>
|
||||
</MainContent>
|
||||
</Scrollable>
|
||||
)}
|
||||
{folder?.playlists?.length === 0 && (
|
||||
<PlaceholderWrapper>
|
||||
<FolderIcon size={100} color="rgb(70, 70, 70)" />
|
||||
<Placeholder>
|
||||
Start moving playlists to your folder.
|
||||
</Placeholder>
|
||||
<Button onClick={() => setIsMovePlaylistsModalOpen(true)}>
|
||||
Move Playlists
|
||||
</Button>
|
||||
</PlaceholderWrapper>
|
||||
)}
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
<MovePlaylistsModal
|
||||
isOpen={isMovePlaylistsModalOpen}
|
||||
onClose={() => setIsMovePlaylistsModalOpen(false)}
|
||||
onMovePlaylists={onMovePlaylists}
|
||||
playlists={playlists}
|
||||
folderId={folder?.id}
|
||||
/>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ const Container = styled.div`
|
||||
position: relative;
|
||||
background: ${(props) => props.theme.colors.tooltip};
|
||||
color: #ab28fc;
|
||||
justify-content: flex-end;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-right: 20px;
|
||||
padding-top: 2px;
|
||||
@@ -31,9 +31,10 @@ const IconWrapper = styled.div`
|
||||
|
||||
export type ListeningOnProps = {
|
||||
icon?: "music-player" | "xbmc" | "airplay" | "chromecast";
|
||||
deviceName?: string;
|
||||
};
|
||||
|
||||
const ListeningOn: FC<ListeningOnProps> = ({ icon }) => {
|
||||
const ListeningOn: FC<ListeningOnProps> = ({ icon, deviceName }) => {
|
||||
return (
|
||||
<Wrapper>
|
||||
<Container>
|
||||
@@ -47,7 +48,7 @@ const ListeningOn: FC<ListeningOnProps> = ({ icon }) => {
|
||||
{icon === "chromecast" && <Chromecast size={15} color={"#ab28fc"} />}
|
||||
</IconWrapper>
|
||||
<div style={{ marginTop: -3, marginRight: 25 }}>
|
||||
Listening on Salon TV
|
||||
Listening on {deviceName}
|
||||
</div>
|
||||
</Container>
|
||||
</Wrapper>
|
||||
|
||||
@@ -16,6 +16,7 @@ import { useTimeFormat } from "../../Hooks/useFormat";
|
||||
import { resourceUriResolver } from "../../ResourceUriResolver";
|
||||
import { Device } from "../../Types/Device";
|
||||
import { useTheme } from "@emotion/react";
|
||||
import ListeningOn from "../ListeningOn";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
@@ -155,8 +156,11 @@ export type PlaylistProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const Playlist: FC<PlaylistProps> = (props) => {
|
||||
@@ -169,6 +173,7 @@ const Playlist: FC<PlaylistProps> = (props) => {
|
||||
nowPlaying,
|
||||
playlist,
|
||||
recentPlaylists,
|
||||
currentCastDevice,
|
||||
} = props;
|
||||
const { formatTime } = useTimeFormat();
|
||||
const tracks =
|
||||
@@ -186,82 +191,85 @@ const Playlist: FC<PlaylistProps> = (props) => {
|
||||
})) || [];
|
||||
const theme = useTheme();
|
||||
return (
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
<BackButton onClick={onBack}>
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<ArrowBack color={theme.colors.text} />
|
||||
</div>
|
||||
</BackButton>
|
||||
<Header>
|
||||
<NoCover>
|
||||
<PlaylistIcon
|
||||
size={48}
|
||||
color="#ab28fc"
|
||||
style={{ marginRight: -38, marginTop: 38 }}
|
||||
<>
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active="artists" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent displayHeader={false}>
|
||||
<Scrollable>
|
||||
<BackButton onClick={onBack}>
|
||||
<div style={{ marginTop: 2 }}>
|
||||
<ArrowBack color={theme.colors.text} />
|
||||
</div>
|
||||
</BackButton>
|
||||
<Header>
|
||||
<NoCover>
|
||||
<PlaylistIcon
|
||||
size={48}
|
||||
color="#ab28fc"
|
||||
style={{ marginRight: -38, marginTop: 38 }}
|
||||
/>
|
||||
</NoCover>
|
||||
<PlaylistDetails>
|
||||
<PlaylistDetailsWrapper>
|
||||
<Title>{playlist.name}</Title>
|
||||
</PlaylistDetailsWrapper>
|
||||
<Buttons>
|
||||
<Button
|
||||
onClick={() => onPlayPlaylist(playlist.id, false)}
|
||||
kind="primary"
|
||||
disabled={!tracks.length}
|
||||
>
|
||||
<Label>
|
||||
<Icon>
|
||||
<Play small color="#fff" />
|
||||
</Icon>
|
||||
<div style={{ marginLeft: 7 }}>Play</div>
|
||||
</Label>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button
|
||||
onClick={() => onPlayPlaylist(playlist.id, true)}
|
||||
kind="secondary"
|
||||
disabled={!tracks.length}
|
||||
>
|
||||
<Label>
|
||||
<Shuffle color="#ab28fc" />
|
||||
<div style={{ marginLeft: 7 }}>Shuffle</div>
|
||||
</Label>
|
||||
</Button>
|
||||
</Buttons>
|
||||
</PlaylistDetails>
|
||||
</Header>
|
||||
{tracks.length === 0 && (
|
||||
<Placeholder>
|
||||
Start building your playlist with tracks by tapping on ‘Add to
|
||||
playlist’ in the option menu.
|
||||
</Placeholder>
|
||||
)}
|
||||
{tracks.length > 0 && (
|
||||
<TracksTable
|
||||
tracks={tracks}
|
||||
currentTrackId={nowPlaying.id}
|
||||
isPlaying={nowPlaying.isPlaying}
|
||||
header={["Title", "Artist", "Album", "Time"]}
|
||||
maxHeight={"initial"}
|
||||
onPlayTrack={(id, position) =>
|
||||
onPlayPlaylist(id, false, position)
|
||||
}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
</NoCover>
|
||||
<PlaylistDetails>
|
||||
<PlaylistDetailsWrapper>
|
||||
<Title>{playlist.name}</Title>
|
||||
</PlaylistDetailsWrapper>
|
||||
<Buttons>
|
||||
<Button
|
||||
onClick={() => onPlayPlaylist(playlist.id, false)}
|
||||
kind="primary"
|
||||
disabled={!tracks.length}
|
||||
>
|
||||
<Label>
|
||||
<Icon>
|
||||
<Play small color="#fff" />
|
||||
</Icon>
|
||||
<div style={{ marginLeft: 7 }}>Play</div>
|
||||
</Label>
|
||||
</Button>
|
||||
<Separator />
|
||||
<Button
|
||||
onClick={() => onPlayPlaylist(playlist.id, true)}
|
||||
kind="secondary"
|
||||
disabled={!tracks.length}
|
||||
>
|
||||
<Label>
|
||||
<Shuffle color="#ab28fc" />
|
||||
<div style={{ marginLeft: 7 }}>Shuffle</div>
|
||||
</Label>
|
||||
</Button>
|
||||
</Buttons>
|
||||
</PlaylistDetails>
|
||||
</Header>
|
||||
{tracks.length === 0 && (
|
||||
<Placeholder>
|
||||
Start building your playlist with tracks by tapping on ‘Add to
|
||||
playlist’ in the option menu.
|
||||
</Placeholder>
|
||||
)}
|
||||
{tracks.length > 0 && (
|
||||
<TracksTable
|
||||
tracks={tracks}
|
||||
currentTrackId={nowPlaying.id}
|
||||
isPlaying={nowPlaying.isPlaying}
|
||||
header={["Title", "Artist", "Album", "Time"]}
|
||||
maxHeight={"initial"}
|
||||
onPlayTrack={(id, position) =>
|
||||
onPlayPlaylist(id, false, position)
|
||||
}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
)}
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
)}
|
||||
</Scrollable>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ import Albums from "./Albums";
|
||||
import Artists from "./Artists";
|
||||
import Playlists from "./Playlists";
|
||||
import { Device } from "../../Types/Device";
|
||||
import ListeningOn from "../ListeningOn";
|
||||
|
||||
const Container = styled.div`
|
||||
display: flex;
|
||||
@@ -66,59 +67,66 @@ export type SearchResultsProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const SearchResults: FC<SearchResultsProps> = (props) => {
|
||||
const [activeKey, setActiveKey] = useState<React.Key>(0);
|
||||
const { tracks, nowPlaying, onPlayTrack, onPlayNext } = props;
|
||||
const { tracks, nowPlaying, onPlayTrack, onPlayNext, currentCastDevice } =
|
||||
props;
|
||||
return (
|
||||
<Container>
|
||||
<Sidebar active={""} {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<div>
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
onChange={({ activeKey }) => setActiveKey(activeKey)}
|
||||
overrides={{
|
||||
TabList: {
|
||||
style: {
|
||||
marginLeft: "26px",
|
||||
marginRight: "26px",
|
||||
<>
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active={""} {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<div>
|
||||
<Tabs
|
||||
activeKey={activeKey}
|
||||
onChange={({ activeKey }) => setActiveKey(activeKey)}
|
||||
overrides={{
|
||||
TabList: {
|
||||
style: {
|
||||
marginLeft: "26px",
|
||||
marginRight: "26px",
|
||||
},
|
||||
},
|
||||
},
|
||||
TabBorder: {
|
||||
style: {
|
||||
marginLeft: "26px",
|
||||
marginRight: "26px",
|
||||
TabBorder: {
|
||||
style: {
|
||||
marginLeft: "26px",
|
||||
marginRight: "26px",
|
||||
},
|
||||
},
|
||||
},
|
||||
}}
|
||||
>
|
||||
<Tab title="Tracks">
|
||||
<Results>
|
||||
<Tracks {...props} />
|
||||
</Results>
|
||||
</Tab>
|
||||
<Tab title="Albums">
|
||||
<Results>
|
||||
<Albums {...props} />
|
||||
</Results>
|
||||
</Tab>
|
||||
<Tab title="Artists">
|
||||
<Results>
|
||||
<Artists {...props} />
|
||||
</Results>
|
||||
</Tab>
|
||||
<Tab title="Playlists">
|
||||
<Playlists />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</Content>
|
||||
</Container>
|
||||
}}
|
||||
>
|
||||
<Tab title="Tracks">
|
||||
<Results>
|
||||
<Tracks {...props} />
|
||||
</Results>
|
||||
</Tab>
|
||||
<Tab title="Albums">
|
||||
<Results>
|
||||
<Albums {...props} />
|
||||
</Results>
|
||||
</Tab>
|
||||
<Tab title="Artists">
|
||||
<Results>
|
||||
<Artists {...props} />
|
||||
</Results>
|
||||
</Tab>
|
||||
<Tab title="Playlists">
|
||||
<Playlists />
|
||||
</Tab>
|
||||
</Tabs>
|
||||
</div>
|
||||
</Content>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@ import { FC } from "react";
|
||||
import { Track } from "../../Types";
|
||||
import { Device } from "../../Types/Device";
|
||||
import ControlBar from "../ControlBar";
|
||||
import ListeningOn from "../ListeningOn";
|
||||
import MainContent from "../MainContent";
|
||||
import Sidebar from "../Sidebar";
|
||||
import TracksTable from "../TracksTable";
|
||||
@@ -54,8 +55,11 @@ export type TracksProps = {
|
||||
devices: Device[];
|
||||
castDevices: Device[];
|
||||
currentDevice?: Device;
|
||||
currentCastDevice?: Device;
|
||||
connectToDevice: (deviceId: string) => void;
|
||||
disconnectFromDevice: () => void;
|
||||
connectToCastDevice: (deviceId: string) => void;
|
||||
disconnectFromCastDevice: () => void;
|
||||
};
|
||||
|
||||
const Tracks: FC<TracksProps> = (props) => {
|
||||
@@ -67,26 +71,30 @@ const Tracks: FC<TracksProps> = (props) => {
|
||||
onCreatePlaylist,
|
||||
onAddTrackToPlaylist,
|
||||
recentPlaylists,
|
||||
currentCastDevice,
|
||||
} = props;
|
||||
return (
|
||||
<Container>
|
||||
<Sidebar active="tracks" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent title="Tracks">
|
||||
<TracksTable
|
||||
tracks={tracks}
|
||||
currentTrackId={nowPlaying.id}
|
||||
isPlaying={nowPlaying.isPlaying}
|
||||
onPlayTrack={onPlayTrack}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
<>
|
||||
{currentCastDevice && <ListeningOn deviceName={currentCastDevice.name} />}
|
||||
<Container>
|
||||
<Sidebar active="tracks" {...props} />
|
||||
<Content>
|
||||
<ControlBar {...props} />
|
||||
<MainContent title="Tracks">
|
||||
<TracksTable
|
||||
tracks={tracks}
|
||||
currentTrackId={nowPlaying.id}
|
||||
isPlaying={nowPlaying.isPlaying}
|
||||
onPlayTrack={onPlayTrack}
|
||||
onPlayNext={onPlayNext}
|
||||
onCreatePlaylist={onCreatePlaylist}
|
||||
recentPlaylists={recentPlaylists}
|
||||
onAddTrackToPlaylist={onAddTrackToPlaylist}
|
||||
/>
|
||||
</MainContent>
|
||||
</Content>
|
||||
</Container>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,8 +14,11 @@ const AlbumDetailsPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const { data, loading, refetch } = useGetAlbumQuery({
|
||||
variables: {
|
||||
@@ -113,8 +116,11 @@ const AlbumDetailsPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -30,8 +30,11 @@ const AlbumsPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const albums = !loading && data ? data.albums : [];
|
||||
const {
|
||||
@@ -88,8 +91,11 @@ const AlbumsPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -43,8 +43,11 @@ const ArtistDetailsPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const artist = !loading && data ? data.artist : {};
|
||||
const tracks =
|
||||
@@ -130,8 +133,11 @@ const ArtistDetailsPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -27,8 +27,11 @@ const ArtistsPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const artists = !loading && data ? data.artists : [];
|
||||
const {
|
||||
@@ -84,8 +87,11 @@ const ArtistsPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -40,8 +40,11 @@ const FolderPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const {
|
||||
folders,
|
||||
@@ -95,8 +98,11 @@ const FolderPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -19,8 +19,11 @@ const PlaylistPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const { formatTime } = useTimeFormat();
|
||||
const {
|
||||
@@ -91,8 +94,11 @@ const PlaylistPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -14,8 +14,11 @@ const SearchPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const {
|
||||
play,
|
||||
@@ -104,8 +107,11 @@ const SearchPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -32,8 +32,11 @@ const TracksPage = () => {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
} = useDevices();
|
||||
const tracks = !loading && data ? data.tracks : [];
|
||||
const {
|
||||
@@ -104,8 +107,11 @@ const TracksPage = () => {
|
||||
devices={devices}
|
||||
castDevices={castDevices}
|
||||
currentDevice={currentDevice}
|
||||
currentCastDevice={currentCastDevice}
|
||||
connectToDevice={(id) => connectToDevice({ variables: { id } })}
|
||||
disconnectFromDevice={() => disconnectFromDevice()}
|
||||
connectToCastDevice={(id) => connectToCastDevice({ variables: { id } })}
|
||||
disconnectFromCastDevice={() => disconnectFromCastDevice()}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
|
||||
@@ -15,3 +15,19 @@ export const DISCONNECT_FROM_DEVICE = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CONNECT_TO_CAST_DEVICE = gql`
|
||||
mutation ConnectToCastDevice($id: ID!) {
|
||||
connectToCastDevice(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const DISCONNECT_FROM_CAST_DEVICE = gql`
|
||||
mutation DisconnectFromCastDevice {
|
||||
disconnectFromCastDevice {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -40,3 +40,16 @@ export const CONNECTED_DEVICE = gql`
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
export const CONNECTED_CAST_DEVICE = gql`
|
||||
query ConnectedCastDevice {
|
||||
connectedCastDevice {
|
||||
id
|
||||
name
|
||||
app
|
||||
host
|
||||
port
|
||||
isConnected
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -19,6 +19,8 @@ export const ON_DEVICE_CONNECTED = gql`
|
||||
onConnected {
|
||||
id
|
||||
name
|
||||
service
|
||||
app
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -28,6 +30,8 @@ export const ON_DEVICE_DISCONNECTED = gql`
|
||||
onDisconnected {
|
||||
id
|
||||
name
|
||||
service
|
||||
app
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -106,11 +106,13 @@ export type Mutation = {
|
||||
addTrackToPlaylist: Playlist;
|
||||
addTracks: Scalars['Boolean'];
|
||||
clearTracklist: Scalars['Boolean'];
|
||||
connectToCastDevice: Device;
|
||||
connectToDevice: Device;
|
||||
createFolder: Folder;
|
||||
createPlaylist: Playlist;
|
||||
deleteFolder: Folder;
|
||||
deletePlaylist: Playlist;
|
||||
disconnectFromCastDevice?: Maybe<Device>;
|
||||
disconnectFromDevice?: Maybe<Device>;
|
||||
movePlaylistToFolder: Folder;
|
||||
movePlaylistsToFolder: Folder;
|
||||
@@ -152,6 +154,11 @@ export type MutationAddTracksArgs = {
|
||||
};
|
||||
|
||||
|
||||
export type MutationConnectToCastDeviceArgs = {
|
||||
id: Scalars['ID'];
|
||||
};
|
||||
|
||||
|
||||
export type MutationConnectToDeviceArgs = {
|
||||
id: Scalars['ID'];
|
||||
};
|
||||
@@ -301,8 +308,8 @@ export type Query = {
|
||||
albums: Array<Album>;
|
||||
artist: Artist;
|
||||
artists: Array<Artist>;
|
||||
connectedCastDevice: Device;
|
||||
connectedDevice: Device;
|
||||
currentCastDevice?: Maybe<Device>;
|
||||
currentlyPlayingSong: CurrentlyPlayingSong;
|
||||
folder: Folder;
|
||||
folders: Array<Folder>;
|
||||
@@ -465,6 +472,18 @@ export type DisconnectFromDeviceMutationVariables = Exact<{ [key: string]: never
|
||||
|
||||
export type DisconnectFromDeviceMutation = { __typename?: 'Mutation', disconnectFromDevice?: { __typename?: 'Device', id: string } | null };
|
||||
|
||||
export type ConnectToCastDeviceMutationVariables = Exact<{
|
||||
id: Scalars['ID'];
|
||||
}>;
|
||||
|
||||
|
||||
export type ConnectToCastDeviceMutation = { __typename?: 'Mutation', connectToCastDevice: { __typename?: 'Device', id: string } };
|
||||
|
||||
export type DisconnectFromCastDeviceMutationVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type DisconnectFromCastDeviceMutation = { __typename?: 'Mutation', disconnectFromCastDevice?: { __typename?: 'Device', id: string } | null };
|
||||
|
||||
export type ListDevicesQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
@@ -480,6 +499,11 @@ export type ConnectedDeviceQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
export type ConnectedDeviceQuery = { __typename?: 'Query', connectedDevice: { __typename?: 'Device', id: string, name: string, app: string, host: string, port: number, isConnected: boolean } };
|
||||
|
||||
export type ConnectedCastDeviceQueryVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type ConnectedCastDeviceQuery = { __typename?: 'Query', connectedCastDevice: { __typename?: 'Device', id: string, name: string, app: string, host: string, port: number, isConnected: boolean } };
|
||||
|
||||
export type OnNewDeviceSubscriptionVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
@@ -488,12 +512,12 @@ export type OnNewDeviceSubscription = { __typename?: 'Subscription', onNewDevice
|
||||
export type OnDeviceConnectedSubscriptionVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type OnDeviceConnectedSubscription = { __typename?: 'Subscription', onConnected: { __typename?: 'ConnectedDevice', id: string, name: string } };
|
||||
export type OnDeviceConnectedSubscription = { __typename?: 'Subscription', onConnected: { __typename?: 'ConnectedDevice', id: string, name: string, service: string, app: string } };
|
||||
|
||||
export type OnDeviceDisconnectedSubscriptionVariables = Exact<{ [key: string]: never; }>;
|
||||
|
||||
|
||||
export type OnDeviceDisconnectedSubscription = { __typename?: 'Subscription', onDisconnected: { __typename?: 'DisconnectedDevice', id: string, name: string } };
|
||||
export type OnDeviceDisconnectedSubscription = { __typename?: 'Subscription', onDisconnected: { __typename?: 'DisconnectedDevice', id: string, name: string, service: string, app: string } };
|
||||
|
||||
export type AlbumFragmentFragment = { __typename?: 'Album', id: string, title: string, artist: string, year?: number | null, cover?: string | null };
|
||||
|
||||
@@ -877,6 +901,71 @@ export function useDisconnectFromDeviceMutation(baseOptions?: Apollo.MutationHoo
|
||||
export type DisconnectFromDeviceMutationHookResult = ReturnType<typeof useDisconnectFromDeviceMutation>;
|
||||
export type DisconnectFromDeviceMutationResult = Apollo.MutationResult<DisconnectFromDeviceMutation>;
|
||||
export type DisconnectFromDeviceMutationOptions = Apollo.BaseMutationOptions<DisconnectFromDeviceMutation, DisconnectFromDeviceMutationVariables>;
|
||||
export const ConnectToCastDeviceDocument = gql`
|
||||
mutation ConnectToCastDevice($id: ID!) {
|
||||
connectToCastDevice(id: $id) {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type ConnectToCastDeviceMutationFn = Apollo.MutationFunction<ConnectToCastDeviceMutation, ConnectToCastDeviceMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useConnectToCastDeviceMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useConnectToCastDeviceMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useConnectToCastDeviceMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [connectToCastDeviceMutation, { data, loading, error }] = useConnectToCastDeviceMutation({
|
||||
* variables: {
|
||||
* id: // value for 'id'
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useConnectToCastDeviceMutation(baseOptions?: Apollo.MutationHookOptions<ConnectToCastDeviceMutation, ConnectToCastDeviceMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<ConnectToCastDeviceMutation, ConnectToCastDeviceMutationVariables>(ConnectToCastDeviceDocument, options);
|
||||
}
|
||||
export type ConnectToCastDeviceMutationHookResult = ReturnType<typeof useConnectToCastDeviceMutation>;
|
||||
export type ConnectToCastDeviceMutationResult = Apollo.MutationResult<ConnectToCastDeviceMutation>;
|
||||
export type ConnectToCastDeviceMutationOptions = Apollo.BaseMutationOptions<ConnectToCastDeviceMutation, ConnectToCastDeviceMutationVariables>;
|
||||
export const DisconnectFromCastDeviceDocument = gql`
|
||||
mutation DisconnectFromCastDevice {
|
||||
disconnectFromCastDevice {
|
||||
id
|
||||
}
|
||||
}
|
||||
`;
|
||||
export type DisconnectFromCastDeviceMutationFn = Apollo.MutationFunction<DisconnectFromCastDeviceMutation, DisconnectFromCastDeviceMutationVariables>;
|
||||
|
||||
/**
|
||||
* __useDisconnectFromCastDeviceMutation__
|
||||
*
|
||||
* To run a mutation, you first call `useDisconnectFromCastDeviceMutation` within a React component and pass it any options that fit your needs.
|
||||
* When your component renders, `useDisconnectFromCastDeviceMutation` returns a tuple that includes:
|
||||
* - A mutate function that you can call at any time to execute the mutation
|
||||
* - An object with fields that represent the current status of the mutation's execution
|
||||
*
|
||||
* @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2;
|
||||
*
|
||||
* @example
|
||||
* const [disconnectFromCastDeviceMutation, { data, loading, error }] = useDisconnectFromCastDeviceMutation({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useDisconnectFromCastDeviceMutation(baseOptions?: Apollo.MutationHookOptions<DisconnectFromCastDeviceMutation, DisconnectFromCastDeviceMutationVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useMutation<DisconnectFromCastDeviceMutation, DisconnectFromCastDeviceMutationVariables>(DisconnectFromCastDeviceDocument, options);
|
||||
}
|
||||
export type DisconnectFromCastDeviceMutationHookResult = ReturnType<typeof useDisconnectFromCastDeviceMutation>;
|
||||
export type DisconnectFromCastDeviceMutationResult = Apollo.MutationResult<DisconnectFromCastDeviceMutation>;
|
||||
export type DisconnectFromCastDeviceMutationOptions = Apollo.BaseMutationOptions<DisconnectFromCastDeviceMutation, DisconnectFromCastDeviceMutationVariables>;
|
||||
export const ListDevicesDocument = gql`
|
||||
query ListDevices {
|
||||
listDevices {
|
||||
@@ -996,6 +1085,45 @@ export function useConnectedDeviceLazyQuery(baseOptions?: Apollo.LazyQueryHookOp
|
||||
export type ConnectedDeviceQueryHookResult = ReturnType<typeof useConnectedDeviceQuery>;
|
||||
export type ConnectedDeviceLazyQueryHookResult = ReturnType<typeof useConnectedDeviceLazyQuery>;
|
||||
export type ConnectedDeviceQueryResult = Apollo.QueryResult<ConnectedDeviceQuery, ConnectedDeviceQueryVariables>;
|
||||
export const ConnectedCastDeviceDocument = gql`
|
||||
query ConnectedCastDevice {
|
||||
connectedCastDevice {
|
||||
id
|
||||
name
|
||||
app
|
||||
host
|
||||
port
|
||||
isConnected
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
/**
|
||||
* __useConnectedCastDeviceQuery__
|
||||
*
|
||||
* To run a query within a React component, call `useConnectedCastDeviceQuery` and pass it any options that fit your needs.
|
||||
* When your component renders, `useConnectedCastDeviceQuery` returns an object from Apollo Client that contains loading, error, and data properties
|
||||
* you can use to render your UI.
|
||||
*
|
||||
* @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options;
|
||||
*
|
||||
* @example
|
||||
* const { data, loading, error } = useConnectedCastDeviceQuery({
|
||||
* variables: {
|
||||
* },
|
||||
* });
|
||||
*/
|
||||
export function useConnectedCastDeviceQuery(baseOptions?: Apollo.QueryHookOptions<ConnectedCastDeviceQuery, ConnectedCastDeviceQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useQuery<ConnectedCastDeviceQuery, ConnectedCastDeviceQueryVariables>(ConnectedCastDeviceDocument, options);
|
||||
}
|
||||
export function useConnectedCastDeviceLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions<ConnectedCastDeviceQuery, ConnectedCastDeviceQueryVariables>) {
|
||||
const options = {...defaultOptions, ...baseOptions}
|
||||
return Apollo.useLazyQuery<ConnectedCastDeviceQuery, ConnectedCastDeviceQueryVariables>(ConnectedCastDeviceDocument, options);
|
||||
}
|
||||
export type ConnectedCastDeviceQueryHookResult = ReturnType<typeof useConnectedCastDeviceQuery>;
|
||||
export type ConnectedCastDeviceLazyQueryHookResult = ReturnType<typeof useConnectedCastDeviceLazyQuery>;
|
||||
export type ConnectedCastDeviceQueryResult = Apollo.QueryResult<ConnectedCastDeviceQuery, ConnectedCastDeviceQueryVariables>;
|
||||
export const OnNewDeviceDocument = gql`
|
||||
subscription OnNewDevice {
|
||||
onNewDevice {
|
||||
@@ -1036,6 +1164,8 @@ export const OnDeviceConnectedDocument = gql`
|
||||
onConnected {
|
||||
id
|
||||
name
|
||||
service
|
||||
app
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -1066,6 +1196,8 @@ export const OnDeviceDisconnectedDocument = gql`
|
||||
onDisconnected {
|
||||
id
|
||||
name
|
||||
service
|
||||
app
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
@@ -4,8 +4,11 @@ import { useEffect, useState } from "react";
|
||||
import { useNavigate } from "react-router-dom";
|
||||
import { Device } from "../Types/Device";
|
||||
import {
|
||||
useConnectedCastDeviceQuery,
|
||||
useConnectedDeviceQuery,
|
||||
useConnectToCastDeviceMutation,
|
||||
useConnectToDeviceMutation,
|
||||
useDisconnectFromCastDeviceMutation,
|
||||
useDisconnectFromDeviceMutation,
|
||||
useListCastDevicesQuery,
|
||||
useListDevicesQuery,
|
||||
@@ -18,14 +21,19 @@ export const useDevices = () => {
|
||||
const navigate = useNavigate();
|
||||
const [currentDevice, setCurrentDevice] =
|
||||
useState<Device | undefined>(undefined);
|
||||
const [currentCastDevice, setCurrentCastDevice] =
|
||||
useState<Device | undefined>(undefined);
|
||||
const [devices, setDevices] = useState<Device[]>([]);
|
||||
const [castDevices, setCastDevices] = useState<Device[]>([]);
|
||||
const { data } = useOnNewDeviceSubscription();
|
||||
const { data: listDevicesData } = useListDevicesQuery();
|
||||
const { data: listCastDevicesData } = useListCastDevicesQuery();
|
||||
const { data: connectedDeviceData, refetch } = useConnectedDeviceQuery();
|
||||
const { data: connectedCastDeviceData } = useConnectedCastDeviceQuery();
|
||||
const [connectToDevice] = useConnectToDeviceMutation();
|
||||
const [disconnectFromDevice] = useDisconnectFromDeviceMutation();
|
||||
const [connectToCastDevice] = useConnectToCastDeviceMutation();
|
||||
const [disconnectFromCastDevice] = useDisconnectFromCastDeviceMutation();
|
||||
const { data: deviceConnectedData } = useOnDeviceConnectedSubscription();
|
||||
const { data: deviceDisconnectedData } =
|
||||
useOnDeviceDisconnectedSubscription();
|
||||
@@ -86,6 +94,15 @@ export const useDevices = () => {
|
||||
enqueue({
|
||||
message: `Connected to ${deviceConnectedData.onConnected.name}`,
|
||||
});
|
||||
if (deviceConnectedData.onConnected.app === "chromecast") {
|
||||
setCurrentCastDevice({
|
||||
id: deviceConnectedData.onConnected.id,
|
||||
type: deviceConnectedData.onConnected.app,
|
||||
name: deviceConnectedData.onConnected.name,
|
||||
isConnected: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
refetch()
|
||||
.then((result) => {
|
||||
if (result.data?.connectedDevice) {
|
||||
@@ -125,11 +142,24 @@ export const useDevices = () => {
|
||||
});
|
||||
}, [connectedDeviceData]);
|
||||
|
||||
useEffect(() => {
|
||||
connectedCastDeviceData &&
|
||||
setCurrentCastDevice({
|
||||
id: connectedCastDeviceData.connectedCastDevice.id,
|
||||
type: connectedCastDeviceData.connectedCastDevice.app,
|
||||
name: connectedCastDeviceData.connectedCastDevice.name,
|
||||
isConnected: connectedCastDeviceData.connectedCastDevice.isConnected,
|
||||
});
|
||||
}, [connectedCastDeviceData]);
|
||||
|
||||
return {
|
||||
devices,
|
||||
castDevices,
|
||||
currentDevice,
|
||||
currentCastDevice,
|
||||
connectToDevice,
|
||||
disconnectFromDevice,
|
||||
connectToCastDevice,
|
||||
disconnectFromCastDevice,
|
||||
};
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user