parent
cb1da01788
commit
855fbf1b96
@ -1,3 +1,6 @@ |
||||
node_modules |
||||
dist/ |
||||
*.log |
||||
*.log |
||||
.env |
||||
deploy |
||||
.idea |
File diff suppressed because it is too large
Load Diff
@ -1,50 +1,164 @@ |
||||
import { Text, Window, hot, View } from "@nodegui/react-nodegui"; |
||||
import {Button, ComboBox, hot, PlainTextEdit, Text, View, Window} from "@nodegui/react-nodegui"; |
||||
import React from "react"; |
||||
import { QIcon } from "@nodegui/nodegui"; |
||||
import { StepOne } from "./components/stepone"; |
||||
import { StepTwo } from "./components/steptwo"; |
||||
import {AlignmentFlag, QIcon} from "@nodegui/nodegui"; |
||||
import nodeguiIcon from "../assets/nodegui.jpg"; |
||||
import {RNComboBox} from "@nodegui/react-nodegui/dist/components/ComboBox/RNComboBox"; |
||||
import {RNText} from "@nodegui/react-nodegui/dist/components/Text/RNText"; |
||||
import tencentTmt from "./tencent"; |
||||
import {RNPlainTextEdit} from "@nodegui/react-nodegui/dist/components/PlainTextEdit/RNPlainTextEdit"; |
||||
import baiduTranslate from "./baidu" |
||||
import Translate from "./components/Translate"; |
||||
|
||||
const minSize = { width: 500, height: 520 }; |
||||
const winIcon = new QIcon(nodeguiIcon); |
||||
class App extends React.Component { |
||||
render() { |
||||
return ( |
||||
<Window |
||||
windowIcon={winIcon} |
||||
windowTitle="Hello 👋🏽" |
||||
minSize={minSize} |
||||
styleSheet={styleSheet} |
||||
> |
||||
<View style={containerStyle}> |
||||
<Text id="welcome-text">Welcome to NodeGui 🐕</Text> |
||||
<Text id="step-1">1. Play around</Text> |
||||
<StepOne /> |
||||
<Text id="step-2">2. Debug</Text> |
||||
<StepTwo /> |
||||
</View> |
||||
</Window> |
||||
); |
||||
} |
||||
} |
||||
class App extends React.Component<any, any> { |
||||
private getComboBoxHandler: (key: ("sourceIndex" | "targetIndex")) => (index: number) => void; |
||||
private sourceLang: Array<{text:string,lang:string}>; |
||||
private lang: { [key: string]: string }; |
||||
private sourceRef: React.RefObject<RNComboBox>; |
||||
private targetRef:React.RefObject<RNComboBox>; |
||||
private labelRef: React.RefObject<RNText>; |
||||
private sourceTextRef: React.RefObject<RNPlainTextEdit>; |
||||
private tencentTextRef: React.RefObject<RNPlainTextEdit>; |
||||
private baiduTextRef: React.RefObject<RNPlainTextEdit>; |
||||
|
||||
constructor(props: any) { |
||||
super(props); |
||||
this.state = { |
||||
additionalButtons: [], |
||||
size: {height: 300, width: 900}, |
||||
allow:false, |
||||
} |
||||
this.sourceRef=React.createRef<RNComboBox>() |
||||
this.targetRef=React.createRef<RNComboBox>() |
||||
this.labelRef=React.createRef<RNText>() |
||||
this.sourceTextRef=React.createRef<RNPlainTextEdit>() |
||||
this.tencentTextRef=React.createRef<RNPlainTextEdit>() |
||||
this.baiduTextRef=React.createRef<RNPlainTextEdit>() |
||||
this.getComboBoxHandler = (key: 'sourceIndex' | 'targetIndex') => { |
||||
return (index: number) => { |
||||
let ref |
||||
if(key==='sourceIndex'){ |
||||
ref=this.targetRef |
||||
}else{ |
||||
ref=this.sourceRef |
||||
} |
||||
if (ref.current?.currentIndex() === index) { |
||||
for(let langIndex in this.sourceLang){ |
||||
if(+langIndex!==index){ |
||||
ref.current?.setCurrentIndex(+langIndex) |
||||
break |
||||
} |
||||
} |
||||
} |
||||
|
||||
// console.debug(`${key}选中${this.sourceLang[index].text}`)
|
||||
} |
||||
} |
||||
this.lang = { |
||||
'en': '英语', |
||||
'zh': '中文' |
||||
} |
||||
this.sourceLang = [] |
||||
|
||||
|
||||
for (let key in this.lang) { |
||||
this.sourceLang.push({text: this.lang[key],lang:key}) |
||||
} |
||||
} |
||||
|
||||
componentDidMount() { |
||||
this.labelRef.current?.setAlignment(AlignmentFlag.AlignCenter) |
||||
} |
||||
|
||||
render() { |
||||
|
||||
const winIcon = new QIcon(nodeguiIcon); |
||||
|
||||
const comboHandler = { |
||||
currentIndexChanged: this.getComboBoxHandler("sourceIndex"), |
||||
} |
||||
const targetComboHandler = { |
||||
currentIndexChanged: this.getComboBoxHandler("targetIndex") |
||||
} |
||||
|
||||
const sourceHandler={ |
||||
textChanged:()=>{ |
||||
let flag=(this.sourceTextRef.current?.toPlainText().length||0)>0 |
||||
this.setState({allow:flag}) |
||||
} |
||||
} |
||||
|
||||
const translateHandler={ |
||||
clicked:()=>{ |
||||
let source=this.sourceTextRef.current?.toPlainText()||'' |
||||
let target=this.sourceLang[this.targetRef.current?.currentIndex()||0].lang |
||||
tencentTmt(source,target) |
||||
.then(res=>{ |
||||
console.info(res); |
||||
this.tencentTextRef.current?.setPlainText(res.TargetText) |
||||
}).catch(err=>console.error("error", err)) |
||||
|
||||
const containerStyle = ` |
||||
flex: 1;
|
||||
`;
|
||||
baiduTranslate(source,target).then((res: { text: () => any; })=>res.text()).then((res: string)=>{ |
||||
console.info(res) |
||||
let r=JSON.parse(res) |
||||
this.baiduTextRef.current?.setPlainText(r["trans_result"][0]["dst"]) |
||||
}).catch((err: any)=>console.error("error", err)) |
||||
} |
||||
} |
||||
|
||||
return ( |
||||
<Window styleSheet={styleSheet} |
||||
windowIcon={winIcon} size={this.state.size}> |
||||
<View id="rootView"> |
||||
<View style={`flex-direction:row`}> |
||||
<ComboBox style={`flex:1;`} items={this.sourceLang.concat({lang:'auto',text:'自动'})} currentIndex={0} |
||||
on={comboHandler} ref={this.sourceRef}></ComboBox> |
||||
<ComboBox style={`flex:1;`} items={this.sourceLang} currentIndex={1} |
||||
on={targetComboHandler} ref={this.targetRef}></ComboBox> |
||||
</View> |
||||
<View style={`flex-direction:row;flex:1;`}> |
||||
|
||||
<View style={`flex-direction:column;flex:1;`}> |
||||
<PlainTextEdit placeholderText='请输入原文' |
||||
ref={this.sourceTextRef} |
||||
on={sourceHandler} |
||||
style={`flex:9`} |
||||
></PlainTextEdit> |
||||
<Text id="tencent" style={`flex:1`} ref={this.labelRef}></Text> |
||||
</View> |
||||
|
||||
|
||||
<Translate targetTextRef={this.tencentTextRef} name={"腾讯翻译"} href={"https://cloud.tencent.com/product/tmt"}/> |
||||
<Translate targetTextRef={this.baiduTextRef} name={"百度翻译"} href={"https://api.fanyi.baidu.com/"}/> |
||||
|
||||
</View> |
||||
<View style={`align-items:'center';padding:5px`}> |
||||
<Button enabled={this.state.allow} text="翻译" on={translateHandler}></Button> |
||||
</View> |
||||
</View> |
||||
</Window> |
||||
); |
||||
} |
||||
} |
||||
|
||||
const styleSheet = ` |
||||
#welcome-text { |
||||
font-size: 24px; |
||||
padding-top: 20px; |
||||
qproperty-alignment: 'AlignHCenter'; |
||||
font-family: 'sans-serif'; |
||||
} |
||||
|
||||
#step-1, #step-2 { |
||||
font-size: 18px; |
||||
padding-top: 10px; |
||||
padding-horizontal: 20px; |
||||
} |
||||
`;
|
||||
#rootView{ |
||||
height: '100%'; |
||||
flex-direction:'column'; |
||||
} |
||||
|
||||
QPushButton{ |
||||
width:300; |
||||
color:red; |
||||
font-size:20px; |
||||
background-color:gray; |
||||
border-radius:10px; |
||||
} |
||||
QPushButton:pressed{ |
||||
background-color:gray; |
||||
} |
||||
QPushButton:enabled{
|
||||
background-color: white; |
||||
} |
||||
` |
||||
|
||||
export default hot(App); |
||||
|
@ -0,0 +1,12 @@ |
||||
const fetch = require("node-fetch"); |
||||
const MD5 = require('md5.js'); |
||||
|
||||
function md5(message:string){ |
||||
return new MD5().update(message).digest('hex') |
||||
} |
||||
|
||||
export default async function baiduTranslate(q:string,to:string){ |
||||
let salt=Math.round(Math.random()*new Date().getTime()) |
||||
let sign=md5(process.env.REACT_APP_BAIDU_APP_ID+q+salt+process.env.REACT_APP_BAIDU_SECRET_KEY) |
||||
return fetch.default(`http://api.fanyi.baidu.com/api/trans/vip/translate?q=${q}&from=auto&to=${to}&appid=${process.env.REACT_APP_BAIDU_APP_ID}&salt=${salt}&sign=${sign}`) |
||||
} |
@ -0,0 +1,20 @@ |
||||
import {PlainTextEdit, Text, View} from "@nodegui/react-nodegui"; |
||||
import React, {useEffect, useRef} from "react"; |
||||
import {RNPlainTextEdit} from "@nodegui/react-nodegui/dist/components/PlainTextEdit/RNPlainTextEdit"; |
||||
import {RNText} from "@nodegui/react-nodegui/dist/components/Text/RNText"; |
||||
import {AlignmentFlag} from "@nodegui/nodegui"; |
||||
|
||||
export default function Translate(props: {targetTextRef:React.RefObject<RNPlainTextEdit>,name:string,href:string}){ |
||||
|
||||
const labelRef=useRef<RNText>() |
||||
|
||||
useEffect(() => { |
||||
labelRef.current?.setAlignment(AlignmentFlag.AlignCenter) |
||||
}); |
||||
|
||||
return <View style={`flex-direction:column;flex:1;`}> |
||||
<PlainTextEdit style={`flex:9`} readOnly={true} ref={props.targetTextRef}></PlainTextEdit> |
||||
<Text openExternalLinks={true} ref={labelRef} style={`flex:1;text-align:center;`} on={{ |
||||
}}>{"<a href=\""+props.href+"\">"+props.name}</Text> |
||||
</View> |
||||
} |
@ -1,30 +0,0 @@ |
||||
module.exports = `data:image/png;base64,
|
||||
iVBORw0KGgoAAAANSUhEUgAAADIAAAAzCAMAAADivasmAAACglBMVEUAAABPPz9RQj9QQUBPPj5PPz5TRENQQEBTQUFRQUFRQUFTQ0J |
||||
RQUFQQEBkWFdXSkpVSUhTQEFRQUFUQUFQQUBQQEBOPj1QQD9WQkVdUE5RRERZTEtWRkdRQUFQQEBQQEBSQUJRQUFRQEBURUVQQEBPPT |
||||
1aRUVOPT1VRkZPQUBRQEBRQUBSQUFPQEBTQUFSQ0NRQEFQQkFUPkFUQkNOPz5RPj9SP0BTRERVRUVUQEFWRUX///+jnpz+//6lnpykn
|
||||
pz9/f2inpyinZv9/v2kn538+/v///6inpv7+vmknZv+/v/+/f22s7KnoJ6Xj4+ln51SQkJVP0ClnZtTQEK0sa6koJ38/Pr19fTT0c+m
|
||||
oJ6Gfn3w7u6wrKuhm5lOQkBSPj/l5OLBv72sp6Wmo6CdlpSblJL6f4f3gIRRQD9NQD78/fv5+fbz8/Lr6enf3dzFw8G/u7qkm5qgmJa |
||||
MhoV6cnF/T1D8/f3y8vLt7Ovh4N/a2NjLx8bIxsWuqaeknp+nn52akZCTi4mRiIePhoV/eXjKcnh5bWxrYmFpYF9gVVVdUVJYSklMPT |
||||
v49/jl5OTd29nOy8rMycjHxsS8uLaopKShmZf2goiLg4KIfn2DeXh5cG9yaGdvZmVoXV1cTU9VR0dLPzry8O/p6Ofm5ubZ1tbW1NLS0 |
||||
tHRzszDwb+6trS1srD4gomEfXt1a2q0ZWpsZWT29/Xo5ePV0tO7ubicl5iYkpKVjY3ofofde4KMgYHNc3qtZmuRWFhZTUxPQ0RbQEG1 |
||||
sLGyrq6qqqr4gYbzhYXpfYXxhISJfHx+dHPDbnO/bnOAcnK+bHG5a3B0bGy2ZWqgZGicWVxlXFqWXFlyUE9KQ0GhVcLgAAAAO3RSTlM |
||||
AB9CjBc/izbaqZzInDf759e7DbmtGGxYR+fj29cm5rpaNXT07A/3669mdkoV7elJPLSHz6d3UfV9UML/w/okAAAWkSURBVEjHhZZlVx |
||||
tBFIaXUqAtdXd3d8vszmp2kwBpQkJKDCkUd0pb3IpTijvU3d3dXf9PZzbaNpy+n/acO8+ZK+/chHBq8taoLZOWEENp/YiGCfOnE96a1 |
||||
1cK4y9NnOYbWLJgbFlWdvcE7/D6aiNDUdqLgaN9EWNG9tmgFlJvVhIejSgHkRl7AF8euOhfYurEXIZlY4p4/bLhhFsBYfA8d6AIsKWz |
||||
tv9NLArsAiLVRO8Gobu8kGFhqhAFmWoQqezabcP/IKaMKwOqPdEaNUb8/kTUCkVKDOCz+uYFL1w9NyggIGji/FHBawbieWC1cErSJ0J |
||||
y0hGWonIH+7orwuLjS8vNVY/62wE4Z9JofCIKJGVEPqVS6bUqIIsvofR6NkNCkSERWkqPpbCgg4EQaItPN9LkkAh9IITVeiMMw7AQxh |
||||
6klT4RkpRORQJfgmzGVR8IG0JLLSLwKR6KBhN3mvkHkWJYMJQgtJr+RuJhSAEKoSJUFAUckmtyVAUBb2iGoYNjvAwTB5HDcJCNDImJs |
||||
TIOiI3NjGltc14eCUMHFruJ4cvaoXzKGJt/lVMqNZYCxIut1yRSyUnR50Un1O9B/HaFyveLISaOIxUKNak53sacitCQaCAcLRU623Bp |
||||
oRtZ3M8DrKJUdMYh8ng+7frWSJlGXBBzcZUbmZQLZEXTCrdIr0/StEdGbs91IyNzRJzWuQhSofYc9bBk8hmMAP3MMa5SJthkd6RzKCp |
||||
o8jgPRguCgJlUESFU6JV1rldUIxtlTwqnIKXMysp8wUVwaW1XbqZqUGqZGKE6/d15AawMDacQCjMK7HXHSLUDicg5lpPIRqCvJhnJmu |
||||
1YTBvHsRRuYboSpdU2UBueeNJ1i+lRTZKuBzdlPyuPoWeNjCzo5jHCpqKc8zISdbp6iwsRzFE63U2McFaMiPEr8GYYPd4GMGJNxu0Ur |
||||
N97rgvu6k/k1N2yYCSvQEb4S6PwDuviIUYKOXxILUg0zSmUSGq1mkSjp+WRcgdle1Jxy8cQC/uLKWxeMZ1WDC3cZoeju/2JQHOkFiPs |
||||
ftITpzlSo9HQ3mbgrPLsjKV2InhOrh6iPA0aT1x54JzBYHgacpL0Qo7gJ1TSuXwKmn1ANQ+Y4utqD6Ix66KiUK/CD3vdk8aiVO5tmib |
||||
vcDMDQPF+hUf0xXAkXXiSl09JwYBqiZuNXRY8I4sBtsI8TxJqrqkWM3aD4IXQuGclH9aiFxlUoaLgs0YXoUy2SHmk5UZvfVFThJo7Jr |
||||
mpiLNQD22zRhOTe1V6isqU3EiavVBADr5Vm5JMk8cftwhuZDdaHvy9EcSksXF4k2SaXMyBpGKENH7edQ25tDmx2YmQEmoZ1LJVIwli1 |
||||
LhyLaofbVGalMs0DzZLJmuiPceSnF5dt9/Z47QQBhHxY1f5YZMFvAUQjf9Gmpy2cLhmV/3jcN0T+6+BpMEznEyYWkQegpKKpTucO8m/ |
||||
JptisAEcDUs/+vPh+wf77n/bl9jq2B/CcxSm9D1zNhJO4eSMenBK40ji8NFDLxK+7HvZcUcXo3Q6OhKC0rELvH8T59exVKRrcCca7if |
||||
svbyv48Ir3Vm1YyaWIhHkziG8FVSm5QF/JCUZp45uwciFvXdkhKalfLSU+PZZU72RwM4SlK0q9mQjbrMLuRtVgBITDhoYgJCw+g3eyN |
||||
QVlUZeXjMt0SkpV3683nvoQcfeT1HREWlnYkXAMCqqc8IU4g/5jazOptALQn1Rnb8d9bEjISHh7tKqViMAPH6N2b0TdxJ/a/J4M4WjE |
||||
DJ8r/3hu0Nfn9S2Q4AlZnWNn+zrb9QG/xlmG3p3AIr6rrqkpPrcLIik0trMM/ynEb4V7D++qow1AkYE2uw4VssyjJEtq5q9cjQxtKaP |
||||
mjuzurIiLM5GUWxcWEVlzcx5k6YS/5HforX+iUkNDQ32zUH+q9dN/+fAbySYWHnCNGc5AAAAAElFTkSuQmCC`;
|
@ -1,30 +0,0 @@ |
||||
import { Text, View } from "@nodegui/react-nodegui"; |
||||
import React from "react"; |
||||
const dogImg = require("./dog"); |
||||
|
||||
export function StepOne() { |
||||
return ( |
||||
<View style={containerStyle}> |
||||
<Text wordWrap={true}> |
||||
Edit App.tsx to make changes to this screen. Then come back to see your |
||||
changes. Changes should reflect live thanks to Hot Reloading. 🔥 |
||||
</Text> |
||||
<Text> |
||||
{` |
||||
<p style="color: rgb(255,72,38);">
|
||||
<center> |
||||
<img src="${dogImg}" alt="doggy" />
|
||||
</center> |
||||
<center>You can even use <i><strong>Rich Html</strong></i> text like this if you want 😎.</center> |
||||
</p> |
||||
<hr /> |
||||
`}
|
||||
</Text> |
||||
</View> |
||||
); |
||||
} |
||||
|
||||
const containerStyle = ` |
||||
margin-horizontal: 20px; |
||||
padding-horizontal: 10px; |
||||
`;
|
@ -1,53 +0,0 @@ |
||||
import { Text, View, Button, useEventHandler } from "@nodegui/react-nodegui"; |
||||
import { QPushButtonSignals } from "@nodegui/nodegui"; |
||||
import React from "react"; |
||||
import open from "open"; |
||||
|
||||
export function StepTwo() { |
||||
const btnHandler = useEventHandler<QPushButtonSignals>( |
||||
{ |
||||
clicked: () => open("https://react.nodegui.org").catch(console.log) |
||||
}, |
||||
[] |
||||
); |
||||
return ( |
||||
<View style={containerStyle}> |
||||
<Text style={textStyle} wordWrap={true}> |
||||
{` |
||||
<ol> |
||||
<li> |
||||
Open chrome and navigate to chrome://inspect. You should see a target below with your app.
|
||||
</li> |
||||
<br/> |
||||
<li> |
||||
Next click on "Open dedicated DevTools for Node" |
||||
</li> |
||||
<br/> |
||||
<li> |
||||
On the dedicated devtools. Click on Source > Node > "Your node process" |
||||
</li> |
||||
</ol> |
||||
`}
|
||||
</Text> |
||||
<Button |
||||
style={btnStyle} |
||||
on={btnHandler} |
||||
text={`Open React NodeGui docs`} |
||||
></Button> |
||||
</View> |
||||
); |
||||
} |
||||
|
||||
const containerStyle = ` |
||||
flex: 1; |
||||
justify-content: 'space-around'; |
||||
`;
|
||||
|
||||
const textStyle = ` |
||||
padding-right: 20px; |
||||
`;
|
||||
|
||||
const btnStyle = ` |
||||
margin-horizontal: 20px; |
||||
height: 40px; |
||||
`;
|
@ -0,0 +1,40 @@ |
||||
import {TextTranslateResponse} from "tencentcloud-sdk-nodejs/tencentcloud/services/tmt/v20180321/tmt_models"; |
||||
|
||||
const tencentcloud = require("tencentcloud-sdk-nodejs") |
||||
|
||||
const TmtClient = tencentcloud.tmt.v20180321.Client; |
||||
|
||||
const clientConfig = { |
||||
credential: { |
||||
secretId: process.env.REACT_APP_TENCENT_SECRET_ID, |
||||
secretKey: process.env.REACT_APP_TENCENT_SECRET_KEY, |
||||
}, |
||||
region: process.env.REACT_APP_TENCENT_REGION, |
||||
profile: { |
||||
httpProfile: { |
||||
endpoint: process.env.REACT_APP_TENCENT_ENDPOINT, |
||||
}, |
||||
}, |
||||
}; |
||||
|
||||
const client = new TmtClient(clientConfig) |
||||
export default function tencentTmt(SourceText:string,Target:string){ |
||||
return new Promise((resolve:(value:TextTranslateResponse)=>void, reject) => { |
||||
const params = { |
||||
SourceText, |
||||
"Source": "auto", |
||||
Target, |
||||
"ProjectId": 0 |
||||
}; |
||||
client.TextTranslate(params).then( |
||||
(res:TextTranslateResponse) => { |
||||
resolve(res) |
||||
}, |
||||
(err: any) => { |
||||
reject(err) |
||||
} |
||||
) |
||||
}) |
||||
|
||||
|
||||
} |
Loading…
Reference in new issue