diff --git a/web/.eslintrc b/web/.eslintrc
index 929c132..02f9504 100644
--- a/web/.eslintrc
+++ b/web/.eslintrc
@@ -36,6 +36,7 @@
"react/prop-types": 0,
"react/react-in-jsx-scope": 0,
"react/jsx-uses-react": 0,
- "import/no-unresolved": 0 // used to allow relative paths from "src" folder
+ "import/no-unresolved": 0, // used to allow relative paths from "src" folder
+ "react/jsx-props-no-spreading": 0
}
}
\ No newline at end of file
diff --git a/web/package.json b/web/package.json
index 261134a..7984c45 100644
--- a/web/package.json
+++ b/web/package.json
@@ -5,11 +5,19 @@
"dependencies": {
"@material-ui/core": "^4.11.4",
"@material-ui/icons": "^4.11.2",
+ "axios": "^0.21.1",
"clsx": "^1.1.1",
"fontsource-roboto": "^4.0.0",
+ "konva": "^8.0.1",
+ "lodash": "^4.17.21",
"material-ui-image": "^3.3.2",
+ "parse-torrent-title": "^1.3.0",
"react": "^17.0.2",
+ "react-copy-to-clipboard": "^5.0.3",
+ "react-div-100vh": "^0.6.0",
"react-dom": "^17.0.2",
+ "react-konva": "^17.0.2-4",
+ "react-measure": "^2.5.2",
"react-scripts": "4.0.3",
"styled-components": "^5.3.0"
},
diff --git a/web/public/index.html b/web/public/index.html
index 569cd1a..1fe47d0 100644
--- a/web/public/index.html
+++ b/web/public/index.html
@@ -10,44 +10,6 @@
TorrServer
-
diff --git a/web/src/App.jsx b/web/src/App.jsx
deleted file mode 100644
index 7286c36..0000000
--- a/web/src/App.jsx
+++ /dev/null
@@ -1,34 +0,0 @@
-import CssBaseline from '@material-ui/core/CssBaseline'
-import { createMuiTheme, MuiThemeProvider } from '@material-ui/core'
-
-import Appbar from './components/Appbar/index'
-
-const baseTheme = createMuiTheme({
- overrides: {
- MuiCssBaseline: {
- '@global': {
- html: {
- WebkitFontSmoothing: 'auto',
- },
- },
- },
- },
- palette: {
- primary: {
- main: '#3fb57a',
- },
- secondary: {
- main: '#FFA724',
- },
- tonalOffset: 0.2,
- },
-})
-
-export default function App() {
- return (
-
-
-
-
- )
-}
diff --git a/web/src/App/Sidebar.jsx b/web/src/App/Sidebar.jsx
new file mode 100644
index 0000000..5d6edac
--- /dev/null
+++ b/web/src/App/Sidebar.jsx
@@ -0,0 +1,60 @@
+import { playlistAllHost, shutdownHost } from 'utils/Hosts'
+import Divider from '@material-ui/core/Divider'
+import ListItem from '@material-ui/core/ListItem'
+import ListItemIcon from '@material-ui/core/ListItemIcon'
+import ListItemText from '@material-ui/core/ListItemText'
+import AddDialogButton from 'components/Add'
+import RemoveAll from 'components/RemoveAll'
+import SettingsDialog from 'components/Settings'
+import AboutDialog from 'components/About'
+import UploadDialog from 'components/Upload'
+import {
+ CreditCard as CreditCardIcon,
+ List as ListIcon,
+ PowerSettingsNew as PowerSettingsNewIcon,
+} from '@material-ui/icons'
+import List from '@material-ui/core/List'
+
+import { AppSidebarStyle } from './style'
+
+export default function Sidebar({ isDrawerOpen, setIsDonationDialogOpen }) {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ fetch(shutdownHost())}>
+
+
+
+
+
+
+
+
+
+
+ setIsDonationDialogOpen(true)}>
+
+
+
+
+
+
+
+ )
+}
diff --git a/web/src/App/index.jsx b/web/src/App/index.jsx
new file mode 100644
index 0000000..ce7164a
--- /dev/null
+++ b/web/src/App/index.jsx
@@ -0,0 +1,63 @@
+import CssBaseline from '@material-ui/core/CssBaseline'
+import { createMuiTheme, MuiThemeProvider } from '@material-ui/core'
+import { useEffect, useState } from 'react'
+import Typography from '@material-ui/core/Typography'
+import IconButton from '@material-ui/core/IconButton'
+import { Menu as MenuIcon, Close as CloseIcon } from '@material-ui/icons'
+import { echoHost } from 'utils/Hosts'
+import TorrentList from 'components/TorrentList'
+import DonateSnackbar from 'components/Donate'
+import DonateDialog from 'components/Donate/DonateDialog'
+import Div100vh from 'react-div-100vh'
+import axios from 'axios'
+
+import { AppWrapper, AppHeader } from './style'
+import Sidebar from './Sidebar'
+
+const baseTheme = createMuiTheme({
+ overrides: { MuiCssBaseline: { '@global': { html: { WebkitFontSmoothing: 'auto' } } } },
+ palette: { primary: { main: '#3fb57a' }, secondary: { main: '#FFA724' }, tonalOffset: 0.2 },
+})
+
+export default function App() {
+ const [isDrawerOpen, setIsDrawerOpen] = useState(false)
+ const [isDonationDialogOpen, setIsDonationDialogOpen] = useState(false)
+ const [torrServerVersion, setTorrServerVersion] = useState('')
+
+ useEffect(() => {
+ axios.get(echoHost()).then(({ data }) => setTorrServerVersion(data))
+ }, [])
+
+ return (
+
+
+
+ {/* Div100vh - iOS WebKit fix */}
+
+
+
+ setIsDrawerOpen(!isDrawerOpen)}
+ edge='start'
+ >
+ {isDrawerOpen ? : }
+
+
+
+ TorrServer {torrServerVersion}
+
+
+
+
+
+
+
+ {isDonationDialogOpen && setIsDonationDialogOpen(false)} />}
+ {!JSON.parse(localStorage.getItem('snackbarIsClosed')) && }
+
+
+
+ )
+}
diff --git a/web/src/App/style.js b/web/src/App/style.js
new file mode 100644
index 0000000..bebad80
--- /dev/null
+++ b/web/src/App/style.js
@@ -0,0 +1,64 @@
+import styled, { css } from 'styled-components'
+
+export const AppWrapper = styled.div`
+ height: 100%;
+ display: grid;
+ grid-template-columns: 60px 1fr;
+ grid-template-rows: 60px 1fr;
+ grid-template-areas:
+ 'head head'
+ 'side content';
+`
+
+export const CenteredGrid = styled.div`
+ height: 100%;
+ display: grid;
+ place-items: center;
+`
+
+export const AppHeader = styled.div`
+ background: #3fb57a;
+ color: rgba(0, 0, 0, 0.87);
+ grid-area: head;
+ display: flex;
+ align-items: center;
+ box-shadow: 0px 2px 4px -1px rgb(0 0 0 / 20%), 0px 4px 5px 0px rgb(0 0 0 / 14%), 0px 1px 10px 0px rgb(0 0 0 / 12%);
+ padding: 0 24px;
+ z-index: 3;
+`
+export const AppSidebarStyle = styled.div`
+ ${({ isDrawerOpen }) => css`
+ grid-area: side;
+ width: ${isDrawerOpen ? '400%' : '100%'};
+ z-index: 2;
+ overflow-x: hidden;
+ transition: width 195ms cubic-bezier(0.4, 0, 0.6, 1) 0ms;
+ border-right: 1px solid rgba(0, 0, 0, 0.12);
+ background: #fff;
+ white-space: nowrap;
+ `}
+`
+export const TorrentListWrapper = styled.div`
+ grid-area: content;
+ padding: 20px;
+ overflow: auto;
+
+ display: grid;
+ place-content: start;
+ grid-template-columns: repeat(auto-fit, minmax(max-content, 570px));
+ gap: 20px;
+
+ @media (max-width: 1260px), (max-height: 500px) {
+ padding: 10px;
+ gap: 15px;
+ grid-template-columns: repeat(3, 1fr);
+ }
+
+ @media (max-width: 1100px) {
+ grid-template-columns: repeat(2, 1fr);
+ }
+
+ @media (max-width: 700px) {
+ grid-template-columns: 1fr;
+ }
+`
diff --git a/web/src/components/About.jsx b/web/src/components/About.jsx
index bbcd699..a241eee 100644
--- a/web/src/components/About.jsx
+++ b/web/src/components/About.jsx
@@ -3,7 +3,6 @@ import Button from '@material-ui/core/Button'
import Dialog from '@material-ui/core/Dialog'
import DialogActions from '@material-ui/core/DialogActions'
import DialogContent from '@material-ui/core/DialogContent'
-import DialogContentText from '@material-ui/core/DialogContentText'
import DialogTitle from '@material-ui/core/DialogTitle'
import InfoIcon from '@material-ui/icons/Info'
import ListItem from '@material-ui/core/ListItem'
@@ -27,23 +26,21 @@ export default function AboutDialog() {
-
-
- Thanks to everyone who tested and helped.
-
-
- Special thanks:
- Anacrolix Matt Joiner github.com/anacrolix
-
- tsynik nikk Никита github.com/tsynik
-
- dancheskus github.com/dancheskus
-
- Tw1cker Руслан Пахнев github.com/Nemiroff
-
- SpAwN_LMG
-
-
+
+ Thanks to everyone who tested and helped.
+
+
+ Special thanks:
+ Anacrolix Matt Joiner github.com/anacrolix
+
+ tsynik nikk Никита github.com/tsynik
+
+ dancheskus github.com/dancheskus
+
+ Tw1cker Руслан Пахнев github.com/Nemiroff
+
+ SpAwN_LMG
+
diff --git a/web/src/components/Add/AddDialog.jsx b/web/src/components/Add/AddDialog.jsx
index dbbbe72..4c7225f 100644
--- a/web/src/components/Add/AddDialog.jsx
+++ b/web/src/components/Add/AddDialog.jsx
@@ -63,7 +63,7 @@ export default function AddDialog({ handleClose }) {
Cancel
-