diff --git a/web/public/index.html b/web/public/index.html index 403c8f8..df1c16c 100644 --- a/web/public/index.html +++ b/web/public/index.html @@ -4,10 +4,11 @@ + - + TorrServer MatriX diff --git a/web/src/components/About/index.jsx b/web/src/components/About/index.jsx index 180cad2..b025ae5 100644 --- a/web/src/components/About/index.jsx +++ b/web/src/components/About/index.jsx @@ -3,12 +3,13 @@ import { useEffect, useState } from 'react' import Button from '@material-ui/core/Button' import Dialog from '@material-ui/core/Dialog' import InfoIcon from '@material-ui/icons/Info' -import ListItem from '@material-ui/core/ListItem' import ListItemIcon from '@material-ui/core/ListItemIcon' import ListItemText from '@material-ui/core/ListItemText' import { useTranslation } from 'react-i18next' import { useMediaQuery } from '@material-ui/core' import { echoHost } from 'utils/Hosts' +import StyledMenuButtonWrapper from 'style/StyledMenuButtonWrapper' +import { isStandaloneApp } from 'utils/Utils' import LinkComponent from './LinkComponent' import { DialogWrapper, HeaderSection, ThanksSection, Section, FooterSection } from './style' @@ -24,12 +25,22 @@ export default function AboutDialog() { return ( <> - setOpen(true)}> - - - - - + setOpen(true)}> + {isStandaloneApp ? ( + <> + +
{t('About')}
+ + ) : ( + <> + + + + + + + )} +
- - - - - - + + {isStandaloneApp ? ( + <> + +
{t('AddFromLink')}
+ + ) : ( + <> + + + + + + + )} +
{isDialogOpen && } diff --git a/web/src/components/App/PWAFooter/index.jsx b/web/src/components/App/PWAFooter/index.jsx new file mode 100644 index 0000000..834e802 --- /dev/null +++ b/web/src/components/App/PWAFooter/index.jsx @@ -0,0 +1,31 @@ +import { CreditCard as CreditCardIcon } from '@material-ui/icons' +import { useTranslation } from 'react-i18next' +import CloseServer from 'components/CloseServer' +import StyledMenuButtonWrapper from 'style/StyledMenuButtonWrapper' +import AddDialogButton from 'components/Add' +import AboutDialog from 'components/About' +import SettingsDialogButton from 'components/Settings' + +import StyledPWAFooter from './style' + +export default function PWAFooter({ setIsDonationDialogOpen, isOffline, isLoading }) { + const { t } = useTranslation() + + return ( + + + + setIsDonationDialogOpen(true)}> + + +
{t('Donate')}
+
+ + + + + + +
+ ) +} diff --git a/web/src/components/App/PWAFooter/style.js b/web/src/components/App/PWAFooter/style.js new file mode 100644 index 0000000..79d8f7c --- /dev/null +++ b/web/src/components/App/PWAFooter/style.js @@ -0,0 +1,18 @@ +import styled from 'styled-components' + +export default styled.div` + background: #575757; + color: #fff; + position: fixed; + bottom: 0; + width: 100%; + height: 90px; + + display: none; + + @media screen and (display-mode: standalone) { + display: grid; + grid-template-columns: repeat(5, 1fr); + justify-items: center; + } +` diff --git a/web/src/components/App/index.jsx b/web/src/components/App/index.jsx index cbee0c9..9e913dc 100644 --- a/web/src/components/App/index.jsx +++ b/web/src/components/App/index.jsx @@ -1,7 +1,6 @@ import CssBaseline from '@material-ui/core/CssBaseline' import { createContext, 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, @@ -21,11 +20,12 @@ import { ThemeProvider as StyledComponentsThemeProvider } from 'styled-component import { useQuery } from 'react-query' import { getTorrents } from 'utils/Utils' import GlobalStyle from 'style/GlobalStyle' +import { lightTheme, THEME_MODES, useMaterialUITheme } from 'style/materialUISetup' +import getStyledComponentsTheme from 'style/getStyledComponentsTheme' -import { AppWrapper, AppHeader, HeaderToggle } from './style' +import { AppWrapper, AppHeader, HeaderToggle, StyledIconButton } from './style' import Sidebar from './Sidebar' -import { lightTheme, THEME_MODES, useMaterialUITheme } from '../../style/materialUISetup' -import getStyledComponentsTheme from '../../style/getStyledComponentsTheme' +import PWAFooter from './PWAFooter' export const DarkModeContext = createContext() @@ -63,14 +63,9 @@ export default function App() { - setIsDrawerOpen(!isDrawerOpen)} - style={{ marginRight: '6px' }} - > + setIsDrawerOpen(!isDrawerOpen)}> {isDrawerOpen ? : } - + TorrServer {torrServerVersion} @@ -118,6 +113,12 @@ export default function App() { + + {isDonationDialogOpen && setIsDonationDialogOpen(false)} />} diff --git a/web/src/components/App/style.js b/web/src/components/App/style.js index 7deba4e..b5b7574 100644 --- a/web/src/components/App/style.js +++ b/web/src/components/App/style.js @@ -1,3 +1,4 @@ +import { IconButton } from '@material-ui/core' import { rgba } from 'polished' import styled, { css } from 'styled-components' @@ -15,6 +16,12 @@ export const AppWrapper = styled.div` grid-template-areas: 'head head' 'side content'; + + @media screen and (display-mode: standalone) { + grid-template-columns: 0 1fr; + grid-template-rows: 90px 1fr 90px; + height: 100vh; + } `} ` @@ -36,6 +43,15 @@ export const AppHeader = styled.div` 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 16px; z-index: 3; + + @media screen and (display-mode: standalone) { + grid-template-columns: max-content 1fr; + align-items: end; + padding: 7px 16px; + position: fixed; + width: 100%; + height: 90px; + } `} ` export const AppSidebarStyle = styled.div` @@ -58,6 +74,10 @@ export const AppSidebarStyle = styled.div` svg { fill: ${sidebarFillColor}; } + + @media screen and (display-mode: standalone) { + display: none; + } `} ` export const TorrentListWrapper = styled.div` @@ -83,6 +103,11 @@ export const TorrentListWrapper = styled.div` @media (max-width: 700px) { grid-template-columns: 1fr; } + + @media screen and (display-mode: standalone) { + height: calc(100vh - 90px); + padding-bottom: 105px; + } ` export const HeaderToggle = styled.div` @@ -117,3 +142,11 @@ export const HeaderToggle = styled.div` } `} ` + +export const StyledIconButton = styled(IconButton)` + margin-right: 6px; + + @media screen and (display-mode: standalone) { + display: none; + } +` diff --git a/web/src/components/CloseServer.jsx b/web/src/components/CloseServer.jsx index a347eeb..950b888 100644 --- a/web/src/components/CloseServer.jsx +++ b/web/src/components/CloseServer.jsx @@ -1,8 +1,10 @@ import { useState } from 'react' -import { Button, Dialog, DialogActions, DialogTitle, ListItem, ListItemIcon, ListItemText } from '@material-ui/core' +import { Button, Dialog, DialogActions, DialogTitle, ListItemIcon, ListItemText } from '@material-ui/core' import { PowerSettingsNew as PowerSettingsNewIcon } from '@material-ui/icons' import { shutdownHost } from 'utils/Hosts' import { useTranslation } from 'react-i18next' +import { isStandaloneApp } from 'utils/Utils' +import StyledMenuButtonWrapper from 'style/StyledMenuButtonWrapper' export default function CloseServer({ isOffline, isLoading }) { const { t } = useTranslation() @@ -12,13 +14,22 @@ export default function CloseServer({ isOffline, isLoading }) { return ( <> - - - - + + {isStandaloneApp ? ( + <> + +
{t('CloseServer')}
+ + ) : ( + <> + + + - -
+ + + )} + {t('CloseServer?')} diff --git a/web/src/components/Settings/index.jsx b/web/src/components/Settings/index.jsx index 5073946..7014e98 100644 --- a/web/src/components/Settings/index.jsx +++ b/web/src/components/Settings/index.jsx @@ -1,9 +1,10 @@ -import ListItem from '@material-ui/core/ListItem' import ListItemIcon from '@material-ui/core/ListItemIcon' import ListItemText from '@material-ui/core/ListItemText' import { useState } from 'react' import SettingsIcon from '@material-ui/icons/Settings' import { useTranslation } from 'react-i18next' +import StyledMenuButtonWrapper from 'style/StyledMenuButtonWrapper' +import { isStandaloneApp } from 'utils/Utils' import SettingsDialog from './SettingsDialog' @@ -16,12 +17,22 @@ export default function SettingsDialogButton({ isOffline, isLoading }) { return (
- - - - - - + + {isStandaloneApp ? ( + <> + +
{t('SettingsDialog.Settings')}
+ + ) : ( + <> + + + + + + + )} +
{isDialogOpen && }
diff --git a/web/src/style/GlobalStyle.js b/web/src/style/GlobalStyle.js index d3bc618..8a4fc8e 100755 --- a/web/src/style/GlobalStyle.js +++ b/web/src/style/GlobalStyle.js @@ -15,6 +15,17 @@ export default createGlobalStyle` -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; letter-spacing: -0.1px; + -webkit-tap-highlight-color: transparent; + + @media screen and (display-mode: standalone) { + height: 100vh; + } + } + + header { + @media screen and (display-mode: standalone) { + padding-top: 30px; + } } button { diff --git a/web/src/style/StyledMenuButtonWrapper.js b/web/src/style/StyledMenuButtonWrapper.js new file mode 100644 index 0000000..fe772fa --- /dev/null +++ b/web/src/style/StyledMenuButtonWrapper.js @@ -0,0 +1,14 @@ +import { ListItem } from '@material-ui/core' +import styled from 'styled-components' + +export default styled(ListItem).attrs({ button: true })` + @media screen and (display-mode: standalone) { + width: 100%; + height: 60px; + display: flex; + flex-direction: column; + justify-content: center; + align-items: center; + font-size: 10px; + } +` diff --git a/web/src/style/materialUISetup.js b/web/src/style/materialUISetup.js index f30d2e4..875ee91 100644 --- a/web/src/style/materialUISetup.js +++ b/web/src/style/materialUISetup.js @@ -1,4 +1,4 @@ -import { createMuiTheme, useMediaQuery } from '@material-ui/core' +import { createTheme, useMediaQuery } from '@material-ui/core' import { useEffect, useMemo, useState } from 'react' import { mainColors } from './colors' @@ -7,7 +7,7 @@ export const THEME_MODES = { LIGHT: 'light', DARK: 'dark', AUTO: 'auto' } const typography = { fontFamily: 'Open Sans, sans-serif' } -export const darkTheme = createMuiTheme({ +export const darkTheme = createTheme({ typography, palette: { type: THEME_MODES.DARK, @@ -15,7 +15,7 @@ export const darkTheme = createMuiTheme({ secondary: { main: mainColors.dark.secondary }, }, }) -export const lightTheme = createMuiTheme({ +export const lightTheme = createTheme({ typography, palette: { type: THEME_MODES.LIGHT, @@ -45,7 +45,7 @@ export const useMaterialUITheme = () => { const muiTheme = useMemo( () => - createMuiTheme({ + createTheme({ typography, palette: { type: theme, diff --git a/web/src/utils/Utils.js b/web/src/utils/Utils.js index 4e3dbb1..782a097 100644 --- a/web/src/utils/Utils.js +++ b/web/src/utils/Utils.js @@ -65,3 +65,5 @@ export const getTorrents = async () => { throw new Error(null) } } + +export const isStandaloneApp = window.matchMedia('screen and (display-mode: standalone)').matches