refactor: add TranslatorManager
This commit is contained in:
73
src/views/Action/ContentFab.js
Normal file
73
src/views/Action/ContentFab.js
Normal file
@@ -0,0 +1,73 @@
|
||||
import Fab from "@mui/material/Fab";
|
||||
import TranslateIcon from "@mui/icons-material/Translate";
|
||||
import ThemeProvider from "../../hooks/Theme";
|
||||
import Draggable from "./Draggable";
|
||||
import { useState, useMemo, useCallback } from "react";
|
||||
import { SettingProvider } from "../../hooks/Setting";
|
||||
import { MSG_TRANS_TOGGLE } from "../../config";
|
||||
import { sendIframeMsg } from "../../libs/iframe";
|
||||
import useWindowSize from "../../hooks/WindowSize";
|
||||
|
||||
export default function ContentFab({
|
||||
translator,
|
||||
fabConfig: { x: fabX, y: fabY, fabClickAction = 0 } = {},
|
||||
popupManager,
|
||||
}) {
|
||||
const fabWidth = 40;
|
||||
const windowSize = useWindowSize();
|
||||
const [moved, setMoved] = useState(false);
|
||||
|
||||
const handleStart = useCallback(() => {
|
||||
setMoved(false);
|
||||
}, []);
|
||||
|
||||
const handleMove = useCallback(() => {
|
||||
setMoved(true);
|
||||
}, []);
|
||||
|
||||
const handleClick = useCallback(() => {
|
||||
if (!moved) {
|
||||
if (fabClickAction === 1) {
|
||||
translator.toggle();
|
||||
sendIframeMsg(MSG_TRANS_TOGGLE);
|
||||
} else {
|
||||
popupManager.toggle();
|
||||
}
|
||||
}
|
||||
}, [moved, translator, popupManager, fabClickAction]);
|
||||
|
||||
const fabProps = useMemo(
|
||||
() => ({
|
||||
windowSize,
|
||||
width: fabWidth,
|
||||
height: fabWidth,
|
||||
left: fabX ?? -fabWidth,
|
||||
top: fabY ?? windowSize.h / 2,
|
||||
}),
|
||||
[windowSize, fabWidth, fabX, fabY]
|
||||
);
|
||||
|
||||
return (
|
||||
<SettingProvider>
|
||||
<ThemeProvider>
|
||||
<Draggable
|
||||
key="fab"
|
||||
snapEdge
|
||||
{...fabProps}
|
||||
onStart={handleStart}
|
||||
onMove={handleMove}
|
||||
handler={
|
||||
<Fab size="small" color="primary" onClick={handleClick}>
|
||||
<TranslateIcon
|
||||
sx={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
}}
|
||||
/>
|
||||
</Fab>
|
||||
}
|
||||
/>
|
||||
</ThemeProvider>
|
||||
</SettingProvider>
|
||||
);
|
||||
}
|
||||
@@ -50,7 +50,7 @@ export default function Draggable({
|
||||
height,
|
||||
left,
|
||||
top,
|
||||
show,
|
||||
show = true,
|
||||
snapEdge,
|
||||
onStart,
|
||||
onMove,
|
||||
|
||||
@@ -1,157 +1,19 @@
|
||||
import Fab from "@mui/material/Fab";
|
||||
import TranslateIcon from "@mui/icons-material/Translate";
|
||||
import ThemeProvider from "../../hooks/Theme";
|
||||
import Draggable from "./Draggable";
|
||||
import { useEffect, useState, useMemo, useCallback } from "react";
|
||||
import { useEffect, useMemo, useCallback } from "react";
|
||||
import { SettingProvider } from "../../hooks/Setting";
|
||||
import Popup from "../Popup";
|
||||
import { debounce } from "../../libs/utils";
|
||||
import { isGm } from "../../libs/client";
|
||||
import Header from "../Popup/Header";
|
||||
import Box from "@mui/material/Box";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import {
|
||||
DEFAULT_SHORTCUTS,
|
||||
OPT_SHORTCUT_TRANSLATE,
|
||||
OPT_SHORTCUT_STYLE,
|
||||
OPT_SHORTCUT_POPUP,
|
||||
OPT_SHORTCUT_SETTING,
|
||||
MSG_TRANS_TOGGLE,
|
||||
MSG_TRANS_TOGGLE_STYLE,
|
||||
} from "../../config";
|
||||
import { shortcutRegister } from "../../libs/shortcut";
|
||||
import { sendIframeMsg } from "../../libs/iframe";
|
||||
import { kissLog } from "../../libs/log";
|
||||
import { getI18n } from "../../hooks/I18n";
|
||||
import useWindowSize from "../../hooks/WindowSize";
|
||||
|
||||
export default function Action({ translator, fab }) {
|
||||
const fabWidth = 40;
|
||||
const [showPopup, setShowPopup] = useState(false);
|
||||
const [windowSize, setWindowSize] = useState({
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight,
|
||||
});
|
||||
const [moved, setMoved] = useState(false);
|
||||
export default function Action({ translator, onClose }) {
|
||||
const windowSize = useWindowSize();
|
||||
|
||||
const { fabClickAction = 0 } = fab || {};
|
||||
|
||||
const handleWindowResize = useMemo(
|
||||
() =>
|
||||
debounce(() => {
|
||||
setWindowSize({
|
||||
w: window.innerWidth,
|
||||
h: window.innerHeight,
|
||||
});
|
||||
}),
|
||||
[]
|
||||
);
|
||||
|
||||
const handleWindowClick = (e) => {
|
||||
setShowPopup(false);
|
||||
};
|
||||
|
||||
const handleStart = useCallback(() => {
|
||||
setMoved(false);
|
||||
}, []);
|
||||
|
||||
const handleMove = useCallback(() => {
|
||||
setMoved(true);
|
||||
}, []);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isGm) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 注册快捷键
|
||||
const shortcuts = translator.setting.shortcuts || DEFAULT_SHORTCUTS;
|
||||
const clearShortcuts = [
|
||||
shortcutRegister(shortcuts[OPT_SHORTCUT_TRANSLATE], () => {
|
||||
translator.toggle();
|
||||
sendIframeMsg(MSG_TRANS_TOGGLE);
|
||||
setShowPopup(false);
|
||||
}),
|
||||
shortcutRegister(shortcuts[OPT_SHORTCUT_STYLE], () => {
|
||||
translator.toggleStyle();
|
||||
sendIframeMsg(MSG_TRANS_TOGGLE_STYLE);
|
||||
setShowPopup(false);
|
||||
}),
|
||||
shortcutRegister(shortcuts[OPT_SHORTCUT_POPUP], () => {
|
||||
setShowPopup((pre) => !pre);
|
||||
}),
|
||||
shortcutRegister(shortcuts[OPT_SHORTCUT_SETTING], () => {
|
||||
window.open(process.env.REACT_APP_OPTIONSPAGE, "_blank");
|
||||
}),
|
||||
];
|
||||
|
||||
return () => {
|
||||
clearShortcuts.forEach((fn) => {
|
||||
fn();
|
||||
});
|
||||
};
|
||||
}, [translator]);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isGm) {
|
||||
return;
|
||||
}
|
||||
|
||||
// 注册菜单
|
||||
try {
|
||||
const menuCommandIds = [];
|
||||
const { contextMenuType, uiLang } = translator.setting;
|
||||
contextMenuType !== 0 &&
|
||||
menuCommandIds.push(
|
||||
GM.registerMenuCommand(
|
||||
getI18n(uiLang, "translate_switch"),
|
||||
(event) => {
|
||||
translator.toggle();
|
||||
sendIframeMsg(MSG_TRANS_TOGGLE);
|
||||
setShowPopup(false);
|
||||
},
|
||||
"Q"
|
||||
),
|
||||
GM.registerMenuCommand(
|
||||
getI18n(uiLang, "toggle_style"),
|
||||
(event) => {
|
||||
translator.toggleStyle();
|
||||
sendIframeMsg(MSG_TRANS_TOGGLE_STYLE);
|
||||
setShowPopup(false);
|
||||
},
|
||||
"C"
|
||||
),
|
||||
GM.registerMenuCommand(
|
||||
getI18n(uiLang, "open_menu"),
|
||||
(event) => {
|
||||
setShowPopup((pre) => !pre);
|
||||
},
|
||||
"K"
|
||||
),
|
||||
GM.registerMenuCommand(
|
||||
getI18n(uiLang, "open_setting"),
|
||||
(event) => {
|
||||
window.open(process.env.REACT_APP_OPTIONSPAGE, "_blank");
|
||||
},
|
||||
"O"
|
||||
)
|
||||
);
|
||||
|
||||
return () => {
|
||||
menuCommandIds.forEach((id) => {
|
||||
GM.unregisterMenuCommand(id);
|
||||
});
|
||||
};
|
||||
} catch (err) {
|
||||
kissLog("registerMenuCommand", err);
|
||||
}
|
||||
}, [translator]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("resize", handleWindowResize);
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleWindowResize);
|
||||
};
|
||||
}, [handleWindowResize]);
|
||||
const handleWindowClick = useCallback(() => {
|
||||
onClose();
|
||||
}, [onClose]);
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("click", handleWindowClick);
|
||||
@@ -159,7 +21,7 @@ export default function Action({ translator, fab }) {
|
||||
return () => {
|
||||
window.removeEventListener("click", handleWindowClick);
|
||||
};
|
||||
}, []);
|
||||
}, [handleWindowClick]);
|
||||
|
||||
const popProps = useMemo(() => {
|
||||
const width = Math.min(windowSize.w, 360);
|
||||
@@ -175,67 +37,22 @@ export default function Action({ translator, fab }) {
|
||||
};
|
||||
}, [windowSize]);
|
||||
|
||||
const fabProps = {
|
||||
windowSize,
|
||||
width: fabWidth,
|
||||
height: fabWidth,
|
||||
left: fab.x ?? -fabWidth,
|
||||
top: fab.y ?? windowSize.h / 2,
|
||||
};
|
||||
|
||||
return (
|
||||
<SettingProvider>
|
||||
<ThemeProvider>
|
||||
<Draggable
|
||||
key="pop"
|
||||
{...popProps}
|
||||
show={showPopup}
|
||||
onStart={handleStart}
|
||||
onMove={handleMove}
|
||||
usePaper
|
||||
handler={
|
||||
<Box style={{ cursor: "move" }}>
|
||||
<Header setShowPopup={setShowPopup} />
|
||||
<Header onClose={onClose} />
|
||||
<Divider />
|
||||
</Box>
|
||||
}
|
||||
>
|
||||
{showPopup && (
|
||||
<Popup setShowPopup={setShowPopup} translator={translator} />
|
||||
)}
|
||||
<Popup translator={translator} />
|
||||
</Draggable>
|
||||
<Draggable
|
||||
key="fab"
|
||||
snapEdge
|
||||
{...fabProps}
|
||||
show={fab.isHide ? false : !showPopup}
|
||||
onStart={handleStart}
|
||||
onMove={handleMove}
|
||||
handler={
|
||||
<Fab
|
||||
size="small"
|
||||
color="primary"
|
||||
onClick={(e) => {
|
||||
if (!moved) {
|
||||
if (fabClickAction === 1) {
|
||||
translator.toggle();
|
||||
sendIframeMsg(MSG_TRANS_TOGGLE);
|
||||
setShowPopup(false);
|
||||
} else {
|
||||
setShowPopup((pre) => !pre);
|
||||
}
|
||||
}
|
||||
}}
|
||||
>
|
||||
<TranslateIcon
|
||||
sx={{
|
||||
width: 24,
|
||||
height: 24,
|
||||
}}
|
||||
/>
|
||||
</Fab>
|
||||
}
|
||||
/>
|
||||
</ThemeProvider>
|
||||
</SettingProvider>
|
||||
);
|
||||
|
||||
@@ -5,7 +5,7 @@ import Stack from "@mui/material/Stack";
|
||||
import DarkModeButton from "../Options/DarkModeButton";
|
||||
import Typography from "@mui/material/Typography";
|
||||
|
||||
export default function Header({ setShowPopup }) {
|
||||
export default function Header({ onClose }) {
|
||||
const handleHomepage = () => {
|
||||
window.open(process.env.REACT_APP_HOMEPAGE, "_blank");
|
||||
};
|
||||
@@ -33,10 +33,10 @@ export default function Header({ setShowPopup }) {
|
||||
</Typography>
|
||||
</Stack>
|
||||
|
||||
{setShowPopup ? (
|
||||
{onClose ? (
|
||||
<IconButton
|
||||
onClick={() => {
|
||||
setShowPopup(false);
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
<CloseIcon />
|
||||
|
||||
@@ -35,7 +35,7 @@ import { parseUrlPattern } from "../../libs/utils";
|
||||
|
||||
// 插件popup没有参数
|
||||
// 网页弹框有
|
||||
export default function Popup({ setShowPopup, translator }) {
|
||||
export default function Popup({ translator }) {
|
||||
const i18n = useI18n();
|
||||
const [rule, setRule] = useState(translator?.rule);
|
||||
const [setting, setSetting] = useState(translator?.setting);
|
||||
@@ -49,7 +49,6 @@ export default function Popup({ setShowPopup, translator }) {
|
||||
} else {
|
||||
window.open(process.env.REACT_APP_OPTIONSPAGE, "_blank");
|
||||
}
|
||||
setShowPopup && setShowPopup(false);
|
||||
};
|
||||
|
||||
const handleTransToggle = async (e) => {
|
||||
|
||||
Reference in New Issue
Block a user