Fix web ui & optimise publish plugin/prettier actions (#1344)

* fix: display selected plugin

* fix: app bar responsive

* fix: sticky header

* added user-agent tooltip

* fix: responsive pop

* responsivve parsenovel

* chatper list responsive

* update dependecies

* update npm i action

* test

* skip prepare

* add terser to deps

* update tsc command

* remove ts-node

* fix: tsc options

* separate tsconfig for publish plugins

* revert host_plugins.yml

* test only terser & typescipt

* revert github action file

* cheapter prettier action
This commit is contained in:
nyagami
2024-11-29 15:52:36 +07:00
committed by GitHub
parent 99c5fb5d8f
commit e0b7d7eccb
16 changed files with 1332 additions and 1399 deletions
+2 -2
View File
@@ -1,8 +1,8 @@
#root {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
text-align: center;
width: 100vw;
padding-bottom: 40px;
}
.logo {
+2 -1
View File
@@ -32,10 +32,11 @@ function App() {
<ThemeProvider theme={theme}>
<CssBaseline />
<Appbar />
<Container
sx={{
mt: 6,
width: { sm: 500, md: 1024, lg: '90vw' },
width: '90%',
}}
>
<HeadersSection />
+90 -74
View File
@@ -5,16 +5,17 @@ import Toolbar from '@mui/material/Toolbar';
import {
Avatar,
Backdrop,
Button,
FormControl,
InputAdornment,
Link,
ListItem,
ListItemAvatar,
ListItemButton,
ListItemText,
TextField,
Typography,
} from '@mui/material';
import { Search, Translate } from '@mui/icons-material';
import { Search } from '@mui/icons-material';
import { searchPlugins } from '@provider/plugins';
import { Plugin } from '@typings/plugin';
import { FixedSizeList, ListChildComponentProps } from 'react-window';
@@ -28,11 +29,12 @@ function renderPlugin(setListVisible: (v: boolean) => void) {
return function (props: ListChildComponentProps<Plugin.PluginBase[]>) {
const { index, style, data } = props;
const plugin = data[index];
const selectPlugin = useAppStore(state => state.selectPlugin);
const { selectPlugin, pluginItem } = useAppStore(state => state);
return (
<ListItem style={style} key={index} component="div" disablePadding>
<ListItemButton
selected={plugin.id === pluginItem?.id}
onClick={() => {
selectPlugin({
id: plugin.id,
@@ -67,79 +69,93 @@ export default function Appbar() {
}, [keyword]);
return (
<Box sx={{ display: 'flex' }}>
<AppBar position="fixed" color="inherit" elevation={0}>
<Toolbar>
<FormControl
sx={{
display: 'block',
position: 'relative',
zIndex: 10,
<AppBar
sx={{ width: '100vw' }}
position="sticky"
color="inherit"
elevation={0}
>
<Toolbar>
<FormControl
sx={{
display: 'block',
position: 'relative',
zIndex: 10,
width: {
xs: '80%',
md: '40%',
},
}}
>
<TextField
size="small"
variant="outlined"
placeholder="Seach plugin"
value={keyword}
onChange={e => setKeyword(e.target.value)}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search />
</InputAdornment>
),
}}
>
<TextField
size="small"
variant="outlined"
placeholder="Seach plugin"
value={keyword}
onChange={e => setKeyword(e.target.value)}
InputProps={{
startAdornment: (
<InputAdornment position="start">
<Search />
</InputAdornment>
),
fullWidth
autoComplete="off"
onFocus={() => {
setListVisible(true);
if (searchedPlugins.length === 0)
setSearchPlugins(searchPlugins(keyword));
}}
/>
{listVisible ? (
<FixedSizeList
height={400}
width={'100%'}
itemData={searchedPlugins}
itemSize={46}
itemCount={searchedPlugins.length}
overscanCount={5}
style={{
position: 'absolute',
boxShadow: '2px 10px 20px rgba(0, 0, 0, 0.2)',
backgroundColor: 'white',
}}
sx={{ width: 434 }}
onFocus={() => {
setListVisible(true);
if (searchedPlugins.length === 0)
setSearchPlugins(searchPlugins(keyword));
}}
/>
{listVisible ? (
<FixedSizeList
height={400}
width={434}
itemData={searchedPlugins}
itemSize={46}
itemCount={searchedPlugins.length}
overscanCount={5}
style={{
position: 'absolute',
boxShadow: '2px 10px 20px rgba(0, 0, 0, 0.2)',
backgroundColor: 'white',
}}
>
{renderPlugin(setListVisible)}
</FixedSizeList>
) : null}
</FormControl>
<Backdrop
open={listVisible}
onClick={() => setListVisible(false)}
sx={{ zIndex: 9 }}
invisible={true}
></Backdrop>
<InputAdornment position="end">
<Button variant="contained" endIcon={<Translate />}>
Language
</Button>
</InputAdornment>
{plugin ? (
<Box sx={{ pl: 2, display: 'flex', alignItems: 'center' }}>
<Avatar
sx={{ mr: 1 }}
src={resovleIcon(plugin.icon)}
variant="square"
/>
<a href={plugin.site} target="_blank">
{plugin.name} - v{plugin.version}
</a>
</Box>
>
{renderPlugin(setListVisible)}
</FixedSizeList>
) : null}
</Toolbar>
</AppBar>
</Box>
</FormControl>
<Backdrop
open={listVisible}
onClick={() => setListVisible(false)}
sx={{ zIndex: 9 }}
invisible={true}
/>
{plugin ? (
<Link
sx={{
pl: 2,
display: 'flex',
alignItems: 'center',
textDecoration: 'none',
}}
href={plugin.site}
target="_blank"
>
<Avatar
sx={{ mr: 1 }}
src={resovleIcon(plugin.icon)}
variant="square"
/>
<Typography
sx={{ display: { xs: 'none', sm: 'none', md: 'block' } }}
>
{plugin.name} - v{plugin.version}
</Typography>
</Link>
) : null}
</Toolbar>
</AppBar>
);
}
+22 -15
View File
@@ -7,6 +7,7 @@ import {
MenuItem,
Select,
TextField,
Tooltip,
} from '@mui/material';
import Checkbox from '@mui/material/Checkbox';
import useDebounce from '@hooks/useDebounce';
@@ -57,17 +58,21 @@ export default function HeadersSection() {
</Alert>
) : null}
<Box sx={{ display: 'flex', alignItems: 'center' }}>
<TextField
size="small"
InputProps={{
startAdornment: (
<InputAdornment position="start">User Agent</InputAdornment>
),
}}
disabled
value={navigator.userAgent}
sx={{ width: '100%' }}
/>
<Tooltip title={navigator.userAgent}>
<TextField
size="small"
slotProps={{
input: {
startAdornment: (
<InputAdornment position="start">User Agent</InputAdornment>
),
},
}}
disabled
value={navigator.userAgent}
sx={{ width: '100%' }}
/>
</Tooltip>
<Checkbox
size="large"
checked={useUserAgent}
@@ -77,10 +82,12 @@ export default function HeadersSection() {
<Box sx={{ height: 10 }} />
<TextField
size="small"
InputProps={{
startAdornment: (
<InputAdornment position="start">Cookies</InputAdornment>
),
slotProps={{
input: {
startAdornment: (
<InputAdornment position="start">Cookies</InputAdornment>
),
},
}}
value={cookies}
onChange={e => {
@@ -62,7 +62,7 @@ export default function ChapterList({
chapters: Plugin.ChapterItem[];
}) {
return (
<Paper style={{ height: 400, width: '100%', textAlign: 'left' }}>
<Paper style={{ height: 400, minWidth: 600, textAlign: 'left' }}>
<TableVirtuoso
data={chapters}
components={VirtuosoTableComponents}
@@ -11,10 +11,10 @@ import {
Stack,
Tooltip,
Typography,
useTheme,
} from '@mui/material';
import CopiableItem from '@components/CopiableItem';
import PathItem from '@components/PathItem';
import Textarea from '@components/Textarea';
const FlexRow = ({ children }: { children: ReactNode }) => (
<Stack direction="row" gap={1} sx={{ alignItems: 'center' }}>
@@ -28,12 +28,12 @@ export default function SourceNovelCard({
sourceNovel: Plugin.SourceNovel;
}) {
return (
<Card sx={{ display: 'flex', p: 1, width: '100%', textAlign: 'left' }}>
<Box sx={{ display: 'flex', p: 1, width: '100%', textAlign: 'left' }}>
<CopiableItem content={sourceNovel.cover}>
<Tooltip title={sourceNovel.cover}>
<CardMedia
component="img"
sx={{ width: 200, height: '100%' }}
sx={{ width: 300, height: 400, objectFit: 'cover' }}
image={sourceNovel.cover}
/>
</Tooltip>
@@ -99,14 +99,19 @@ export default function SourceNovelCard({
</CardContent>
<CardContent>
<Typography>Summary</Typography>
<Textarea
sx={{ width: '100%' }}
maxRows={5}
value={sourceNovel.summary}
disabled
/>
<Typography
sx={{
overflowY: 'auto',
height: 300,
p: 2,
borderRadius: 2,
backgroundColor: 'rgba(0,0,0,0.1)',
}}
>
{sourceNovel.summary}
</Typography>
</CardContent>
</Box>
</Card>
</Box>
);
}
+29 -29
View File
@@ -9,7 +9,7 @@ import { useAppStore } from '@store';
export default function ParseNovel() {
const plugin = useAppStore(state => state.plugin);
const [sourceNovel, setSouceNovel] = useState<
Plugin.SourceNovel | undefined
(Plugin.SourceNovel & { totalPages?: number }) | undefined
>();
const [chapters, setChapters] = useState<Plugin.ChapterItem[]>([]);
const [loading, setLoading] = useState(false);
@@ -37,34 +37,34 @@ export default function ParseNovel() {
};
return (
<AccordionContainer title="Parse Novel" loading={loading}>
<Stack direction={'row'} spacing={2}>
<TextField
value={novelPath}
onChange={e => setNovelPath(e.target.value)}
size="small"
label="Novel path"
/>
<Button
disabled={plugin === undefined}
onClick={fetchNovel}
variant="contained"
>
Fetch
</Button>
</Stack>
{sourceNovel ? <SourceNovelCard sourceNovel={sourceNovel} /> : null}
<Box sx={{ height: 20 }} />
{chapters.length ? <ChapterList chapters={chapters} /> : null}
<Box sx={{ height: 20 }} />
{/* @ts-ignore */}
{sourceNovel?.totalPages ? (
<Pagination
// @ts-ignore
count={sourceNovel.totalPages}
onChange={(e, page) => fetchPage(page)}
variant="outlined"
/>
) : null}
<Box sx={{ overflowX: 'auto', width: '100%' }}>
<Stack direction={'row'} spacing={2}>
<TextField
value={novelPath}
onChange={e => setNovelPath(e.target.value)}
size="small"
label="Novel path"
/>
<Button
disabled={plugin === undefined}
onClick={fetchNovel}
variant="contained"
>
Fetch
</Button>
</Stack>
{sourceNovel ? <SourceNovelCard sourceNovel={sourceNovel} /> : null}
<Box sx={{ height: 20 }} />
{chapters.length ? <ChapterList chapters={chapters} /> : null}
<Box sx={{ height: 20 }} />
{sourceNovel?.totalPages ? (
<Pagination
count={sourceNovel.totalPages}
onChange={(e, page) => fetchPage(page)}
variant="outlined"
/>
) : null}
</Box>
</AccordionContainer>
);
}
@@ -80,7 +80,13 @@ export default function PopularNovels() {
return (
<AccordionContainer title="Popular Novels" loading={loading}>
<Stack direction={'row'} spacing={2} alignItems={'center'}>
<Stack
direction={'row'}
useFlexGap
sx={{ flexWrap: 'wrap' }}
spacing={2}
alignItems={'center'}
>
<FormGroup>
<FormControlLabel
control={
@@ -140,13 +146,12 @@ export default function PopularNovels() {
sx={{
width: '100%',
overflowX: 'auto',
display: 'flex',
}}
>
<Stack sx={{ width: 'max-content' }} direction={'row'} spacing={2}>
{novels.map((novel, index) => (
<NovelItemCard key={'novelItem_' + index} item={novel} />
))}
</Stack>
{novels.map((novel, index) => (
<NovelItemCard key={'novelItem_' + index} item={novel} />
))}
</Box>
</AccordionContainer>
);
@@ -13,7 +13,7 @@ import CopiableItem from '@components/CopiableItem';
import PathItem from '@components/PathItem';
export default function NovelItemCard({ item }: { item: Plugin.NovelItem }) {
return (
<Card sx={{ display: 'flex', p: 1 }}>
<Box sx={{ display: 'flex', p: 1 }}>
<CopiableItem content={item.cover}>
<Tooltip title={item.cover}>
<CardMedia
@@ -50,6 +50,6 @@ export default function NovelItemCard({ item }: { item: Plugin.NovelItem }) {
<PathItem path={item.path} />
</CardContent>
</Box>
</Card>
</Box>
);
}