Merge remote-tracking branch 'origin/dev' into dev
This commit is contained in:
@@ -15,8 +15,7 @@ A simple, open source [bilingual translation extension & Greasemonkey script](ht
|
|||||||
- [x] Firefox
|
- [x] Firefox
|
||||||
- [x] Kiwi (Android)
|
- [x] Kiwi (Android)
|
||||||
- [x] Orion (iOS)
|
- [x] Orion (iOS)
|
||||||
- [ ] Safari
|
- [x] Safari
|
||||||
- [x] Safari (Mac)
|
|
||||||
- [x] Thunderbird
|
- [x] Thunderbird
|
||||||
- [x] Supports multiple translation services
|
- [x] Supports multiple translation services
|
||||||
- [x] Google/Microsoft
|
- [x] Google/Microsoft
|
||||||
@@ -59,8 +58,9 @@ A simple, open source [bilingual translation extension & Greasemonkey script](ht
|
|||||||
- [x] Orion (iOS)
|
- [x] Orion (iOS)
|
||||||
- [x] Edge [Installation address](https://microsoftedge.microsoft.com/addons/detail/%E7%AE%80%E7%BA%A6%E7%BF%BB%E8%AF%91/jemckldkclkinpjighnoilpbldbdmmlh?hl=zh-CN)
|
- [x] Edge [Installation address](https://microsoftedge.microsoft.com/addons/detail/%E7%AE%80%E7%BA%A6%E7%BF%BB%E8%AF%91/jemckldkclkinpjighnoilpbldbdmmlh?hl=zh-CN)
|
||||||
- [x] Firefox [Installation address](https://addons.mozilla.org/zh-CN/firefox/addon/kiss-translator/)
|
- [x] Firefox [Installation address](https://addons.mozilla.org/zh-CN/firefox/addon/kiss-translator/)
|
||||||
- [ ] Safari
|
- [x] Safari
|
||||||
- [x] Safari (Mac) Compiled by a third party, not verified, obtained by yourself: https://www.nodeloc.com/t/topic/54245
|
- [x] Safari (Mac)
|
||||||
|
- [x] Safari (iOS)
|
||||||
- [x] Thunderbird [Download address](https://github.com/fishjar/kiss-translator/releases)
|
- [x] Thunderbird [Download address](https://github.com/fishjar/kiss-translator/releases)
|
||||||
- [x] GreaseMonkey Script
|
- [x] GreaseMonkey Script
|
||||||
- [x] Chrome/Edge/Firefox ([Tampermonkey](https://www.tampermonkey.net/)/[Violentmonkey](https://violentmonkey.github.io/)) [Installation link](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)
|
- [x] Chrome/Edge/Firefox ([Tampermonkey](https://www.tampermonkey.net/)/[Violentmonkey](https://violentmonkey.github.io/)) [Installation link](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)
|
||||||
|
|||||||
@@ -15,8 +15,7 @@
|
|||||||
- [x] Firefox
|
- [x] Firefox
|
||||||
- [x] Kiwi (Android)
|
- [x] Kiwi (Android)
|
||||||
- [x] Orion (iOS)
|
- [x] Orion (iOS)
|
||||||
- [ ] Safari
|
- [x] Safari
|
||||||
- [x] Safari (Mac)
|
|
||||||
- [x] Thunderbird
|
- [x] Thunderbird
|
||||||
- [x] 支持多种翻译服务
|
- [x] 支持多种翻译服务
|
||||||
- [x] Google/Microsoft
|
- [x] Google/Microsoft
|
||||||
@@ -59,8 +58,9 @@
|
|||||||
- [x] Orion (iOS)
|
- [x] Orion (iOS)
|
||||||
- [x] Edge [安装地址](https://microsoftedge.microsoft.com/addons/detail/%E7%AE%80%E7%BA%A6%E7%BF%BB%E8%AF%91/jemckldkclkinpjighnoilpbldbdmmlh?hl=zh-CN)
|
- [x] Edge [安装地址](https://microsoftedge.microsoft.com/addons/detail/%E7%AE%80%E7%BA%A6%E7%BF%BB%E8%AF%91/jemckldkclkinpjighnoilpbldbdmmlh?hl=zh-CN)
|
||||||
- [x] Firefox [安装地址](https://addons.mozilla.org/zh-CN/firefox/addon/kiss-translator/)
|
- [x] Firefox [安装地址](https://addons.mozilla.org/zh-CN/firefox/addon/kiss-translator/)
|
||||||
- [ ] Safari
|
- [x] Safari
|
||||||
- [x] Safari (Mac) 第三方编译,未作验证,自行获取: https://www.nodeloc.com/t/topic/54245
|
- [x] Safari (Mac)
|
||||||
|
- [x] Safari (iOS)
|
||||||
- [x] Thunderbird [下载地址](https://github.com/fishjar/kiss-translator/releases)
|
- [x] Thunderbird [下载地址](https://github.com/fishjar/kiss-translator/releases)
|
||||||
- [x] 油猴脚本
|
- [x] 油猴脚本
|
||||||
- [x] Chrome/Edge/Firefox ([Tampermonkey](https://www.tampermonkey.net/)/[Violentmonkey](https://violentmonkey.github.io/)) [安装链接](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)
|
- [x] Chrome/Edge/Firefox ([Tampermonkey](https://www.tampermonkey.net/)/[Violentmonkey](https://violentmonkey.github.io/)) [安装链接](https://fishjar.github.io/kiss-translator/kiss-translator.user.js)
|
||||||
|
|||||||
@@ -862,7 +862,21 @@ export const I18N = {
|
|||||||
en: `Hide Fab Button`,
|
en: `Hide Fab Button`,
|
||||||
zh_TW: `隱藏懸浮按鈕`,
|
zh_TW: `隱藏懸浮按鈕`,
|
||||||
},
|
},
|
||||||
|
fab_click_action: {
|
||||||
|
zh: `单击悬浮按钮动作`,
|
||||||
|
en: `Single Click Fab Action`,
|
||||||
|
zh_TW: `單擊懸浮按钮動作`,
|
||||||
|
},
|
||||||
|
fab_click_menu: {
|
||||||
|
zh: `弹出菜单`,
|
||||||
|
en: `Popup Menu`,
|
||||||
|
zh_TW: `彈出選單`,
|
||||||
|
},
|
||||||
|
fab_click_translate: {
|
||||||
|
zh: `直接翻译`,
|
||||||
|
en: `Translate`,
|
||||||
|
zh_TW: `直接翻譯`,
|
||||||
|
},
|
||||||
hide_tran_button: {
|
hide_tran_button: {
|
||||||
zh: `隐藏翻译按钮`,
|
zh: `隐藏翻译按钮`,
|
||||||
en: `Hide Translate Button`,
|
en: `Hide Translate Button`,
|
||||||
|
|||||||
@@ -33,6 +33,7 @@ export const DEFAULT_CSPLIST = ["https://github.com"]; // 禁用CSP名单
|
|||||||
// 同步设置
|
// 同步设置
|
||||||
export const OPT_SYNCTYPE_WORKER = "KISS-Worker";
|
export const OPT_SYNCTYPE_WORKER = "KISS-Worker";
|
||||||
export const OPT_SYNCTYPE_WEBDAV = "WebDAV";
|
export const OPT_SYNCTYPE_WEBDAV = "WebDAV";
|
||||||
|
export const OPT_SYNCTOKEN_PERFIX = "kt_";
|
||||||
export const OPT_SYNCTYPE_ALL = [OPT_SYNCTYPE_WORKER, OPT_SYNCTYPE_WEBDAV];
|
export const OPT_SYNCTYPE_ALL = [OPT_SYNCTYPE_WORKER, OPT_SYNCTYPE_WEBDAV];
|
||||||
export const DEFAULT_SYNC = {
|
export const DEFAULT_SYNC = {
|
||||||
syncType: OPT_SYNCTYPE_WORKER, // 同步方式
|
syncType: OPT_SYNCTYPE_WORKER, // 同步方式
|
||||||
@@ -125,6 +126,7 @@ export const DEFAULT_SETTING = {
|
|||||||
httpTimeout: DEFAULT_HTTP_TIMEOUT,
|
httpTimeout: DEFAULT_HTTP_TIMEOUT,
|
||||||
clearCache: false, // 是否在浏览器下次启动时清除缓存
|
clearCache: false, // 是否在浏览器下次启动时清除缓存
|
||||||
injectRules: true, // 是否注入订阅规则
|
injectRules: true, // 是否注入订阅规则
|
||||||
|
fabClickAction: 0, // 悬浮按钮点击行为
|
||||||
// injectWebfix: true, // 是否注入修复补丁(作废)
|
// injectWebfix: true, // 是否注入修复补丁(作废)
|
||||||
// detectRemote: false, // 是否使用远程语言检测(移至rule,作废)
|
// detectRemote: false, // 是否使用远程语言检测(移至rule,作废)
|
||||||
// contextMenus: true, // 是否添加右键菜单(作废)
|
// contextMenus: true, // 是否添加右键菜单(作废)
|
||||||
|
|||||||
@@ -33,6 +33,8 @@ export default function Action({ translator, fab }) {
|
|||||||
});
|
});
|
||||||
const [moved, setMoved] = useState(false);
|
const [moved, setMoved] = useState(false);
|
||||||
|
|
||||||
|
const { fabClickAction = 0 } = fab || {};
|
||||||
|
|
||||||
const handleWindowResize = useMemo(
|
const handleWindowResize = useMemo(
|
||||||
() =>
|
() =>
|
||||||
debounce(() => {
|
debounce(() => {
|
||||||
@@ -215,7 +217,14 @@ export default function Action({ translator, fab }) {
|
|||||||
color="primary"
|
color="primary"
|
||||||
onClick={(e) => {
|
onClick={(e) => {
|
||||||
if (!moved) {
|
if (!moved) {
|
||||||
setShowPopup((pre) => !pre);
|
if (fabClickAction === 1) {
|
||||||
|
translator.toggle();
|
||||||
|
sendIframeMsg(MSG_TRANS_TOGGLE);
|
||||||
|
setShowPopup(false);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
setShowPopup((pre) => !pre);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
|
|||||||
@@ -122,7 +122,7 @@ export default function Settings() {
|
|||||||
transInterval = 200,
|
transInterval = 200,
|
||||||
langDetector = OPT_TRANS_MICROSOFT,
|
langDetector = OPT_TRANS_MICROSOFT,
|
||||||
} = setting;
|
} = setting;
|
||||||
const { isHide = false } = fab || {};
|
const { isHide = false, fabClickAction = 0 } = fab || {};
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<Box>
|
<Box>
|
||||||
@@ -232,6 +232,19 @@ export default function Settings() {
|
|||||||
</Select>
|
</Select>
|
||||||
</FormControl>
|
</FormControl>
|
||||||
|
|
||||||
|
<FormControl size="small">
|
||||||
|
<InputLabel>{i18n("fab_click_action")}</InputLabel>
|
||||||
|
<Select
|
||||||
|
name="fabClickAction"
|
||||||
|
value={fabClickAction}
|
||||||
|
label={i18n("fab_click_action")}
|
||||||
|
onChange= {(e) => updateFab({ fabClickAction: e.target.value })}
|
||||||
|
>
|
||||||
|
<MenuItem value={0}>{i18n("fab_click_menu")}</MenuItem>
|
||||||
|
<MenuItem value={1}>{i18n("fab_click_translate")}</MenuItem>
|
||||||
|
</Select>
|
||||||
|
</FormControl>
|
||||||
|
|
||||||
<FormControl size="small">
|
<FormControl size="small">
|
||||||
<InputLabel>{i18n("context_menus")}</InputLabel>
|
<InputLabel>{i18n("context_menus")}</InputLabel>
|
||||||
<Select
|
<Select
|
||||||
|
|||||||
@@ -7,18 +7,22 @@ import Alert from "@mui/material/Alert";
|
|||||||
import Link from "@mui/material/Link";
|
import Link from "@mui/material/Link";
|
||||||
import MenuItem from "@mui/material/MenuItem";
|
import MenuItem from "@mui/material/MenuItem";
|
||||||
import LoadingButton from "@mui/lab/LoadingButton";
|
import LoadingButton from "@mui/lab/LoadingButton";
|
||||||
|
import Button from "@mui/material/Button";
|
||||||
import {
|
import {
|
||||||
URL_KISS_WORKER,
|
URL_KISS_WORKER,
|
||||||
OPT_SYNCTYPE_ALL,
|
OPT_SYNCTYPE_ALL,
|
||||||
OPT_SYNCTYPE_WORKER,
|
OPT_SYNCTYPE_WORKER,
|
||||||
OPT_SYNCTYPE_WEBDAV,
|
OPT_SYNCTYPE_WEBDAV,
|
||||||
|
OPT_SYNCTOKEN_PERFIX,
|
||||||
} from "../../config";
|
} from "../../config";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { syncSettingAndRules } from "../../libs/sync";
|
import { syncSettingAndRules } from "../../libs/sync";
|
||||||
import { useAlert } from "../../hooks/Alert";
|
import { useAlert } from "../../hooks/Alert";
|
||||||
import SyncIcon from "@mui/icons-material/Sync";
|
|
||||||
import { useSetting } from "../../hooks/Setting";
|
import { useSetting } from "../../hooks/Setting";
|
||||||
import { kissLog } from "../../libs/log";
|
import { kissLog } from "../../libs/log";
|
||||||
|
import SyncIcon from "@mui/icons-material/Sync";
|
||||||
|
import ContentCopyIcon from '@mui/icons-material/ContentCopy';
|
||||||
|
import ContentPasteIcon from '@mui/icons-material/ContentPaste';
|
||||||
|
|
||||||
export default function SyncSetting() {
|
export default function SyncSetting() {
|
||||||
const i18n = useI18n();
|
const i18n = useI18n();
|
||||||
@@ -50,6 +54,57 @@ export default function SyncSetting() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const handleGenerateShareString = async () => {
|
||||||
|
try {
|
||||||
|
const base64Config = btoa(JSON.stringify({
|
||||||
|
syncType: syncType,
|
||||||
|
syncUrl: syncUrl,
|
||||||
|
syncUser: syncUser,
|
||||||
|
syncKey: syncKey,
|
||||||
|
}));
|
||||||
|
const shareString = `${OPT_SYNCTOKEN_PERFIX}${base64Config}`;
|
||||||
|
await navigator.clipboard.writeText(shareString);
|
||||||
|
console.debug("Share string copied to clipboard", shareString);
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to copy share string to clipboard", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
const handleImportFromClipboard = async () => {
|
||||||
|
try {
|
||||||
|
const text = await navigator.clipboard.readText();
|
||||||
|
console.debug('read_clipboard', text)
|
||||||
|
if (text.startsWith(OPT_SYNCTOKEN_PERFIX)) {
|
||||||
|
const base64Config = text.slice(OPT_SYNCTOKEN_PERFIX.length);
|
||||||
|
const jsonString = atob(base64Config);
|
||||||
|
const updatedConfig = JSON.parse(jsonString);
|
||||||
|
|
||||||
|
if (!OPT_SYNCTYPE_ALL.includes(updatedConfig.syncType)) {
|
||||||
|
console.error('error syncType', updatedConfig.syncType)
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (
|
||||||
|
updatedConfig.syncUrl
|
||||||
|
) {
|
||||||
|
updateSync({
|
||||||
|
syncType: updatedConfig.syncType,
|
||||||
|
syncUrl: updatedConfig.syncUrl,
|
||||||
|
syncUser: updatedConfig.syncUser,
|
||||||
|
syncKey: updatedConfig.syncKey,
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
console.error("Invalid config structure");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
console.error("Invalid share string", text);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Failed to read from clipboard or parse JSON", error);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
if (!sync) {
|
if (!sync) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -133,6 +188,22 @@ export default function SyncSetting() {
|
|||||||
>
|
>
|
||||||
{i18n("sync_now")}
|
{i18n("sync_now")}
|
||||||
</LoadingButton>
|
</LoadingButton>
|
||||||
|
<Button
|
||||||
|
size="small"
|
||||||
|
variant="contained"
|
||||||
|
onClick={handleGenerateShareString}
|
||||||
|
startIcon={<ContentCopyIcon />}
|
||||||
|
>
|
||||||
|
{i18n("copy", "copy")}
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
onClick={handleImportFromClipboard}
|
||||||
|
size="small"
|
||||||
|
variant="contained"
|
||||||
|
startIcon={<ContentPasteIcon />}
|
||||||
|
>
|
||||||
|
{i18n("import", "import")}
|
||||||
|
</Button>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Stack>
|
</Stack>
|
||||||
</Box>
|
</Box>
|
||||||
|
|||||||
Reference in New Issue
Block a user