Compare commits

..

10 Commits

Author SHA1 Message Date
Gabe Yuan
c6f8a45027 v1.6.7 2023-09-04 23:28:41 +08:00
Gabe Yuan
6ec16e1f98 fix popup header 2023-09-04 23:24:50 +08:00
Gabe Yuan
40adf85b20 fix help link 2023-09-04 23:12:35 +08:00
Gabe Yuan
4c78f469c1 update readme 2023-09-04 23:08:00 +08:00
Gabe Yuan
55af58faac add rules help button 2023-09-04 22:29:39 +08:00
Gabe Yuan
4200caa641 fix popup header 2023-09-04 22:03:17 +08:00
Gabe Yuan
0ac06f8e3d use new rules link 2023-09-04 17:04:28 +08:00
Gabe Yuan
966c78fb16 optimize test link 2023-09-03 22:18:33 +08:00
Gabe Yuan
5c5a35d3bb v1.6.6 2023-09-03 21:47:38 +08:00
Gabe Yuan
2c24214f48 fix Violentmonkey --> .connect 2023-09-03 21:45:06 +08:00
19 changed files with 226 additions and 100 deletions

7
.env
View File

@@ -2,7 +2,7 @@ GENERATE_SOURCEMAP=false
REACT_APP_NAME=KISS Translator
REACT_APP_NAME_CN=简约翻译
REACT_APP_VERSION=1.6.5
REACT_APP_VERSION=1.6.7
REACT_APP_HOMEPAGE=https://github.com/fishjar/kiss-translator
@@ -13,8 +13,9 @@ REACT_APP_OPTIONSPAGE_DEV=http://localhost:3000/options.html
REACT_APP_LOGOURL=https://fishjar.github.io/kiss-translator/images/logo192.png
REACT_APP_LOGOURL2=https://kiss-translator.rayjar.com/images/logo192.png
REACT_APP_RULESURL=https://fishjar.github.io/kiss-translator/kiss-translator-rules.json
REACT_APP_RULESURL2=https://kiss-translator.rayjar.com/kiss-translator-rules.json
REACT_APP_RULESURL=https://fishjar.github.io/kiss-rules/kiss-rules.json
REACT_APP_RULESURL_ON=https://fishjar.github.io/kiss-rules/kiss-rules-on.json
REACT_APP_RULESURL_OFF=https://fishjar.github.io/kiss-rules/kiss-rules-off.json
REACT_APP_VERSIONFILE=https://fishjar.github.io/kiss-translator/version.txt
REACT_APP_VERSIONFILE2=https://kiss-translator.rayjar.com/version.txt

View File

@@ -18,7 +18,29 @@ If you also like a little more simplicity, welcome to pick it up.
- Keep it simple, smart
## Shortcut keys
## Associated ProjectS
- Data synchronization service: [https://github.com/fishjar/kiss-worker](https://github.com/fishjar/kiss-worker)
- Data synchronization service available for this project.
- You can also share your own private rule list.
- Deploy by yourself, manage by yourself, data is private.
- Community subscription rules: [https://github.com/fishjar/kiss-rules](https://github.com/fishjar/kiss-rules)
- Provides the latest and most complete list of subscription rules maintained by the community.
- Help with rules-related issues.
- Web page correction script: [https://github.com/fishjar/kiss-webfixer](https://github.com/fishjar/kiss-webfixer)
- Fixed scripts for some special sites.
- So that the translation software can get better display effect.
- Translation interface agent: [https://github.com/fishjar/kiss-proxy](https://github.com/fishjar/kiss-proxy)
- If you encounter network problems when accessing a certain translation interface, this proxy service may help you.
- Deploy and manage by yourself.
- Minimalistic Dictionary Plugin: [https://github.com/fishjar/kiss-dictionary](https://github.com/fishjar/kiss-dictionary)
- A word-marking translation plug-in used with this project.
- Supports query of English words, sentences and Chinese characters.
- Supports history records and word collections.
## Description
### Support shortcut keys
- `Alt+Q` Toggle Translation
- `Alt+C` Toggle Styles
@@ -60,10 +82,6 @@ yarn install
yarn build
```
## Data Sync
Goto: [https://github.com/fishjar/kiss-worker](https://github.com/fishjar/kiss-worker)
## Discussion
- Join [Telegram Group](https://t.me/+RRCu_4oNwrM2NmFl)

View File

@@ -18,7 +18,29 @@
- 保持简约
## 快捷键
## 关联项目
- 数据同步服务: [https://github.com/fishjar/kiss-worker](https://github.com/fishjar/kiss-worker)
- 可用于本项目的数据同步服务。
- 亦可用与分享个人的私有规则列表。
- 自己部署,自己管理,数据私有。
- 社区订阅规则: [https://github.com/fishjar/kiss-rules](https://github.com/fishjar/kiss-rules)
- 提供社区维护的,最新最全的订阅规则列表。
- 求助规则相关的问题。
- 网页修正脚本: [https://github.com/fishjar/kiss-webfixer](https://github.com/fishjar/kiss-webfixer)
- 针对一些特殊网站的修正脚本。
- 以便翻译软件得到更好的展示效果。
- 翻译接口代理: [https://github.com/fishjar/kiss-proxy](https://github.com/fishjar/kiss-proxy)
- 如果访问某个翻译接口遇到网络问题,这个代理服务也许可以帮你到你。
- 自己部署,自己管理。
- 简约词典插件: [https://github.com/fishjar/kiss-dictionary](https://github.com/fishjar/kiss-dictionary)
- 搭配本项目一起使用的划词翻译插件。
- 支持英文单词、句子、汉字的查询。
- 支持历史记录、单词收藏。
## 简要说明
### 支持快捷键
- `Alt+Q` 开启翻译
- `Alt+C` 切换样式
@@ -60,10 +82,6 @@ yarn install
yarn build
```
## 数据同步
移步: [https://github.com/fishjar/kiss-worker](https://github.com/fishjar/kiss-worker)
## 交流
- 加入 [Telegram 群](https://t.me/+RRCu_4oNwrM2NmFl)

View File

@@ -102,6 +102,7 @@ const userscriptWebpack = (config, env) => {
// @connect githubusercontent.com
// @connect kiss-translator.rayjar.com
// @connect ghproxy.com
// @connect localhost:3000
// @run-at document-end
// ==/UserScript==

View File

@@ -1,7 +1,7 @@
{
"name": "kiss-translator",
"description": "A minimalist bilingual translation Extension & Greasemonkey Script",
"version": "1.6.5",
"version": "1.6.7",
"author": "Gabe<yugang2002@gmail.com>",
"private": true,
"dependencies": {

View File

@@ -2,7 +2,7 @@
"manifest_version": 2,
"name": "__MSG_app_name__",
"description": "__MSG_app_description__",
"version": "1.6.5",
"version": "1.6.7",
"default_locale": "en",
"author": "Gabe<yugang2002@gmail.com>",
"homepage_url": "https://github.com/fishjar/kiss-translator",

View File

@@ -2,7 +2,7 @@
"manifest_version": 3,
"name": "__MSG_app_name__",
"description": "__MSG_app_description__",
"version": "1.6.5",
"version": "1.6.7",
"default_locale": "en",
"author": "Gabe<yugang2002@gmail.com>",
"homepage_url": "https://github.com/fishjar/kiss-translator",

View File

@@ -352,4 +352,12 @@ export const I18N = {
zh: `清除失败`,
en: `Clear failed`,
},
share: {
zh: `分享`,
en: `Share`,
},
help: {
zh: `求助`,
en: `Help`,
},
};

View File

@@ -58,6 +58,9 @@ export const THEME_DARK = "dark";
export const URL_KISS_WORKER = "https://github.com/fishjar/kiss-worker";
export const URL_KISS_PROXY = "https://github.com/fishjar/kiss-proxy";
export const URL_KISS_RULES = "https://github.com/fishjar/kiss-rules";
export const URL_KISS_RULES_NEW_ISSUE =
"https://github.com/fishjar/kiss-rules/issues/new";
export const URL_RAW_PREFIX =
"https://raw.githubusercontent.com/fishjar/kiss-translator/master";
export const URL_MICROSOFT_AUTH = "https://edge.microsoft.com/translate/auth";
@@ -183,10 +186,14 @@ export const GLOBLA_RULE = {
export const DEFAULT_SUBRULES_LIST = [
{
url: process.env.REACT_APP_RULESURL,
selected: false,
},
{
url: process.env.REACT_APP_RULESURL_ON,
selected: true,
},
{
url: process.env.REACT_APP_RULESURL2,
url: process.env.REACT_APP_RULESURL_OFF,
selected: false,
},
];

View File

@@ -177,7 +177,9 @@ const RULES = [
},
];
export const BUILTIN_RULES = RULES.map((item) => ({
export const BUILTIN_RULES = RULES.sort((a, b) =>
a.pattern.localeCompare(b.pattern)
).map((item) => ({
...DEFAULT_RULE,
...item,
transOpen: "true",

View File

@@ -83,7 +83,9 @@ const fetchApi = async ({ input, init = {}, translator, token }) => {
} else {
info = GM.info;
}
const connects = info?.script?.connects || [];
// Tampermonkey --> .connects
// Violentmonkey --> .connect
const connects = info?.script?.connects || info?.script?.connect || [];
const url = new URL(input);
const isSafe = connects.find((item) => url.hostname.endsWith(item));
if (isSafe) {

View File

@@ -1,18 +1,15 @@
import Paper from "@mui/material/Paper";
import Box from "@mui/material/Box";
import Fab from "@mui/material/Fab";
import TranslateIcon from "@mui/icons-material/Translate";
import ThemeProvider from "../../hooks/Theme";
import Draggable from "./Draggable";
import IconButton from "@mui/material/IconButton";
import CloseIcon from "@mui/icons-material/Close";
import Stack from "@mui/material/Stack";
import { useEffect, useState, useMemo, useCallback } from "react";
import { SettingProvider } from "../../hooks/Setting";
import Popup from "../Popup";
import { debounce } from "../../libs/utils";
import * as shortcut from "@violentmonkey/shortcut";
import { isGm } from "../../libs/client";
import Header from "../Popup/Header";
export default function Action({ translator, fab }) {
const fabWidth = 40;
@@ -161,23 +158,7 @@ export default function Action({ translator, fab }) {
onMove={handleMove}
handler={
<Paper style={{ cursor: "move" }} elevation={3}>
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
spacing={2}
>
<Box style={{ marginLeft: 16 }}>
{`${process.env.REACT_APP_NAME} v${process.env.REACT_APP_VERSION}`}
</Box>
<IconButton
onClick={() => {
setShowPopup(false);
}}
>
<CloseIcon />
</IconButton>
</Stack>
<Header setShowPopup={setShowPopup} />
</Paper>
}
>

View File

@@ -0,0 +1,13 @@
import IconButton from "@mui/material/IconButton";
import { useDarkMode } from "../../hooks/ColorMode";
import LightModeIcon from "@mui/icons-material/LightMode";
import DarkModeIcon from "@mui/icons-material/DarkMode";
export default function DarkModeButton() {
const { darkMode, toggleDarkMode } = useDarkMode();
return (
<IconButton onClick={toggleDarkMode} color="inherit">
{darkMode ? <LightModeIcon /> : <DarkModeIcon />}
</IconButton>
);
}

View File

@@ -4,16 +4,13 @@ import IconButton from "@mui/material/IconButton";
import MenuIcon from "@mui/icons-material/Menu";
import Toolbar from "@mui/material/Toolbar";
import Box from "@mui/material/Box";
import { useDarkMode } from "../../hooks/ColorMode";
import LightModeIcon from "@mui/icons-material/LightMode";
import DarkModeIcon from "@mui/icons-material/DarkMode";
import Link from "@mui/material/Link";
import { useI18n } from "../../hooks/I18n";
import DarkModeButton from "./DarkModeButton";
function Header(props) {
const i18n = useI18n();
const { onDrawerToggle } = props;
const { darkMode, toggleDarkMode } = useDarkMode();
return (
<AppBar
@@ -39,11 +36,10 @@ function Header(props) {
underline="none"
color="inherit"
href={process.env.REACT_APP_HOMEPAGE}
target="_blank"
>{`${i18n("app_name")} v${process.env.REACT_APP_VERSION}`}</Link>
</Box>
<IconButton onClick={toggleDarkMode} color="inherit">
{darkMode ? <LightModeIcon /> : <DarkModeIcon />}
</IconButton>
<DarkModeButton />
</Toolbar>
</AppBar>
);

View File

@@ -13,6 +13,7 @@ import {
OPT_STYLE_ALL,
OPT_STYLE_DIY,
OPT_STYLE_USE_COLOR,
URL_KISS_RULES_NEW_ISSUE,
} from "../../config";
import { useState, useRef, useEffect, useMemo } from "react";
import { useI18n } from "../../hooks/I18n";
@@ -35,6 +36,7 @@ import Radio from "@mui/material/Radio";
import RadioGroup from "@mui/material/RadioGroup";
import DeleteIcon from "@mui/icons-material/Delete";
import IconButton from "@mui/material/IconButton";
import HelpIcon from "@mui/icons-material/Help";
import ShareIcon from "@mui/icons-material/Share";
import SyncIcon from "@mui/icons-material/Sync";
import { useSubRules } from "../../hooks/SubRules";
@@ -470,7 +472,23 @@ function ShareButton({ rules, injectRules, selectedUrl }) {
onClick={handleClick}
startIcon={<ShareIcon />}
>
{"分享"}
{i18n("share")}
</Button>
);
}
function HelpButton() {
const i18n = useI18n();
return (
<Button
size="small"
variant="outlined"
onClick={() => {
window.open(URL_KISS_RULES_NEW_ISSUE, "_blank");
}}
startIcon={<HelpIcon />}
>
{i18n("help")}
</Button>
);
}
@@ -552,6 +570,8 @@ function UserRules({ subRules }) {
selectedUrl={selectedUrl}
/>
<HelpButton />
<FormControlLabel
control={
<Switch
@@ -715,6 +735,7 @@ function SubRulesEdit({ subList, addSub }) {
>
{i18n("add")}
</Button>
<HelpButton />
</Stack>
{showInput && (

View File

@@ -12,6 +12,7 @@ import { limitNumber } from "../../libs/utils";
import { useI18n } from "../../hooks/I18n";
import { apiTranslate } from "../../apis";
import { useAlert } from "../../hooks/Alert";
import CircularProgress from "@mui/material/CircularProgress";
import {
UI_LANGS,
URL_KISS_PROXY,
@@ -21,6 +22,43 @@ import {
OPT_TRANS_DEEPL,
OPT_TRANS_OPENAI,
} from "../../config";
import { useState } from "react";
function TestLink({ translator, setting }) {
const i18n = useI18n();
const alert = useAlert();
const [loading, setLoading] = useState(false);
const handleApiTest = async () => {
try {
setLoading(true);
const [text] = await apiTranslate({
translator,
q: "hello world",
fromLang: "en",
toLang: "zh-CN",
setting,
});
if (!text) {
throw new Error("empty reault");
}
alert.success(i18n("test_success"));
} catch (err) {
alert.error(`${i18n("test_failed")}: ${err.message}`);
} finally {
setLoading(false);
}
};
if (loading) {
return <CircularProgress sx={{ marginLeft: "2em" }} size={12} />;
}
return (
<Link sx={{ marginLeft: "1em" }} component="button" onClick={handleApiTest}>
{i18n("click_test")}
</Link>
);
}
export default function Settings() {
const i18n = useI18n();
@@ -62,24 +100,6 @@ export default function Settings() {
}
};
const handleApiTest = async (translator) => {
try {
const [text] = await apiTranslate({
translator,
q: "hello world",
fromLang: "en",
toLang: "zh-CN",
setting,
});
if (!text) {
throw new Error("empty reault");
}
alert.success(i18n("test_success"));
} catch (err) {
alert.error(`${i18n("test_failed")}: ${err.message}`);
}
};
const {
uiLang,
googleUrl,
@@ -185,15 +205,7 @@ export default function Settings() {
<>
{i18n("google_api")}
{googleUrl && (
<Link
sx={{ marginLeft: "1em" }}
component="button"
onClick={() => {
handleApiTest(OPT_TRANS_GOOGLE);
}}
>
{i18n("click_test")}
</Link>
<TestLink translator={OPT_TRANS_GOOGLE} setting={setting} />
)}
</>
}
@@ -201,7 +213,9 @@ export default function Settings() {
value={googleUrl}
onChange={handleChange}
helperText={
<Link href={URL_KISS_PROXY}>{i18n("about_api_proxy")}</Link>
<Link href={URL_KISS_PROXY} target="_blank">
{i18n("about_api_proxy")}
</Link>
}
/>
@@ -211,15 +225,7 @@ export default function Settings() {
<>
{i18n("deepl_api")}
{deeplUrl && (
<Link
sx={{ marginLeft: "1em" }}
component="button"
onClick={() => {
handleApiTest(OPT_TRANS_DEEPL);
}}
>
{i18n("click_test")}
</Link>
<TestLink translator={OPT_TRANS_DEEPL} setting={setting} />
)}
</>
}
@@ -242,15 +248,7 @@ export default function Settings() {
<>
{i18n("openai_api")}
{openaiUrl && openaiPrompt && (
<Link
sx={{ marginLeft: "1em" }}
component="button"
onClick={() => {
handleApiTest(OPT_TRANS_OPENAI);
}}
>
{i18n("click_test")}
</Link>
<TestLink translator={OPT_TRANS_OPENAI} setting={setting} />
)}
</>
}
@@ -258,7 +256,9 @@ export default function Settings() {
value={openaiUrl}
onChange={handleChange}
helperText={
<Link href={URL_KISS_PROXY}>{i18n("about_api_proxy")}</Link>
<Link href={URL_KISS_PROXY} target="_blank">
{i18n("about_api_proxy")}
</Link>
}
/>

View File

@@ -58,7 +58,9 @@ export default function SyncSetting() {
value={syncUrl}
onChange={handleChange}
helperText={
<Link href={URL_KISS_WORKER}>{i18n("about_sync_api")}</Link>
<Link href={URL_KISS_WORKER} target="_blank">
{i18n("about_sync_api")}
</Link>
}
/>

42
src/views/Popup/Header.js Normal file
View File

@@ -0,0 +1,42 @@
import Box from "@mui/material/Box";
import IconButton from "@mui/material/IconButton";
import CloseIcon from "@mui/icons-material/Close";
import HomeIcon from "@mui/icons-material/Home";
import Stack from "@mui/material/Stack";
import DarkModeButton from "../Options/DarkModeButton";
export default function Header({ setShowPopup }) {
const handleHomepage = () => {
window.open(process.env.REACT_APP_HOMEPAGE, "_blank");
};
return (
<Stack
direction="row"
justifyContent="space-between"
alignItems="center"
spacing={2}
>
<Stack direction="row" justifyContent="flex-start" alignItems="center">
<IconButton onClick={handleHomepage}>
<HomeIcon />
</IconButton>
<Box>
{`${process.env.REACT_APP_NAME} v${process.env.REACT_APP_VERSION}`}
</Box>
</Stack>
{setShowPopup ? (
<IconButton
onClick={() => {
setShowPopup(false);
}}
>
<CloseIcon />
</IconButton>
) : (
<DarkModeButton />
)}
</Stack>
);
}

View File

@@ -10,6 +10,8 @@ import { browser } from "../../libs/browser";
import { isExt } from "../../libs/client";
import { useI18n } from "../../hooks/I18n";
import TextField from "@mui/material/TextField";
import Divider from "@mui/material/Divider";
import Header from "./Header";
import {
MSG_TRANS_TOGGLE,
MSG_TRANS_GETRULE,
@@ -93,8 +95,14 @@ export default function Popup({ setShowPopup, translator: tran }) {
if (!rule) {
return (
<Box minWidth={300} sx={{ p: 2 }}>
<Stack spacing={3}>
<Box minWidth={300}>
{isExt && (
<>
<Header />
<Divider />
</>
)}
<Stack sx={{ p: 2 }} spacing={3}>
<Button variant="text" onClick={handleOpenSetting}>
{i18n("setting")}
</Button>
@@ -106,8 +114,14 @@ export default function Popup({ setShowPopup, translator: tran }) {
const { transOpen, translator, fromLang, toLang, textStyle, bgColor } = rule;
return (
<Box minWidth={300} sx={{ p: 2 }}>
<Stack spacing={2}>
<Box minWidth={300}>
{isExt && (
<>
<Header />
<Divider />
</>
)}
<Stack sx={{ p: 2 }} spacing={2}>
<Stack
direction="row"
justifyContent="space-between"