tranbox...
This commit is contained in:
@@ -9,11 +9,13 @@ import {
|
||||
MSG_TRANS_GETRULE,
|
||||
MSG_TRANS_PUTRULE,
|
||||
APP_LCNAME,
|
||||
DEFAULT_TRANBOX_SETTING,
|
||||
} from "./config";
|
||||
import { getRulesWithDefault, getFabWithDefault } from "./libs/storage";
|
||||
import { Translator } from "./libs/translator";
|
||||
import { sendIframeMsg, sendParentMsg } from "./libs/iframe";
|
||||
import { matchRule } from "./libs/rules";
|
||||
import Slection from "./views/Selection";
|
||||
|
||||
export async function runTranslator(setting) {
|
||||
const href = document.location.href;
|
||||
@@ -50,7 +52,10 @@ export function runIframe(setting) {
|
||||
|
||||
export async function showFab(translator) {
|
||||
const fab = await getFabWithDefault();
|
||||
if (!fab.isHide) {
|
||||
if (fab.isHide) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $action = document.createElement("div");
|
||||
$action.setAttribute("id", APP_LCNAME);
|
||||
document.body.parentElement.appendChild($action);
|
||||
@@ -71,7 +76,33 @@ export async function showFab(translator) {
|
||||
</CacheProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
|
||||
export function showTransbox({ tranboxSetting = DEFAULT_TRANBOX_SETTING }) {
|
||||
if (!tranboxSetting?.transOpen) {
|
||||
return;
|
||||
}
|
||||
|
||||
const $tranbox = document.createElement("div");
|
||||
$tranbox.setAttribute("id", "kiss-transbox");
|
||||
document.body.parentElement.appendChild($tranbox);
|
||||
const shadowContainer = $tranbox.attachShadow({ mode: "closed" });
|
||||
const emotionRoot = document.createElement("style");
|
||||
const shadowRootElement = document.createElement("div");
|
||||
shadowContainer.appendChild(emotionRoot);
|
||||
shadowContainer.appendChild(shadowRootElement);
|
||||
const cache = createCache({
|
||||
key: "kiss-transbox",
|
||||
prepend: true,
|
||||
container: emotionRoot,
|
||||
});
|
||||
ReactDOM.createRoot(shadowRootElement).render(
|
||||
<React.StrictMode>
|
||||
<CacheProvider value={cache}>
|
||||
<Slection tranboxSetting={tranboxSetting} />
|
||||
</CacheProvider>
|
||||
</React.StrictMode>
|
||||
);
|
||||
}
|
||||
|
||||
export function windowListener(rule) {
|
||||
|
||||
@@ -611,4 +611,24 @@ export const I18N = {
|
||||
zh: `启用`,
|
||||
en: `Enable`,
|
||||
},
|
||||
selection_translate: {
|
||||
zh: `划词翻译`,
|
||||
en: `Selection Translate`,
|
||||
},
|
||||
toggle_selection_translate: {
|
||||
zh: `启用划词翻译`,
|
||||
en: `Use Selection Translate`,
|
||||
},
|
||||
trigger_tranbox_shortcut: {
|
||||
zh: `显示翻译框快捷键`,
|
||||
en: `Toggle Translate Box Shortcut`,
|
||||
},
|
||||
tanbtn_offset_x: {
|
||||
zh: `翻译按钮偏移(X)`,
|
||||
en: `Translate Button Offset (X)`,
|
||||
},
|
||||
tanbtn_offset_y: {
|
||||
zh: `翻译按钮偏移(Y)`,
|
||||
en: `Translate Button Offset (Y)`,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -312,6 +312,18 @@ export const DEFAULT_INPUT_RULE = {
|
||||
transSign: OPT_INPUT_TRANS_SIGNS[0],
|
||||
};
|
||||
|
||||
// 划词翻译
|
||||
export const DEFAULT_TRANBOX_SHORTCUT = ["AltLeft", "KeyB"];
|
||||
export const DEFAULT_TRANBOX_SETTING = {
|
||||
transOpen: true,
|
||||
translator: OPT_TRANS_MICROSOFT,
|
||||
fromLang: "auto",
|
||||
toLang: "zh-CN",
|
||||
tranboxShortcut: DEFAULT_TRANBOX_SHORTCUT,
|
||||
btnOffsetX: 10,
|
||||
btnOffsetY: 10,
|
||||
};
|
||||
|
||||
// 订阅列表
|
||||
export const DEFAULT_SUBRULES_LIST = [
|
||||
{
|
||||
@@ -388,6 +400,7 @@ export const DEFAULT_SETTING = {
|
||||
mouseKey: OPT_MOUSEKEY_DISABLE, // 鼠标悬停翻译
|
||||
shortcuts: DEFAULT_SHORTCUTS, // 快捷键
|
||||
inputRule: DEFAULT_INPUT_RULE, // 输入框设置
|
||||
tranboxSetting: DEFAULT_TRANBOX_SETTING, // 划词翻译设置
|
||||
};
|
||||
|
||||
export const DEFAULT_RULES = [GLOBLA_RULE];
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
runIframe,
|
||||
runTranslator,
|
||||
showFab,
|
||||
showTransbox,
|
||||
windowListener,
|
||||
showErr,
|
||||
} from "./common";
|
||||
@@ -66,6 +67,9 @@ function runtimeListener(translator) {
|
||||
|
||||
// 浮球按钮
|
||||
await showFab(translator);
|
||||
|
||||
// 划词翻译
|
||||
showTransbox(setting);
|
||||
} catch (err) {
|
||||
showErr(err);
|
||||
}
|
||||
|
||||
18
src/hooks/Tranbox.js
Normal file
18
src/hooks/Tranbox.js
Normal file
@@ -0,0 +1,18 @@
|
||||
import { useCallback } from "react";
|
||||
import { DEFAULT_TRANBOX_SETTING } from "../config";
|
||||
import { useSetting } from "./Setting";
|
||||
|
||||
export function useTranbox() {
|
||||
const { setting, updateSetting } = useSetting();
|
||||
const tranboxSetting = setting?.tranboxSetting || DEFAULT_TRANBOX_SETTING;
|
||||
|
||||
const updateTranbox = useCallback(
|
||||
async (obj) => {
|
||||
Object.assign(tranboxSetting, obj);
|
||||
await updateSetting({ tranboxSetting });
|
||||
},
|
||||
[tranboxSetting, updateSetting]
|
||||
);
|
||||
|
||||
return { tranboxSetting, updateTranbox };
|
||||
}
|
||||
@@ -8,6 +8,7 @@ import {
|
||||
runIframe,
|
||||
runTranslator,
|
||||
showFab,
|
||||
showTransbox,
|
||||
windowListener,
|
||||
showErr,
|
||||
} from "./common";
|
||||
@@ -65,6 +66,9 @@ function runSettingPage() {
|
||||
// 浮球按钮
|
||||
await showFab(translator);
|
||||
|
||||
// 划词翻译
|
||||
showTransbox(setting);
|
||||
|
||||
// 同步订阅规则
|
||||
await trySyncAllSubRules(setting);
|
||||
} catch (err) {
|
||||
|
||||
@@ -45,6 +45,12 @@ export default function Navigator(props) {
|
||||
url: "/input",
|
||||
icon: <InputIcon />,
|
||||
},
|
||||
{
|
||||
id: "selection_translate",
|
||||
label: i18n("selection_translate"),
|
||||
url: "/tranbox",
|
||||
icon: <InputIcon />,
|
||||
},
|
||||
{
|
||||
id: "apis_setting",
|
||||
label: i18n("apis_setting"),
|
||||
|
||||
137
src/views/Options/Tranbox.js
Normal file
137
src/views/Options/Tranbox.js
Normal file
@@ -0,0 +1,137 @@
|
||||
import Box from "@mui/material/Box";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import { useI18n } from "../../hooks/I18n";
|
||||
import { OPT_TRANS_ALL, OPT_LANGS_FROM, OPT_LANGS_TO } from "../../config";
|
||||
import ShortcutInput from "./ShortcutInput";
|
||||
import FormControlLabel from "@mui/material/FormControlLabel";
|
||||
import Switch from "@mui/material/Switch";
|
||||
import { useCallback } from "react";
|
||||
import { limitNumber } from "../../libs/utils";
|
||||
import { useTranbox } from "../../hooks/Tranbox";
|
||||
|
||||
export default function Tranbox() {
|
||||
const i18n = useI18n();
|
||||
const { tranboxSetting, updateTranbox } = useTranbox();
|
||||
|
||||
const handleChange = (e) => {
|
||||
e.preventDefault();
|
||||
let { name, value } = e.target;
|
||||
switch (name) {
|
||||
case "btnOffsetX" || "btnOffsetY":
|
||||
value = limitNumber(value, 0, 100);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
updateTranbox({
|
||||
[name]: value,
|
||||
});
|
||||
};
|
||||
|
||||
const handleShortcutInput = useCallback(
|
||||
(val) => {
|
||||
updateTranbox({ tranboxShortcut: val });
|
||||
},
|
||||
[updateTranbox]
|
||||
);
|
||||
|
||||
const {
|
||||
transOpen,
|
||||
translator,
|
||||
fromLang,
|
||||
toLang,
|
||||
tranboxShortcut,
|
||||
btnOffsetX,
|
||||
btnOffsetY,
|
||||
} = tranboxSetting;
|
||||
|
||||
return (
|
||||
<Box>
|
||||
<Stack spacing={3}>
|
||||
<FormControlLabel
|
||||
control={
|
||||
<Switch
|
||||
size="small"
|
||||
name="transOpen"
|
||||
checked={transOpen}
|
||||
onChange={() => {
|
||||
updateTranbox({ transOpen: !transOpen });
|
||||
}}
|
||||
/>
|
||||
}
|
||||
label={i18n("toggle_selection_translate")}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
select
|
||||
size="small"
|
||||
name="translator"
|
||||
value={translator}
|
||||
label={i18n("translate_service")}
|
||||
onChange={handleChange}
|
||||
>
|
||||
{OPT_TRANS_ALL.map((item) => (
|
||||
<MenuItem key={item} value={item}>
|
||||
{item}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
select
|
||||
size="small"
|
||||
name="fromLang"
|
||||
value={fromLang}
|
||||
label={i18n("from_lang")}
|
||||
onChange={handleChange}
|
||||
>
|
||||
{OPT_LANGS_FROM.map(([lang, name]) => (
|
||||
<MenuItem key={lang} value={lang}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
select
|
||||
size="small"
|
||||
name="toLang"
|
||||
value={toLang}
|
||||
label={i18n("to_lang")}
|
||||
onChange={handleChange}
|
||||
>
|
||||
{OPT_LANGS_TO.map(([lang, name]) => (
|
||||
<MenuItem key={lang} value={lang}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
|
||||
<TextField
|
||||
size="small"
|
||||
label={i18n("tanbtn_offset_x")}
|
||||
type="number"
|
||||
name="btnOffsetX"
|
||||
defaultValue={btnOffsetX}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
|
||||
<TextField
|
||||
size="small"
|
||||
label={i18n("tanbtn_offset_y")}
|
||||
type="number"
|
||||
name="btnOffsetY"
|
||||
defaultValue={btnOffsetY}
|
||||
onChange={handleChange}
|
||||
/>
|
||||
|
||||
<ShortcutInput
|
||||
value={tranboxShortcut}
|
||||
onChange={handleShortcutInput}
|
||||
label={i18n("trigger_tranbox_shortcut")}
|
||||
/>
|
||||
</Stack>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
@@ -20,6 +20,7 @@ import Alert from "@mui/material/Alert";
|
||||
import Apis from "./Apis";
|
||||
import Webfix from "./Webfix";
|
||||
import InputSetting from "./InputSetting";
|
||||
import Tranbox from "./Tranbox";
|
||||
|
||||
export default function Options() {
|
||||
const [error, setError] = useState("");
|
||||
@@ -120,6 +121,7 @@ export default function Options() {
|
||||
<Route index element={<Setting />} />
|
||||
<Route path="rules" element={<Rules />} />
|
||||
<Route path="input" element={<InputSetting />} />
|
||||
<Route path="tranbox" element={<Tranbox />} />
|
||||
<Route path="apis" element={<Apis />} />
|
||||
<Route path="sync" element={<SyncSetting />} />
|
||||
<Route path="webfix" element={<Webfix />} />
|
||||
|
||||
248
src/views/Selection/DraggableResizable.js
Normal file
248
src/views/Selection/DraggableResizable.js
Normal file
@@ -0,0 +1,248 @@
|
||||
import { useState } from "react";
|
||||
import Paper from "@mui/material/Paper";
|
||||
import Box from "@mui/material/Box";
|
||||
|
||||
function Pointer({
|
||||
direction,
|
||||
size,
|
||||
setSize,
|
||||
position,
|
||||
setPosition,
|
||||
children,
|
||||
minSize,
|
||||
maxSize,
|
||||
...props
|
||||
}) {
|
||||
const [origin, setOrigin] = useState(null);
|
||||
|
||||
function handlePointerDown(e) {
|
||||
e.target.setPointerCapture(e.pointerId);
|
||||
setOrigin({
|
||||
x: position.x,
|
||||
y: position.y,
|
||||
w: size.w,
|
||||
h: size.h,
|
||||
clientX: e.clientX,
|
||||
clientY: e.clientY,
|
||||
});
|
||||
}
|
||||
|
||||
function handlePointerMove(e) {
|
||||
if (origin) {
|
||||
const dx = e.clientX - origin.clientX;
|
||||
const dy = e.clientY - origin.clientY;
|
||||
let x = position.x;
|
||||
let y = position.y;
|
||||
let w = size.w;
|
||||
let h = size.h;
|
||||
|
||||
switch (direction) {
|
||||
case "Header":
|
||||
x = origin.x + dx;
|
||||
y = origin.y + dy;
|
||||
break;
|
||||
case "TopLeft":
|
||||
x = origin.x + dx;
|
||||
y = origin.y + dy;
|
||||
w = origin.w - dx;
|
||||
h = origin.h - dy;
|
||||
break;
|
||||
case "Top":
|
||||
y = origin.y + dy;
|
||||
h = origin.h - dy;
|
||||
break;
|
||||
case "TopRight":
|
||||
y = origin.y + dy;
|
||||
w = origin.w + dx;
|
||||
h = origin.h - dy;
|
||||
break;
|
||||
case "Left":
|
||||
x = origin.x + dx;
|
||||
w = origin.w - dx;
|
||||
break;
|
||||
case "Right":
|
||||
w = origin.w + dx;
|
||||
break;
|
||||
case "BottomLeft":
|
||||
x = origin.x + dx;
|
||||
w = origin.w - dx;
|
||||
h = origin.h + dy;
|
||||
break;
|
||||
case "Bottom":
|
||||
h = origin.h + dy;
|
||||
break;
|
||||
case "BottomRight":
|
||||
w = origin.w + dx;
|
||||
h = origin.h + dy;
|
||||
break;
|
||||
}
|
||||
|
||||
if (w < minSize.w) {
|
||||
w = minSize.w;
|
||||
x = position.x;
|
||||
}
|
||||
if (w > maxSize.w) {
|
||||
w = maxSize.w;
|
||||
x = position.x;
|
||||
}
|
||||
if (h < minSize.h) {
|
||||
h = minSize.h;
|
||||
y = position.y;
|
||||
}
|
||||
if (h > maxSize.h) {
|
||||
h = maxSize.h;
|
||||
y = position.y;
|
||||
}
|
||||
|
||||
setPosition({ x, y });
|
||||
setSize({ w, h });
|
||||
}
|
||||
}
|
||||
|
||||
function handlePointerUp(e) {
|
||||
setOrigin(null);
|
||||
}
|
||||
|
||||
return (
|
||||
<div
|
||||
{...props}
|
||||
onPointerDown={handlePointerDown}
|
||||
onPointerMove={handlePointerMove}
|
||||
onPointerUp={handlePointerUp}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default function DraggableResizable({
|
||||
header,
|
||||
children,
|
||||
defaultPosition = {
|
||||
x: 0,
|
||||
y: 0,
|
||||
},
|
||||
defaultSize = {
|
||||
w: 600,
|
||||
h: 400,
|
||||
},
|
||||
minSize = {
|
||||
w: 300,
|
||||
h: 200,
|
||||
},
|
||||
maxSize = {
|
||||
w: 1200,
|
||||
h: 1200,
|
||||
},
|
||||
sx,
|
||||
}) {
|
||||
const lineWidth = 4;
|
||||
const [position, setPosition] = useState(defaultPosition);
|
||||
const [size, setSize] = useState(defaultSize);
|
||||
|
||||
const opts = {
|
||||
size,
|
||||
setSize,
|
||||
position,
|
||||
setPosition,
|
||||
minSize,
|
||||
maxSize,
|
||||
};
|
||||
|
||||
return (
|
||||
<Box
|
||||
style={{
|
||||
position: "fixed",
|
||||
left: position.x,
|
||||
top: position.y,
|
||||
display: "grid",
|
||||
gridTemplateColumns: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
||||
gridTemplateRows: `${lineWidth * 2}px auto ${lineWidth * 2}px`,
|
||||
zIndex: 10000,
|
||||
}}
|
||||
>
|
||||
<Pointer
|
||||
direction="TopLeft"
|
||||
style={{
|
||||
transform: `translate(${lineWidth}px, ${lineWidth}px)`,
|
||||
cursor: "nw-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
<Pointer
|
||||
direction="Top"
|
||||
style={{
|
||||
margin: `0 ${lineWidth}px`,
|
||||
transform: `translate(0px, ${lineWidth}px)`,
|
||||
cursor: "row-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
<Pointer
|
||||
direction="TopRight"
|
||||
style={{
|
||||
transform: `translate(-${lineWidth}px, ${lineWidth}px)`,
|
||||
cursor: "ne-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
<Pointer
|
||||
direction="Left"
|
||||
style={{
|
||||
margin: `${lineWidth}px 0`,
|
||||
transform: `translate(${lineWidth}px, 0px)`,
|
||||
cursor: "col-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
<Paper elevation={4}>
|
||||
<Pointer direction="Header" style={{ cursor: "move" }} {...opts}>
|
||||
{header}
|
||||
</Pointer>
|
||||
<div
|
||||
style={{
|
||||
width: size.w,
|
||||
height: size.h,
|
||||
overflow: "hidden auto",
|
||||
}}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
</Paper>
|
||||
<Pointer
|
||||
direction="Right"
|
||||
style={{
|
||||
margin: `${lineWidth}px 0`,
|
||||
transform: `translate(-${lineWidth}px, 0px)`,
|
||||
cursor: "col-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
<Pointer
|
||||
direction="BottomLeft"
|
||||
style={{
|
||||
transform: `translate(${lineWidth}px, -${lineWidth}px)`,
|
||||
cursor: "ne-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
<Pointer
|
||||
direction="Bottom"
|
||||
style={{
|
||||
margin: `0 ${lineWidth}px`,
|
||||
transform: `translate(0px, -${lineWidth}px)`,
|
||||
cursor: "row-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
<Pointer
|
||||
direction="BottomRight"
|
||||
style={{
|
||||
transform: `translate(-${lineWidth}px, -${lineWidth}px)`,
|
||||
cursor: "nw-resize",
|
||||
}}
|
||||
{...opts}
|
||||
/>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
105
src/views/Selection/Tranbox.js
Normal file
105
src/views/Selection/Tranbox.js
Normal file
@@ -0,0 +1,105 @@
|
||||
import { SettingProvider } from "../../hooks/Setting";
|
||||
import ThemeProvider from "../../hooks/Theme";
|
||||
import DraggableResizable from "./DraggableResizable";
|
||||
import Header from "../Popup/Header";
|
||||
import Stack from "@mui/material/Stack";
|
||||
import TextField from "@mui/material/TextField";
|
||||
import MenuItem from "@mui/material/MenuItem";
|
||||
import Grid from "@mui/material/Grid";
|
||||
import Box from "@mui/material/Box";
|
||||
import Divider from "@mui/material/Divider";
|
||||
import { useI18n } from "../../hooks/I18n";
|
||||
import { OPT_TRANS_ALL, OPT_LANGS_FROM, OPT_LANGS_TO } from "../../config";
|
||||
|
||||
function TranForm({ tranboxSetting }) {
|
||||
const i18n = useI18n();
|
||||
|
||||
const {
|
||||
transOpen,
|
||||
translator,
|
||||
fromLang,
|
||||
toLang,
|
||||
tranboxShortcut,
|
||||
btnOffsetX,
|
||||
btnOffsetY,
|
||||
} = tranboxSetting;
|
||||
|
||||
return (
|
||||
<Stack sx={{ p: 2 }} spacing={2}>
|
||||
<Box>
|
||||
<Grid container spacing={2} columns={12}>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="fromLang"
|
||||
value={fromLang}
|
||||
label={i18n("from_lang")}
|
||||
// onChange={handleChange}
|
||||
>
|
||||
{OPT_LANGS_FROM.map(([lang, name]) => (
|
||||
<MenuItem key={lang} value={lang}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||
fullWidth
|
||||
size="small"
|
||||
name="toLang"
|
||||
value={toLang}
|
||||
label={i18n("to_lang")}
|
||||
// onChange={handleChange}
|
||||
>
|
||||
{OPT_LANGS_TO.map(([lang, name]) => (
|
||||
<MenuItem key={lang} value={lang}>
|
||||
{name}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
<Grid item xs={4} sm={4} md={4} lg={4}>
|
||||
<TextField
|
||||
select
|
||||
SelectProps={{ MenuProps: { disablePortal: true } }}
|
||||
fullWidth
|
||||
size="small"
|
||||
value={translator}
|
||||
name="translator"
|
||||
label={i18n("translate_service")}
|
||||
// onChange={handleChange}
|
||||
>
|
||||
{OPT_TRANS_ALL.map((item) => (
|
||||
<MenuItem key={item} value={item}>
|
||||
{item}
|
||||
</MenuItem>
|
||||
))}
|
||||
</TextField>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</Box>
|
||||
</Stack>
|
||||
);
|
||||
}
|
||||
|
||||
export default function TranBox({ position, setShowBox, tranboxSetting }) {
|
||||
return (
|
||||
<SettingProvider>
|
||||
<ThemeProvider>
|
||||
<DraggableResizable
|
||||
defaultPosition={position}
|
||||
header={<Header setShowPopup={setShowBox} />}
|
||||
>
|
||||
<Divider />
|
||||
<TranForm tranboxSetting={tranboxSetting} />
|
||||
</DraggableResizable>
|
||||
</ThemeProvider>
|
||||
</SettingProvider>
|
||||
);
|
||||
}
|
||||
43
src/views/Selection/Tranbtn.js
Normal file
43
src/views/Selection/Tranbtn.js
Normal file
@@ -0,0 +1,43 @@
|
||||
export default function TranBtn({ onClick, position, tranboxSetting }) {
|
||||
return (
|
||||
<div
|
||||
style={{
|
||||
cursor: "pointer",
|
||||
position: "fixed",
|
||||
left: position.x + tranboxSetting.btnOffsetX,
|
||||
top: position.y + tranboxSetting.btnOffsetY,
|
||||
}}
|
||||
onClick={onClick}
|
||||
onMouseUp={(e) => {
|
||||
e.stopPropagation();
|
||||
}}
|
||||
>
|
||||
<svg
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
width="24"
|
||||
height="24"
|
||||
viewBox="0 0 32 32"
|
||||
version="1.1"
|
||||
>
|
||||
<path
|
||||
d="M 0.455 1.257 C 0.173 1.991, 0.068 9.096, 0.221 17.046 L 0.500 31.500 15.365 31.777 C 25.475 31.966, 30.672 31.687, 31.615 30.905 C 32.681 30.020, 33 26.349, 33 14.967 L 33 0.180 16.984 0.050 C 4.455 -0.051, 0.856 0.212, 0.455 1.257 M 0.402 16 C 0.402 24.525, 0.556 28.013, 0.743 23.750 C 0.931 19.488, 0.931 12.513, 0.743 8.250 C 0.556 3.988, 0.402 7.475, 0.402 16 M 3 16 C 3 26.333, 3.121 27, 5 27 C 6.681 27, 7 26.333, 7 22.826 L 7 18.651 9.500 21 C 10.875 22.292, 12 24.170, 12 25.174 C 12 26.333, 12.730 27, 14 27 C 17.333 27, 16.670 21.670, 12.978 18.780 L 9.957 16.415 12.978 13.521 C 14.640 11.928, 16 10.004, 16 9.243 C 16 8.382, 16.848 7.981, 18.250 8.180 C 20.374 8.482, 20.516 9.020, 20.788 17.750 C 21.011 24.955, 21.390 27, 22.500 27 C 23.610 27, 23.989 24.955, 24.212 17.750 C 24.484 9.020, 24.626 8.482, 26.750 8.180 C 27.987 8.005, 29 7.217, 29 6.430 C 29 5.302, 27.205 5, 20.500 5 C 12.937 5, 12 5.201, 12 6.826 C 12 7.830, 10.875 9.708, 9.500 11 L 7 13.349 7 9.174 C 7 5.667, 6.681 5, 5 5 C 3.121 5, 3 5.667, 3 16"
|
||||
stroke="none"
|
||||
fill="#209cee"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M 4 16 C 4 22.667, 4.394 27, 5 27 C 5.550 27, 6 25.200, 6 23 C 6 20.345, 6.446 19, 7.326 19 C 9.199 19, 13 23.286, 13 25.398 C 13 26.371, 13.562 26.979, 14.250 26.750 C 16.713 25.930, 16.145 22.745, 12.946 19.444 L 9.705 16.100 12.852 12.515 C 14.584 10.544, 16 8.558, 16 8.104 C 16 7.649, 17.125 7.492, 18.500 7.755 C 20.957 8.225, 21 8.396, 21 17.700 C 21 24.828, 21.309 27.064, 22.250 26.752 C 23.100 26.471, 23.592 23.401, 23.788 17.169 C 24.049 8.823, 24.251 8, 26.038 8 C 27.140 8, 28 7.323, 28 6.456 C 28 5.179, 26.699 4.953, 20.500 5.151 C 14.356 5.347, 13 5.683, 13 7.008 C 13 8.949, 7.650 14.316, 6.681 13.347 C 6.306 12.973, 6 10.942, 6 8.833 C 6 6.725, 5.550 5, 5 5 C 4.394 5, 4 9.333, 4 16"
|
||||
stroke="none"
|
||||
fill="#f5f9fc"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
<path
|
||||
d="M 3.378 16 C 3.378 22.325, 3.541 24.912, 3.739 21.750 C 3.937 18.587, 3.937 13.412, 3.739 10.250 C 3.541 7.087, 3.378 9.675, 3.378 16 M 6.175 8.691 C 6.079 10.996, 6.381 13.118, 6.847 13.405 C 8.295 14.300, 13.227 8.362, 12.708 6.349 C 12.289 4.723, 12.218 4.750, 12.116 6.576 C 12.052 7.717, 10.903 9.682, 9.563 10.941 L 7.126 13.230 6.738 8.865 L 6.349 4.500 6.175 8.691 M 15.333 5.667 C 15.700 6.033, 16.300 6.033, 16.667 5.667 C 17.033 5.300, 16.733 5, 16 5 C 15.267 5, 14.967 5.300, 15.333 5.667 M 28.079 6.583 C 28.127 7.748, 28.364 7.985, 28.683 7.188 C 28.972 6.466, 28.936 5.603, 28.604 5.271 C 28.272 4.939, 28.036 5.529, 28.079 6.583 M 16 7.500 C 16 7.775, 16.225 8, 16.500 8 C 16.775 8, 17 7.775, 17 7.500 C 17 7.225, 16.775 7, 16.500 7 C 16.225 7, 16 7.225, 16 7.500 M 20 8.500 C 20 8.775, 20.225 9, 20.500 9 C 20.775 9, 21 8.775, 21 8.500 C 21 8.225, 20.775 8, 20.500 8 C 20.225 8, 20 8.225, 20 8.500 M 24 8.500 C 24 8.775, 24.225 9, 24.500 9 C 24.775 9, 25 8.775, 25 8.500 C 25 8.225, 24.775 8, 24.500 8 C 24.225 8, 24 8.225, 24 8.500 M 12.573 12.906 L 9.645 16.500 13.021 13.282 C 14.878 11.512, 16.196 9.895, 15.949 9.688 C 15.702 9.481, 14.183 10.929, 12.573 12.906 M 13.500 20 C 14.495 21.100, 15.535 22, 15.810 22 C 16.085 22, 15.495 21.100, 14.500 20 C 13.505 18.900, 12.465 18, 12.190 18 C 11.915 18, 12.505 18.900, 13.500 20 M 6.272 23 C 6.272 25.475, 6.467 26.488, 6.706 25.250 C 6.944 24.012, 6.944 21.988, 6.706 20.750 C 6.467 19.512, 6.272 20.525, 6.272 23 M 9.650 21 C 10.833 22.375, 12.018 24.400, 12.284 25.500 C 12.753 27.438, 12.772 27.436, 12.884 25.424 C 12.948 24.283, 11.762 22.258, 10.250 20.924 L 7.500 18.500 9.650 21 M 15 26.500 C 15 26.775, 15.225 27, 15.500 27 C 15.775 27, 16 26.775, 16 26.500 C 16 26.225, 15.775 26, 15.500 26 C 15.225 26, 15 26.225, 15 26.500 M 23 26.500 C 23 26.775, 23.225 27, 23.500 27 C 23.775 27, 24 26.775, 24 26.500 C 24 26.225, 23.775 26, 23.500 26 C 23.225 26, 23 26.225, 23 26.500"
|
||||
stroke="none"
|
||||
fill="#259cec"
|
||||
fillRule="evenodd"
|
||||
/>
|
||||
</svg>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
54
src/views/Selection/index.js
Normal file
54
src/views/Selection/index.js
Normal file
@@ -0,0 +1,54 @@
|
||||
import { useState, useEffect } from "react";
|
||||
import TranBtn from "./Tranbtn";
|
||||
import TranBox from "./Tranbox";
|
||||
|
||||
export default function Slection({ tranboxSetting }) {
|
||||
const [showBox, setShowBox] = useState(false);
|
||||
const [showBtn, setShowBtn] = useState(false);
|
||||
const [text, setText] = useState("");
|
||||
const [position, setPosition] = useState({ x: 0, y: 0 });
|
||||
|
||||
console.log("tranboxSetting", tranboxSetting);
|
||||
|
||||
function handleMouseup(e) {
|
||||
const text = window.getSelection()?.toString()?.trim() || "";
|
||||
setPosition({ x: e.clientX, y: e.clientY });
|
||||
setText(text);
|
||||
setShowBtn(!!text);
|
||||
}
|
||||
|
||||
const handleClick = (e) => {
|
||||
e.stopPropagation();
|
||||
setShowBtn(false);
|
||||
if (!!text) {
|
||||
setShowBox(true);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
window.addEventListener("mouseup", handleMouseup);
|
||||
return () => {
|
||||
window.removeEventListener("mouseup", handleMouseup);
|
||||
};
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<>
|
||||
{showBox && (
|
||||
<TranBox
|
||||
position={position}
|
||||
tranboxSetting={tranboxSetting}
|
||||
setShowBox={setShowBox}
|
||||
/>
|
||||
)}
|
||||
|
||||
{showBtn && (
|
||||
<TranBtn
|
||||
position={position}
|
||||
tranboxSetting={tranboxSetting}
|
||||
onClick={handleClick}
|
||||
/>
|
||||
)}
|
||||
</>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user