Add Paul's Toolbox Contents
This commit is contained in:
@@ -0,0 +1,22 @@
|
||||
.bili {
|
||||
gap: 1em;
|
||||
display: flex;
|
||||
|
||||
.image {
|
||||
flex: 0 0 40%;
|
||||
}
|
||||
|
||||
.selector {
|
||||
gap: 1em;
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 1em;
|
||||
|
||||
img {
|
||||
width: 3em;
|
||||
height: 3em;
|
||||
cursor: pointer;
|
||||
border: 1px solid #eee;
|
||||
}
|
||||
}
|
||||
}
|
||||
+126
@@ -0,0 +1,126 @@
|
||||
import { useEffect, useState, type FormEvent } from "react";
|
||||
import Placeholder from "~components/ui/placeholder";
|
||||
import Form from "~components/ui/form";
|
||||
import { IconBack } from "~assets/icons";
|
||||
import styles from "./popup.module.less";
|
||||
import stylesB from "./bili.module.less";
|
||||
import useForm from "~hooks/useForm";
|
||||
|
||||
interface ReadProps {
|
||||
onBack: () => void;
|
||||
}
|
||||
|
||||
interface FormValue {
|
||||
name: string;
|
||||
ename: string;
|
||||
project: string;
|
||||
made: string;
|
||||
sale: string;
|
||||
type: number;
|
||||
desc: string;
|
||||
}
|
||||
|
||||
const getInfo = async () => {
|
||||
let tab: chrome.tabs.Tab;
|
||||
|
||||
[tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
|
||||
|
||||
if (tab && !tab.url.includes("chrome")) {
|
||||
const a = await chrome.tabs.sendMessage(tab.id, { type: 'toolbox:getBiliToy' });
|
||||
|
||||
console.log('get toy:', a);
|
||||
|
||||
return a;
|
||||
}
|
||||
}
|
||||
|
||||
function Toy({ onBack }: ReadProps) {
|
||||
const { bindInput, setValues, onSubmit } = useForm<FormValue>({
|
||||
initialValues: {
|
||||
type: 3,
|
||||
},
|
||||
onSubmit: (values) => {
|
||||
console.log(values);
|
||||
},
|
||||
});
|
||||
|
||||
const [imgs, setImgs] = useState([]);
|
||||
const [currentImg, setCurrentImg] = useState(0);
|
||||
const [failed, setFailed] = useState(false);
|
||||
|
||||
useEffect(() => {
|
||||
getInfo().then((res) => {
|
||||
if (!res) {
|
||||
setFailed(true);
|
||||
return;
|
||||
}
|
||||
|
||||
const { image, ...othors } = res;
|
||||
|
||||
setValues(othors);
|
||||
setImgs(res.images);
|
||||
setCurrentImg(0);
|
||||
})
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.tab} style={{ width: 600 }}>
|
||||
<header className={styles.header}>
|
||||
<button className={styles.back} onClick={onBack}>
|
||||
<IconBack />
|
||||
</button>
|
||||
<h2>添加手办</h2>
|
||||
</header>
|
||||
<main className={styles.body}>
|
||||
<Placeholder className={stylesB.bili} show={failed} value="非 B 站会员购页面">
|
||||
<div className={stylesB.image}>
|
||||
<img src={imgs[currentImg]} alt="" />
|
||||
<div className={stylesB.selector}>
|
||||
{imgs.map((item, index) => (
|
||||
<img src={item} alt="" onClick={() => setCurrentImg(index)} />
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
<Form className={stylesB.form} onSubmit={onSubmit((data) => console.log(data))}>
|
||||
<div>
|
||||
<label htmlFor="name">中文名</label>
|
||||
<input {...bindInput("name")} required placeholder="中文名" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="ename">英文名</label>
|
||||
<input {...bindInput("ename")} required placeholder="英文名" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="project">作品</label>
|
||||
<input {...bindInput("project")} required placeholder="作品" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="made">制作</label>
|
||||
<input {...bindInput("made")} required placeholder="制作" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="sale">发售日期</label>
|
||||
<input {...bindInput("sale")} required placeholder="发售日期" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="type">状态</label>
|
||||
<select {...bindInput("type")}>
|
||||
<option value={1}>已到货</option>
|
||||
<option value={2}>已预订</option>
|
||||
<option value={3}>想要但没钱</option>
|
||||
</select>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="desc">描述</label>
|
||||
<textarea {...bindInput("desc")} rows={5} required placeholder="描述"></textarea>
|
||||
</div>
|
||||
|
||||
<button type="submit">提交</button>
|
||||
</Form>
|
||||
</Placeholder>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Toy;
|
||||
@@ -0,0 +1,49 @@
|
||||
import { useState } from "react";
|
||||
import Menu from "./menu";
|
||||
import Read from "./read";
|
||||
import Toy from "./bili";
|
||||
import Message from "~components/ui/message";
|
||||
import { clsn } from "~utils";
|
||||
import "assets/global.css";
|
||||
import styles from "./popup.module.less";
|
||||
|
||||
function IndexPopup() {
|
||||
const [data, setData] = useState("")
|
||||
|
||||
const [tab, setTab] = useState<string>();
|
||||
|
||||
const onBack = () => {
|
||||
setTab(undefined);
|
||||
}
|
||||
|
||||
const onClickMenu = (value: string) => {
|
||||
if (value === "options") {
|
||||
chrome.runtime.openOptionsPage();
|
||||
return;
|
||||
}
|
||||
|
||||
setTab(value);
|
||||
}
|
||||
|
||||
const renderBody = () => {
|
||||
if (tab === "read") {
|
||||
return <Read onBack={onBack} />;
|
||||
}
|
||||
if (tab === "toy") {
|
||||
return <Toy onBack={onBack} />;
|
||||
}
|
||||
|
||||
return <Menu onClick={onClickMenu} />;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div className={clsn(styles.root, tab && styles.hasTab)}>
|
||||
{renderBody()}
|
||||
</div>
|
||||
<Message />
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default IndexPopup;
|
||||
@@ -0,0 +1,39 @@
|
||||
import { IconBili, IconRead, IconSetting } from "~assets/icons";
|
||||
import styles from "./popup.module.less";
|
||||
|
||||
const items = [
|
||||
{
|
||||
name: "在看",
|
||||
icon: <IconRead />,
|
||||
value: "read",
|
||||
},
|
||||
{
|
||||
name: "增加手办",
|
||||
icon: <IconBili />,
|
||||
value: "toy",
|
||||
},
|
||||
{
|
||||
name: "插件设置",
|
||||
icon: <IconSetting />,
|
||||
value: "options",
|
||||
}
|
||||
];
|
||||
|
||||
interface MenuProps {
|
||||
onClick: (value: string) => void;
|
||||
}
|
||||
|
||||
function Menu({ onClick }: MenuProps) {
|
||||
return (
|
||||
<div className={styles.menu}>
|
||||
{items.map((item) => (
|
||||
<div key={item.value} className={styles.item} onClick={() => onClick(item.value)}>
|
||||
{item.icon && item.icon}
|
||||
{item.name}
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Menu;
|
||||
@@ -0,0 +1,60 @@
|
||||
.root {
|
||||
color: #333;
|
||||
font-size: 14px;
|
||||
min-width: 200px;
|
||||
|
||||
&.hasTab {
|
||||
min-width: 300px;
|
||||
}
|
||||
}
|
||||
|
||||
.menu {
|
||||
.item {
|
||||
display: flex;
|
||||
cursor: pointer;
|
||||
padding: .75em 1em;
|
||||
border-bottom: 1px solid #eee;
|
||||
transition: background-color .3s;
|
||||
|
||||
svg {
|
||||
width: 1em;
|
||||
color: #28b9be;
|
||||
margin-right: .5em;
|
||||
}
|
||||
}
|
||||
|
||||
.item:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
}
|
||||
|
||||
.tab {
|
||||
.header {
|
||||
padding: .75em;
|
||||
position: relative;
|
||||
text-align: center;
|
||||
border-bottom: 1px solid #eee;
|
||||
|
||||
.back {
|
||||
top: 0;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 2em;
|
||||
font-size: 1.3em;
|
||||
position: absolute;
|
||||
transition: background-color .3s;
|
||||
|
||||
&:hover {
|
||||
background-color: #eee;
|
||||
}
|
||||
|
||||
svg {
|
||||
width: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.body {
|
||||
padding: 1em;
|
||||
}
|
||||
}
|
||||
+115
@@ -0,0 +1,115 @@
|
||||
import { sendToBackground } from "@plasmohq/messaging";
|
||||
import { useEffect, useState } from "react";
|
||||
import Form from "~components/ui/form";
|
||||
import { IconBack } from "~assets/icons";
|
||||
import styles from "./popup.module.less";
|
||||
import useForm from "~hooks/useForm";
|
||||
import { add } from "~components/ui/message/utils";
|
||||
|
||||
interface ReadProps {
|
||||
onBack: () => void;
|
||||
}
|
||||
|
||||
interface FormValue {
|
||||
title: string;
|
||||
link: string;
|
||||
desc: string;
|
||||
tips: string;
|
||||
}
|
||||
|
||||
const getInfo = async () => {
|
||||
const [tab] = await chrome.tabs.query({ active: true, lastFocusedWindow: true });
|
||||
|
||||
if (tab) {
|
||||
return await chrome.tabs.sendMessage(tab.id, { type: 'toolbox:getInfo' });
|
||||
}
|
||||
}
|
||||
|
||||
const submitForm = (body: FormValue) => {
|
||||
sendToBackground({
|
||||
name: "read",
|
||||
body: {
|
||||
action: "submitAddForm",
|
||||
values: body,
|
||||
},
|
||||
}).then((res) => {
|
||||
if (res.status === "Success") {
|
||||
add({
|
||||
content: "提交成功",
|
||||
});
|
||||
}
|
||||
else {
|
||||
add({
|
||||
content: res.msg,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function Read({ onBack }: ReadProps) {
|
||||
const [count, setCount] = useState(0);
|
||||
const { bindInput, setValues, onSubmit } = useForm<FormValue>({
|
||||
initialValues: {
|
||||
test: 'test',
|
||||
},
|
||||
onSubmit: (values) => {
|
||||
submitForm(values);
|
||||
},
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
getInfo().then((res) => {
|
||||
if (!res) {
|
||||
return;
|
||||
}
|
||||
|
||||
setValues(res);
|
||||
})
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<div className={styles.tab}>
|
||||
<header className={styles.header}>
|
||||
<button className={styles.back} onClick={onBack}>
|
||||
<IconBack />
|
||||
</button>
|
||||
<h2>在看</h2>
|
||||
</header>
|
||||
<main className={styles.body}>
|
||||
<Form onSubmit={onSubmit(submitForm)}>
|
||||
<input {...bindInput("title")} required placeholder="标题" />
|
||||
<input {...bindInput("link")} required placeholder="链接" />
|
||||
<div>
|
||||
<label htmlFor="desc">概括</label>
|
||||
<textarea {...bindInput("desc")} rows={5} required placeholder="概括"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="tips">评论 / 推荐理由</label>
|
||||
<textarea {...bindInput("tips")} rows={5} placeholder="推荐理由"></textarea>
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="author">作者</label>
|
||||
<input {...bindInput("author")} placeholder="作者" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="image">插图</label>
|
||||
<input {...bindInput("image")} placeholder="插图" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="sitename">站点名称</label>
|
||||
<input {...bindInput("sitename")} placeholder="站点名称" />
|
||||
</div>
|
||||
<div>
|
||||
<label htmlFor="tags">标签</label>
|
||||
<input {...bindInput("tags")} placeholder="标签" />
|
||||
</div>
|
||||
<button type="submit">提交</button>
|
||||
</Form>
|
||||
{count}
|
||||
<button onClick={() => setCount(prevCount => prevCount + 1)}>add</button>
|
||||
</main>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default Read;
|
||||
Reference in New Issue
Block a user