Skip to content

Commit

Permalink
New components (connect plex, dark mode) + Started new Welcome screen (
Browse files Browse the repository at this point in the history
…#162)

* add plex button component

* wip

* add dark mode to top bar

* clean up loading on channels page

* updated dark mode button
  • Loading branch information
markdavella authored Mar 8, 2024
1 parent 193203c commit 9819499
Show file tree
Hide file tree
Showing 11 changed files with 172 additions and 92 deletions.
2 changes: 2 additions & 0 deletions web/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import { Outlet, Link as RouterLink } from 'react-router-dom';
import './App.css';
import ServerEvents from './components/ServerEvents.tsx';
import VersionFooter from './components/VersionFooter.tsx';
import DarkModeButton from './components/settings/DarkModeButton.tsx';
import { useVersion } from './hooks/useVersion.ts';
import useStore from './store/index.ts';
import { setDarkModeState } from './store/themeEditor/actions.ts';
Expand Down Expand Up @@ -176,6 +177,7 @@ export function Root() {
</Link>
</Typography>
<Box flexGrow={1}></Box>
<DarkModeButton iconOnly />
<Button
href="//localhost:8000/api/xmltv.xml"
target="_blank"
Expand Down
1 change: 1 addition & 0 deletions web/src/assets/plex.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

This file was deleted.

52 changes: 52 additions & 0 deletions web/src/components/settings/AddPlexServer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import { AddCircle } from '@mui/icons-material';
import { Button } from '@mui/material';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { InsertPlexServerRequest } from '@tunarr/types/api';
import { apiClient } from '../../external/api.ts';
import { checkNewPlexServers, plexLoginFlow } from '../../helpers/plexLogin.ts';

type AddPlexServer = {
title?: string;
};

export default function AddPlexServer(props: AddPlexServer) {
const { title = 'Add', ...restProps } = props;
const queryClient = useQueryClient();

const addPlexServerMutation = useMutation({
mutationFn: (newServer: InsertPlexServerRequest) => {
return apiClient.createPlexServer(newServer);
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: ['settings', 'plex-servers'],
});
},
});

const addPlexServer = () => {
plexLoginFlow()
.then(checkNewPlexServers)
.then((connections) => {
connections.forEach(({ server, connection }) =>
addPlexServerMutation.mutate({
name: server.name,
uri: connection.uri,
accessToken: server.accessToken,
}),
);
})
.catch(console.error);
};

return (
<Button
onClick={() => addPlexServer()}
variant="contained"
startIcon={<AddCircle />}
{...restProps}
>
{title}
</Button>
);
}
33 changes: 33 additions & 0 deletions web/src/components/settings/ConnectPlex.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
import {
Card,
CardActions,
CardContent,
CardProps,
Typography,
} from '@mui/material';
import AddPlexServer from './AddPlexServer.tsx';

export default function ConnectPlex(props: CardProps) {
const {
sx = {
p: 2,
margin: '0 auto',
textAlign: 'center',
},
...restProps
} = props;

return (
<Card sx={sx} {...restProps}>
<CardContent>
<img src="/web/src/assets/plex.svg" width="75" />
<Typography sx={{ my: 2 }}>
First things first, let's get your Plex Server connected.
</Typography>
<CardActions sx={{ justifyContent: 'center' }}>
<AddPlexServer title="Connect Plex" />
</CardActions>
</CardContent>
</Card>
);
}
32 changes: 32 additions & 0 deletions web/src/components/settings/DarkModeButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
import { DarkMode, LightMode } from '@mui/icons-material';
import { FormControlLabel, IconButton, Switch, Tooltip } from '@mui/material';
import useStore from '../../store/index.ts';
import { setDarkModeState } from '../../store/themeEditor/actions';

type DarkModeProps = {
iconOnly?: boolean;
};

export default function DarkModeButton(props: DarkModeProps) {
const { iconOnly } = props;
const darkMode = useStore((state) => state.theme.darkMode);

return (
<>
{iconOnly ? (
<Tooltip title={`Enable ${darkMode ? 'light' : 'dark'} Mode`}>
<IconButton onClick={() => setDarkModeState()} sx={{ mx: 1 }}>
{darkMode ? <LightMode /> : <DarkMode sx={{ color: '#fff' }} />}
</IconButton>
</Tooltip>
) : (
<FormControlLabel
control={
<Switch checked={darkMode} onClick={() => setDarkModeState()} />
}
label="Dark Mode"
/>
)}
</>
);
}
76 changes: 42 additions & 34 deletions web/src/pages/channels/ChannelsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import TextSnippetIcon from '@mui/icons-material/TextSnippet';
import {
Box,
Button,
CircularProgress,
Dialog,
DialogActions,
DialogContent,
Expand Down Expand Up @@ -115,9 +116,9 @@ export default function ChannelsPage() {
sx={{ cursor: 'pointer' }}
hover={true}
>
<TableCell width="10%">{channel.number}</TableCell>
<TableCell>{channel.number}</TableCell>
{!smallViewport && (
<TableCell width="10%">
<TableCell>
<img
style={{ maxHeight: '40px' }}
src={
Expand Down Expand Up @@ -179,13 +180,21 @@ export default function ChannelsPage() {
if (channelsLoading) {
return (
<TableRow key="pending">
<TableCell colSpan={4}>Loading....</TableCell>
<TableCell
colSpan={smallViewport ? 5 : 6}
sx={{ my: 2, textAlign: 'center' }}
>
<CircularProgress />
</TableCell>
</TableRow>
);
} else if (channelsError) {
return (
<TableRow key="pending">
<TableCell colSpan={4}>Error</TableCell>
<TableRow key="error">
<TableCell
colSpan={smallViewport ? 5 : 6}
sx={{ my: 2, textAlign: 'center' }}
>{`Error: ${channelsError.message}`}</TableCell>
</TableRow>
);
} else {
Expand All @@ -200,36 +209,35 @@ export default function ChannelsPage() {
<Typography flexGrow={1} variant="h4">
Channels
</Typography>
{channelsLoading ? 'Loading...' : null}
{channelsError ? 'An error occurred!: ' + channelsError.message : null}
{channels && channels.length ? (
<Button
component={RouterLink}
to="/channels/new"
variant="contained"
startIcon={<AddCircleIcon />}
>
New
</Button>
) : null}
<Button
component={RouterLink}
to="/channels/new"
variant="contained"
startIcon={<AddCircleIcon />}
>
New
</Button>
</Box>
{channels && channels.length > 0 ? (
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Number</TableCell>
{!smallViewport && <TableCell>Icon</TableCell>}
<TableCell>Name</TableCell>
<TableCell>Live?</TableCell>
<TableCell>Stealth?</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>{getTableRows()}</TableBody>
</Table>
</TableContainer>
) : (

<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Number</TableCell>
{!smallViewport && <TableCell>Icon</TableCell>}
<TableCell>Name</TableCell>
<TableCell>Live?</TableCell>
<TableCell>Stealth?</TableCell>
<TableCell></TableCell>
</TableRow>
</TableHead>
<TableBody>
{channels && channels.length > 0 && getTableRows()}
</TableBody>
</Table>
</TableContainer>

{channels && channels.length === 0 && (
<PaddedPaper
sx={{
display: 'flex',
Expand Down
3 changes: 0 additions & 3 deletions web/src/pages/channels/ChannelsTable.tsx

This file was deleted.

14 changes: 3 additions & 11 deletions web/src/pages/settings/GeneralSettingsPage.tsx
Original file line number Diff line number Diff line change
@@ -1,18 +1,10 @@
import { Button, FormControlLabel, Stack, Switch } from '@mui/material';
import useStore from '../../store/index.ts';
import { setDarkModeState } from '../../store/themeEditor/actions.ts';
import { Button, Stack } from '@mui/material';
import DarkModeButton from '../../components/settings/DarkModeButton.tsx';

export default function GeneralSettingsPage() {
const darkMode = useStore((state) => state.theme.darkMode);

return (
<>
<FormControlLabel
control={
<Switch checked={darkMode} onClick={() => setDarkModeState()} />
}
label="Dark Mode"
/>
<DarkModeButton />
<Stack spacing={2} direction="row" justifyContent="right" sx={{ mt: 2 }}>
<Button variant="outlined">Reset Options</Button>
<Button variant="contained">Save</Button>
Expand Down
37 changes: 2 additions & 35 deletions web/src/pages/settings/PlexSettingsPage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -55,12 +55,11 @@ import {
PlexStreamSettings,
defaultPlexStreamSettings,
} from '@tunarr/types';
import { InsertPlexServerRequest } from '@tunarr/types/api';
import { fill, isNil, isNull, isUndefined } from 'lodash-es';
import React, { Fragment, useCallback, useEffect, useState } from 'react';
import { Controller, SubmitHandler, useForm } from 'react-hook-form';
import AddPlexServer from '../../components/settings/AddPlexServer.tsx';
import { apiClient } from '../../external/api.ts';
import { checkNewPlexServers, plexLoginFlow } from '../../helpers/plexLogin.ts';
import {
resolutionFromString,
resolutionToString,
Expand Down Expand Up @@ -307,17 +306,6 @@ export default function PlexSettingsPage() {
setShowSubtitles(!showSubtitles);
};

const addPlexServerMutation = useMutation({
mutationFn: (newServer: InsertPlexServerRequest) => {
return apiClient.createPlexServer(newServer);
},
onSuccess: () => {
return queryClient.invalidateQueries({
queryKey: ['settings', 'plex-servers'],
});
},
});

const updatePlexServerMutation = useMutation({
mutationFn: (updatedServer: PlexServerSettings) => {
return apiClient.updatePlexServer(updatedServer, {
Expand Down Expand Up @@ -479,21 +467,6 @@ export default function PlexSettingsPage() {
return <h1>XML: {(serversError ?? streamsError)!.message}</h1>;
}

const addPlexServer = () => {
plexLoginFlow()
.then(checkNewPlexServers)
.then((connections) => {
connections.forEach(({ server, connection }) =>
addPlexServerMutation.mutate({
name: server.name,
uri: connection.uri,
accessToken: server.accessToken,
}),
);
})
.catch(console.error);
};

const removePlexServer = (id: string) => {
removePlexServerMutation.mutate(id);
setDeletePlexConfirmation(undefined);
Expand Down Expand Up @@ -1062,13 +1035,7 @@ export default function PlexSettingsPage() {
<Typography variant="h6" sx={{ flexGrow: 1 }}>
Plex Servers
</Typography>
<Button
onClick={() => addPlexServer()}
variant="contained"
startIcon={<AddCircle />}
>
Add
</Button>
<AddPlexServer />
</Box>
{renderServersTable()}
</Box>
Expand Down
7 changes: 5 additions & 2 deletions web/src/pages/welcome/WelcomePage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import dayjs from 'dayjs';
import React, { useEffect } from 'react';
import { useNavigate } from 'react-router-dom';
import PaddedPaper from '../../components/base/PaddedPaper.tsx';
import ConnectPlex from '../../components/settings/ConnectPlex.tsx';
import { usePlexServerSettings } from '../../hooks/settingsHooks.ts';
import { useChannels } from '../../hooks/useChannels.ts';
import { useAllTvGuides } from '../../hooks/useTvGuide.ts';
Expand Down Expand Up @@ -233,13 +234,15 @@ export default function WelcomePage() {
}}
>
{header}
{!pathway
{getStarted}
{!isPlexConnected && <ConnectPlex />}
{/* {!pathway
? chooseYourPathway
: pathway === 'get-started'
? getStarted
: pathway === 'migration'
? migration
: null}
: null} */}
</Box>
</PaddedPaper>
</>
Expand Down

0 comments on commit 9819499

Please sign in to comment.