mirror of
https://github.com/LukeHagar/Warden.git
synced 2025-12-06 04:22:06 +00:00
Switching computers
This commit is contained in:
12
package-lock.json
generated
12
package-lock.json
generated
@@ -14150,9 +14150,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/plex-api-oauth": {
|
"node_modules/plex-api-oauth": {
|
||||||
"version": "1.0.134",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/plex-api-oauth/-/plex-api-oauth-1.0.134.tgz",
|
"resolved": "https://registry.npmjs.org/plex-api-oauth/-/plex-api-oauth-1.1.1.tgz",
|
||||||
"integrity": "sha512-P5KA+rp5dHdNi66sRzIKXwiM7X7BAmFXgo5EpgG/jWBtsmHSX2PmkijhtD0iNlZgeUTAj1e+O2a5grudQsGQug==",
|
"integrity": "sha512-2OvSj4YRJo/yJ9TFjKCNxDNalbUQrcoFuiCvtzHaRpw/TxsO1UtaExnqhoXFUuhTBxP3MvonMXs2bieGMbGUjA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"plex-oauth": "^2.0.2",
|
"plex-oauth": "^2.0.2",
|
||||||
@@ -29287,9 +29287,9 @@
|
|||||||
"integrity": "sha512-Igl37++MSa+4H8LNP3Ene9GU0e1YypmXvFVNvVUwoAx44e74jbUlJXy4Q5rLSBisn0O2lBKdE6VkFIwrDl+UnQ=="
|
"integrity": "sha512-Igl37++MSa+4H8LNP3Ene9GU0e1YypmXvFVNvVUwoAx44e74jbUlJXy4Q5rLSBisn0O2lBKdE6VkFIwrDl+UnQ=="
|
||||||
},
|
},
|
||||||
"plex-api-oauth": {
|
"plex-api-oauth": {
|
||||||
"version": "1.0.134",
|
"version": "1.1.1",
|
||||||
"resolved": "https://registry.npmjs.org/plex-api-oauth/-/plex-api-oauth-1.0.134.tgz",
|
"resolved": "https://registry.npmjs.org/plex-api-oauth/-/plex-api-oauth-1.1.1.tgz",
|
||||||
"integrity": "sha512-P5KA+rp5dHdNi66sRzIKXwiM7X7BAmFXgo5EpgG/jWBtsmHSX2PmkijhtD0iNlZgeUTAj1e+O2a5grudQsGQug==",
|
"integrity": "sha512-2OvSj4YRJo/yJ9TFjKCNxDNalbUQrcoFuiCvtzHaRpw/TxsO1UtaExnqhoXFUuhTBxP3MvonMXs2bieGMbGUjA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"axios": "^0.27.2",
|
"axios": "^0.27.2",
|
||||||
"plex-oauth": "^2.0.2",
|
"plex-oauth": "^2.0.2",
|
||||||
|
|||||||
@@ -11,9 +11,13 @@
|
|||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { app, BrowserWindow, shell, ipcMain, dialog } from 'electron';
|
import { app, BrowserWindow, shell, ipcMain, dialog } from 'electron';
|
||||||
import { autoUpdater } from 'electron-updater';
|
import { autoUpdater } from 'electron-updater';
|
||||||
|
import Store from 'electron-store';
|
||||||
import log from 'electron-log';
|
import log from 'electron-log';
|
||||||
import MenuBuilder from './menu';
|
import MenuBuilder from './menu';
|
||||||
import { resolveHtmlPath } from './util';
|
import { resolveHtmlPath } from './util';
|
||||||
|
const fs = require('fs');
|
||||||
|
|
||||||
|
Store.initRenderer();
|
||||||
|
|
||||||
class AppUpdater {
|
class AppUpdater {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|||||||
@@ -24,7 +24,3 @@ contextBridge.exposeInMainWorld('darkMode', {
|
|||||||
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
|
toggle: () => ipcRenderer.invoke('dark-mode:toggle'),
|
||||||
system: () => ipcRenderer.invoke('dark-mode:system'),
|
system: () => ipcRenderer.invoke('dark-mode:system'),
|
||||||
});
|
});
|
||||||
|
|
||||||
contextBridge.exposeInMainWorld('plex', {
|
|
||||||
login: () => ipcRenderer.invoke('plex:login'),
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
/* eslint-disable prefer-template */
|
||||||
import * as React from 'react';
|
import * as React from 'react';
|
||||||
import { useState, useEffect } from 'react';
|
import { useState, useEffect } from 'react';
|
||||||
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
import { createTheme, ThemeProvider } from '@mui/material/styles';
|
||||||
@@ -33,8 +34,10 @@ import {
|
|||||||
Avatar,
|
Avatar,
|
||||||
Button,
|
Button,
|
||||||
Card,
|
Card,
|
||||||
|
CardActionArea,
|
||||||
CardContent,
|
CardContent,
|
||||||
CardHeader,
|
CardHeader,
|
||||||
|
CardMedia,
|
||||||
Grid,
|
Grid,
|
||||||
Icon,
|
Icon,
|
||||||
IconButton,
|
IconButton,
|
||||||
@@ -53,6 +56,8 @@ import ReactJkMusicPlayer from 'react-jinke-music-player';
|
|||||||
import XMLParser from 'react-xml-parser';
|
import XMLParser from 'react-xml-parser';
|
||||||
import ipaddr from 'ipaddr.js';
|
import ipaddr from 'ipaddr.js';
|
||||||
import { PlexAPIOAuth } from 'plex-api-oauth';
|
import { PlexAPIOAuth } from 'plex-api-oauth';
|
||||||
|
import qs from 'qs';
|
||||||
|
import NoArt from './noart.png';
|
||||||
|
|
||||||
const drawerWidth = 240;
|
const drawerWidth = 240;
|
||||||
|
|
||||||
@@ -65,6 +70,7 @@ const iconindex = {
|
|||||||
|
|
||||||
function App() {
|
function App() {
|
||||||
const [activePage, setActivePage] = useState(0);
|
const [activePage, setActivePage] = useState(0);
|
||||||
|
const [activeArtist, setActiveArtist] = useState();
|
||||||
const [plexStateTracker, setPlexStateTracker] = useState(0);
|
const [plexStateTracker, setPlexStateTracker] = useState(0);
|
||||||
|
|
||||||
if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
|
if (window.matchMedia('(prefers-color-scheme)').media !== 'not all') {
|
||||||
@@ -98,228 +104,16 @@ function App() {
|
|||||||
|
|
||||||
if (PlexSession.clientId === '' || PlexSession.clientId == null) {
|
if (PlexSession.clientId === '' || PlexSession.clientId == null) {
|
||||||
PlexSession.GenerateClientId();
|
PlexSession.GenerateClientId();
|
||||||
|
PlexSession.SavePlexSession();
|
||||||
}
|
}
|
||||||
console.log(PlexSession);
|
console.log(PlexSession);
|
||||||
|
|
||||||
PlexSession.SavePlexSession();
|
|
||||||
|
|
||||||
// function plexLogin() {
|
|
||||||
// let plexOauth = new PlexOauth(clientInformation);
|
|
||||||
// // Get hosted UI URL and Pin Id
|
|
||||||
|
|
||||||
// plexOauth
|
|
||||||
// .requestHostedLoginURL()
|
|
||||||
// .then((data) => {
|
|
||||||
// let [hostedUILink, pinId] = data;
|
|
||||||
|
|
||||||
// openInNewTab(hostedUILink);
|
|
||||||
|
|
||||||
// console.log('Plex Auth URL:');
|
|
||||||
// console.log(hostedUILink); // UI URL used to log into Plex
|
|
||||||
// console.log('Plex Pin ID:');
|
|
||||||
// console.log(pinId);
|
|
||||||
// /*
|
|
||||||
// * You can now navigate the user's browser to the 'hostedUILink'. This will include the forward URL
|
|
||||||
// * for your application, so when they have finished signing into Plex, they will be redirected back
|
|
||||||
// * to the specified URL. From there, you just need to perform a query to check for the auth token.
|
|
||||||
// * (See Below)
|
|
||||||
// */
|
|
||||||
|
|
||||||
// // Check for the auth token, once returning to the application
|
|
||||||
|
|
||||||
// plexOauth
|
|
||||||
// .checkForAuthToken(pinId, 1000, 10)
|
|
||||||
// .then((authToken) => {
|
|
||||||
// console.log('Plex Auth Token:');
|
|
||||||
// console.log(authToken); // Returns the auth token if set, otherwise returns null
|
|
||||||
// if (authToken !== null) {
|
|
||||||
// validatePlexAuthToken(authToken);
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // An auth token will only be null if the user never signs into the hosted UI, or you stop checking for a new one before they can log in
|
|
||||||
// })
|
|
||||||
|
|
||||||
// .catch((err) => {
|
|
||||||
// throw err;
|
|
||||||
// });
|
|
||||||
// })
|
|
||||||
// .catch((err) => {
|
|
||||||
// throw err;
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function validatePlexAuthToken(authToken) {
|
|
||||||
// axios({
|
|
||||||
// method: 'GET',
|
|
||||||
// url:
|
|
||||||
// 'https://plex.tv/api/v2/user?' +
|
|
||||||
// require('qs').stringify({
|
|
||||||
// 'X-Plex-Product': clientInformation.product,
|
|
||||||
// 'X-Plex-Client-Identifier': clientId,
|
|
||||||
// 'X-Plex-Token': authToken,
|
|
||||||
// }),
|
|
||||||
// headers: { accept: 'application/json' },
|
|
||||||
// })
|
|
||||||
// .then((response) => {
|
|
||||||
// console.log(response);
|
|
||||||
// console.log(response.status);
|
|
||||||
// if (response.status === 200) {
|
|
||||||
// let tempData = plexData;
|
|
||||||
// tempData.plexUserData = response.data;
|
|
||||||
// tempData.plexAuthToken = authToken;
|
|
||||||
// setPlexData(tempData);
|
|
||||||
// getPlexServers();
|
|
||||||
// getPlexLibraries();
|
|
||||||
// getPlexMusicLibraries();
|
|
||||||
// savePlexState();
|
|
||||||
// }
|
|
||||||
// if (response.status === 401) {
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
// .catch(function (error) {
|
|
||||||
// if (error.response) {
|
|
||||||
// // The request was made and the server responded with a status code
|
|
||||||
// // that falls out of the range of 2xx
|
|
||||||
// console.log(error.response.data);
|
|
||||||
// console.log(error.response.status);
|
|
||||||
// console.log(error.response.headers);
|
|
||||||
// } else if (error.request) {
|
|
||||||
// // The request was made but no response was received
|
|
||||||
// // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
|
||||||
// // http.ClientRequest in node.js
|
|
||||||
// console.log(error.request);
|
|
||||||
// } else {
|
|
||||||
// // Something happened in setting up the request that triggered an Error
|
|
||||||
// console.log('Error', error.message);
|
|
||||||
// }
|
|
||||||
// console.log(error.config);
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function plexLogout() {
|
|
||||||
// localStorage.setItem('plex-database', null);
|
|
||||||
// setPlexData({
|
|
||||||
// plexAuthToken: null,
|
|
||||||
// plexUserData: null,
|
|
||||||
// plexServers: null,
|
|
||||||
// plexLibraries: null,
|
|
||||||
// plexMusicLibraries: null,
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function testPlexServer(ipAddress, accessToken) {
|
|
||||||
// obj?.connections
|
|
||||||
// ?.filter((ipEntry) => ipEntry?.local === true)
|
|
||||||
// ?.map((localIP) => {
|
|
||||||
// console.log(localIP);
|
|
||||||
// axios({
|
|
||||||
// method: 'GET',
|
|
||||||
// timeout: 100,
|
|
||||||
// url:
|
|
||||||
// 'http://' +
|
|
||||||
// localIP.address +
|
|
||||||
// ':32400?' +
|
|
||||||
// require('qs').stringify({
|
|
||||||
// 'X-Plex-Token': obj?.accessToken,
|
|
||||||
// }),
|
|
||||||
// })
|
|
||||||
// .catch(function (error) {
|
|
||||||
// if (error.response) {
|
|
||||||
// // The request was made and the server responded with a status code
|
|
||||||
// // that falls out of the range of 2xx
|
|
||||||
// console.log(error.response.data);
|
|
||||||
// console.log(error.response.status);
|
|
||||||
// console.log(error.response.headers);
|
|
||||||
// } else if (error.request) {
|
|
||||||
// // The request was made but no response was received
|
|
||||||
// // `error.request` is an instance of XMLHttpRequest in the browser and an instance of
|
|
||||||
// // http.ClientRequest in node.js
|
|
||||||
// console.log(error.request);
|
|
||||||
// } else {
|
|
||||||
// // Something happened in setting up the request that triggered an Error
|
|
||||||
// console.log('Error', error.message);
|
|
||||||
// }
|
|
||||||
// console.log(error.config);
|
|
||||||
// })
|
|
||||||
// .then((response) => {
|
|
||||||
// console.log();
|
|
||||||
// if (response?.status === 200) {
|
|
||||||
// localArray = [...localArray, localIP];
|
|
||||||
// } else {
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// });
|
|
||||||
// });
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function savePlexState() {
|
|
||||||
// if (plexData === null) {
|
|
||||||
// plexLogin();
|
|
||||||
// } else {
|
|
||||||
// localStorage.setItem('plex-database', plexData);
|
|
||||||
// console.log('Plex Database:');
|
|
||||||
// console.log(localStorage.getItem('plex-database'));
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// function getPlexMusicLibraries() {
|
|
||||||
// setPlexMusicLibraries(
|
|
||||||
// plexLibraries?.filter((obj) => obj?.type === 'artist')
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (plexData.authToken !== null) {
|
|
||||||
// console.log(plexData.authToken);
|
|
||||||
// validatePlexAuthToken(plexData.authToken);
|
|
||||||
// } else {
|
|
||||||
// plexLogout();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if (!authToken) {
|
|
||||||
// plexLogin();
|
|
||||||
// }
|
|
||||||
// if (!plexUserData) {
|
|
||||||
// validatePlexAuthToken();
|
|
||||||
// }
|
|
||||||
// if (!plexServers) {
|
|
||||||
// getPlexServers();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// console.log('Main Body');
|
|
||||||
|
|
||||||
// console.log('clientId:');
|
|
||||||
// console.log(clientId);
|
|
||||||
|
|
||||||
// console.log('Plex Auth Token:');
|
|
||||||
// console.log(plexAuthToken);
|
|
||||||
|
|
||||||
// console.log('Plex User Data:');
|
|
||||||
// console.log(plexUserData);
|
|
||||||
|
|
||||||
// console.log('Plex Servers:');
|
|
||||||
// console.log(plexServers);
|
|
||||||
|
|
||||||
// console.log('Plex Libraries:');
|
|
||||||
// console.log(plexLibraries);
|
|
||||||
|
|
||||||
// console.log('Plex Music Libraries:');
|
|
||||||
// console.log(plexMusicLibraries);
|
|
||||||
|
|
||||||
// console.log('Plex DataBase');
|
|
||||||
// console.log(plexData);
|
|
||||||
|
|
||||||
// console.log(PlexSession);
|
|
||||||
|
|
||||||
// useEffect(() => PlexSession.PlexLogin(), []);
|
|
||||||
|
|
||||||
// // PlexSession.GetPlexUserData();
|
|
||||||
|
|
||||||
async function PlexLoginButton() {
|
async function PlexLoginButton() {
|
||||||
await PlexSession.PlexLogin();
|
await PlexSession.PlexLogin();
|
||||||
await PlexSession.GetPlexUserData();
|
await PlexSession.GetPlexUserData();
|
||||||
await PlexSession.GetPlexServers();
|
await PlexSession.GetPlexServers();
|
||||||
await PlexSession.GetPlexLibraries();
|
await PlexSession.GetPlexLibraries();
|
||||||
|
await PlexSession.GetPlexMusicLibraryContent();
|
||||||
await PlexSession.SavePlexSession();
|
await PlexSession.SavePlexSession();
|
||||||
|
|
||||||
setPlexStateTracker(plexStateTracker + 1);
|
setPlexStateTracker(plexStateTracker + 1);
|
||||||
@@ -327,9 +121,7 @@ function App() {
|
|||||||
|
|
||||||
async function PlexLogoutButton() {
|
async function PlexLogoutButton() {
|
||||||
await PlexSession.PlexLogout();
|
await PlexSession.PlexLogout();
|
||||||
|
|
||||||
await PlexSession.SavePlexSession();
|
await PlexSession.SavePlexSession();
|
||||||
|
|
||||||
setPlexStateTracker(plexStateTracker + 1);
|
setPlexStateTracker(plexStateTracker + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -391,17 +183,30 @@ function App() {
|
|||||||
<ListItemText primary="Libraries" />
|
<ListItemText primary="Libraries" />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
{PlexSession?.plexMusic?.map((obj) => (
|
<Divider />
|
||||||
<ListItem key={obj.uuid} disablePadding>
|
<ListItem key="Libraries" disablePadding>
|
||||||
<ListItemButton>
|
<ListItemButton onClick={() => setActivePage(2)}>
|
||||||
<ListItemIcon>{iconindex.Library}</ListItemIcon>
|
<ListItemIcon>{iconindex.Library}</ListItemIcon>
|
||||||
<ListItemText primary={obj.title} />
|
<ListItemText primary="Artists" />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
</ListItem>
|
</ListItem>
|
||||||
))}
|
<Divider />
|
||||||
|
<ListItem key="Libraries" disablePadding>
|
||||||
|
<ListItemButton onClick={() => setActivePage(3)}>
|
||||||
|
<ListItemIcon>{iconindex.Library}</ListItemIcon>
|
||||||
|
<ListItemText primary="Albums" />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
|
<Divider />
|
||||||
|
<ListItem key="Libraries" disablePadding>
|
||||||
|
<ListItemButton onClick={() => setActivePage(4)}>
|
||||||
|
<ListItemIcon>{iconindex.Library}</ListItemIcon>
|
||||||
|
<ListItemText primary="Songs" />
|
||||||
|
</ListItemButton>
|
||||||
|
</ListItem>
|
||||||
<Divider />
|
<Divider />
|
||||||
<ListItem key="Playlists" disablePadding>
|
<ListItem key="Playlists" disablePadding>
|
||||||
<ListItemButton onClick={() => setActivePage(2)}>
|
<ListItemButton onClick={() => setActivePage(5)}>
|
||||||
<ListItemIcon>{iconindex.Playlists}</ListItemIcon>
|
<ListItemIcon>{iconindex.Playlists}</ListItemIcon>
|
||||||
<ListItemText primary="Playlists" />
|
<ListItemText primary="Playlists" />
|
||||||
</ListItemButton>
|
</ListItemButton>
|
||||||
@@ -420,6 +225,11 @@ function App() {
|
|||||||
component="main"
|
component="main"
|
||||||
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
||||||
label="Home"
|
label="Home"
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 200,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
<Typography paragraph>
|
<Typography paragraph>
|
||||||
@@ -433,15 +243,185 @@ function App() {
|
|||||||
label="Library"
|
label="Library"
|
||||||
>
|
>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
<Typography paragraph>
|
<Accordion
|
||||||
This will be the Library page of my App
|
TransitionProps={{
|
||||||
</Typography>
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 400,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AccordionSummary>
|
||||||
|
<Typography variant="h3">Artists</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<Box sx={{}}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{PlexSession?.plexArtistLibraries?.map((Obj) => (
|
||||||
|
<Grid item xs={3} key={Obj.guid}>
|
||||||
|
<Card>
|
||||||
|
<CardActionArea
|
||||||
|
onClick={() => {
|
||||||
|
setActivePage(4);
|
||||||
|
setActiveArtist(Obj);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
height="240"
|
||||||
|
image={
|
||||||
|
Obj.server.relayConnections[0].uri +
|
||||||
|
'/photo/:/transcode?' +
|
||||||
|
qs.stringify({
|
||||||
|
width: 240,
|
||||||
|
height: 240,
|
||||||
|
minSize: 1,
|
||||||
|
upscale: 1,
|
||||||
|
url:
|
||||||
|
Obj.thumb +
|
||||||
|
'?X-Plex-Token=' +
|
||||||
|
Obj.server.accessToken,
|
||||||
|
'X-Plex-Token': Obj.server.accessToken,
|
||||||
|
}) || NoArt
|
||||||
|
}
|
||||||
|
onError={({ currentTarget }) => {
|
||||||
|
currentTarget.onerror = null; // prevents looping
|
||||||
|
currentTarget.src = NoArt;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CardContent>
|
||||||
|
<Typography>{Obj.title}</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</CardActionArea>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
<Accordion
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 200,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AccordionSummary>
|
||||||
|
<Typography variant="h3">Albums</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<Box sx={{}}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{PlexSession?.plexArtistLibraries?.map((Obj) => (
|
||||||
|
<Grid item xs={3} key={Obj.guid}>
|
||||||
|
<Card>
|
||||||
|
<CardActionArea
|
||||||
|
onClick={() => {
|
||||||
|
setActivePage(4);
|
||||||
|
setActiveArtist(Obj);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
height="240"
|
||||||
|
image={
|
||||||
|
Obj.server.relayConnections[0].uri +
|
||||||
|
'/photo/:/transcode?' +
|
||||||
|
qs.stringify({
|
||||||
|
width: 240,
|
||||||
|
height: 240,
|
||||||
|
minSize: 1,
|
||||||
|
upscale: 1,
|
||||||
|
url:
|
||||||
|
Obj.thumb +
|
||||||
|
'?X-Plex-Token=' +
|
||||||
|
Obj.server.accessToken,
|
||||||
|
'X-Plex-Token': Obj.server.accessToken,
|
||||||
|
}) || NoArt
|
||||||
|
}
|
||||||
|
onError={({ currentTarget }) => {
|
||||||
|
currentTarget.onerror = null; // prevents looping
|
||||||
|
currentTarget.src = NoArt;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CardContent>
|
||||||
|
<Typography>{Obj.title}</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</CardActionArea>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
|
<Accordion
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 200,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<AccordionSummary>
|
||||||
|
<Typography variant="h3">Songs</Typography>
|
||||||
|
</AccordionSummary>
|
||||||
|
<AccordionDetails>
|
||||||
|
<Box sx={{}}>
|
||||||
|
<Grid container spacing={2}>
|
||||||
|
{PlexSession?.plexSongLibraries?.map((Obj) => (
|
||||||
|
<Grid item xs={3} key={Obj.guid}>
|
||||||
|
<Card>
|
||||||
|
<CardActionArea
|
||||||
|
onClick={() => {
|
||||||
|
setActivePage(4);
|
||||||
|
setActiveArtist(Obj);
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<CardMedia
|
||||||
|
component="img"
|
||||||
|
height="240"
|
||||||
|
image={
|
||||||
|
Obj.server.relayConnections[0].uri +
|
||||||
|
'/photo/:/transcode?' +
|
||||||
|
qs.stringify({
|
||||||
|
width: 240,
|
||||||
|
height: 240,
|
||||||
|
minSize: 1,
|
||||||
|
upscale: 1,
|
||||||
|
url:
|
||||||
|
Obj.thumb +
|
||||||
|
'?X-Plex-Token=' +
|
||||||
|
Obj.server.accessToken,
|
||||||
|
'X-Plex-Token': Obj.server.accessToken,
|
||||||
|
}) || NoArt
|
||||||
|
}
|
||||||
|
onError={({ currentTarget }) => {
|
||||||
|
currentTarget.onerror = null; // prevents looping
|
||||||
|
currentTarget.src = NoArt;
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<CardContent>
|
||||||
|
<Typography>{Obj.title}</Typography>
|
||||||
|
</CardContent>
|
||||||
|
</CardActionArea>
|
||||||
|
</Card>
|
||||||
|
</Grid>
|
||||||
|
))}
|
||||||
|
</Grid>
|
||||||
|
</Box>
|
||||||
|
</AccordionDetails>
|
||||||
|
</Accordion>
|
||||||
</Box>
|
</Box>
|
||||||
<Box
|
<Box
|
||||||
hidden={isHidden(2)}
|
hidden={isHidden(2)}
|
||||||
component="main"
|
component="main"
|
||||||
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
||||||
label="Playlists"
|
label="Playlists"
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 100,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
<Typography paragraph>
|
<Typography paragraph>
|
||||||
@@ -453,6 +433,11 @@ function App() {
|
|||||||
component="main"
|
component="main"
|
||||||
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
||||||
label="Settings"
|
label="Settings"
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 100,
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
<Toolbar />
|
<Toolbar />
|
||||||
|
|
||||||
@@ -521,7 +506,13 @@ function App() {
|
|||||||
}
|
}
|
||||||
/>
|
/>
|
||||||
<CardContent>
|
<CardContent>
|
||||||
<Accordion variant="dense">
|
<Accordion
|
||||||
|
variant="dense"
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
}}
|
||||||
|
>
|
||||||
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
<AccordionSummary expandIcon={<ExpandMoreIcon />}>
|
||||||
<Typography
|
<Typography
|
||||||
sx={{ flexGrow: 1 }}
|
sx={{ flexGrow: 1 }}
|
||||||
@@ -711,6 +702,37 @@ function App() {
|
|||||||
</Grid>
|
</Grid>
|
||||||
</Grid>
|
</Grid>
|
||||||
</Box>
|
</Box>
|
||||||
|
<Box
|
||||||
|
hidden={isHidden(4)}
|
||||||
|
component="main"
|
||||||
|
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
||||||
|
label="Playlists"
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 100,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Toolbar />
|
||||||
|
<Typography>{activeArtist?.title}</Typography>
|
||||||
|
<List></List>
|
||||||
|
</Box>
|
||||||
|
<Box
|
||||||
|
hidden={isHidden(5)}
|
||||||
|
component="main"
|
||||||
|
sx={{ flexGrow: 1, bgcolor: 'background.default', p: 3 }}
|
||||||
|
label="Playlists"
|
||||||
|
TransitionProps={{
|
||||||
|
unmountOnExit: true,
|
||||||
|
mountOnEnter: true,
|
||||||
|
timeout: 100,
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<Toolbar />
|
||||||
|
<Typography paragraph>
|
||||||
|
This will be the Album page of my App
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
</Box>
|
</Box>
|
||||||
</ThemeProvider>
|
</ThemeProvider>
|
||||||
);
|
);
|
||||||
|
|||||||
BIN
src/renderer/noart.png
Normal file
BIN
src/renderer/noart.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 1004 B |
@@ -7767,9 +7767,9 @@
|
|||||||
"version" "1.1.0"
|
"version" "1.1.0"
|
||||||
|
|
||||||
"plex-api-oauth@^1.0.4":
|
"plex-api-oauth@^1.0.4":
|
||||||
"integrity" "sha512-P5KA+rp5dHdNi66sRzIKXwiM7X7BAmFXgo5EpgG/jWBtsmHSX2PmkijhtD0iNlZgeUTAj1e+O2a5grudQsGQug=="
|
"integrity" "sha512-2OvSj4YRJo/yJ9TFjKCNxDNalbUQrcoFuiCvtzHaRpw/TxsO1UtaExnqhoXFUuhTBxP3MvonMXs2bieGMbGUjA=="
|
||||||
"resolved" "https://registry.npmjs.org/plex-api-oauth/-/plex-api-oauth-1.0.134.tgz"
|
"resolved" "https://registry.npmjs.org/plex-api-oauth/-/plex-api-oauth-1.1.1.tgz"
|
||||||
"version" "1.0.134"
|
"version" "1.1.1"
|
||||||
dependencies:
|
dependencies:
|
||||||
"axios" "^0.27.2"
|
"axios" "^0.27.2"
|
||||||
"plex-oauth" "^2.0.2"
|
"plex-oauth" "^2.0.2"
|
||||||
|
|||||||
Reference in New Issue
Block a user