Skip to content
This repository was archived by the owner on Aug 16, 2024. It is now read-only.

Commit e43c057

Browse files
committed
feat: add close button to App
1 parent 942d35f commit e43c057

File tree

20 files changed

+256
-34
lines changed

20 files changed

+256
-34
lines changed

package.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747
"babel-preset-react-app": "^10.0.0",
4848
"chrome-call": "^4.0.1",
4949
"clean-webpack-plugin": "^3.0.0",
50+
"clsx": "^1.1.1",
5051
"connect.io": "^3.1.3",
5152
"copy-webpack-plugin": "^6.4.0",
5253
"css-loader": "^5.0.1",
@@ -66,11 +67,13 @@
6667
"postcss-import": "^14.0.0",
6768
"postcss-loader": "^4.1.0",
6869
"prettier": "^2.2.1",
70+
"process": "^0.11.10",
6971
"rangy": "^1.3.0",
7072
"react": "^17.0.1",
7173
"react-dom": "^17.0.1",
7274
"react-draggable": "^4.4.3",
7375
"react-hot-loader": "^4.13.0",
76+
"react-scroll-to-bottom": "^4.1.0",
7477
"sass-loader": "^10.1.0",
7578
"smoothscroll-polyfill": "^0.4.4",
7679
"source-map-loader": "^1.1.3",

src/assets/img/icon-128.png

-7.09 KB
Loading

src/assets/img/icon-34.png

-1.12 KB
Loading

src/components/Icon.tsx

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import React from 'react'
2+
3+
const Icon: React.FC = (props) => {
4+
return <div className="ate_Icon">{props.children}</div>
5+
}
6+
7+
export default Icon

src/components/IconButton.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React, { HTMLProps, MouseEventHandler } from 'react'
2+
import clsx from 'clsx'
3+
4+
const IconButton: React.FC<Omit<HTMLProps<HTMLButtonElement>, 'size'>> = (
5+
props,
6+
) => {
7+
const handleClick: MouseEventHandler<HTMLButtonElement> = (e) => {
8+
props.onClick && props.onClick(e)
9+
}
10+
11+
return (
12+
<button
13+
className={clsx(['ate_IconButton', props.className])}
14+
onClick={handleClick}>
15+
{props.children}
16+
</button>
17+
)
18+
}
19+
20+
export default IconButton

src/components/svg/Close.tsx

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import React from 'react'
2+
3+
export default function Close(): React.ReactElement {
4+
return (
5+
<svg
6+
xmlns="http://www.w3.org/2000/svg"
7+
fill="none"
8+
width="16"
9+
height="16"
10+
viewBox="0 0 24 24"
11+
stroke="currentColor">
12+
<path
13+
strokeLinecap="round"
14+
strokeLinejoin="round"
15+
strokeWidth={2}
16+
d="M6 18L18 6M6 6l12 12"
17+
/>
18+
</svg>
19+
)
20+
}

src/manifest.json

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "A Translator",
3-
"permissions": ["<all_urls>", "storage"],
3+
"permissions": ["<all_urls>", "storage", "tabs"],
44
"options_ui": {
55
"page": "options.html",
66
"chrome_style": false,
@@ -10,8 +10,10 @@
1010
"page": "background.html"
1111
},
1212
"browser_action": {
13-
"default_popup": "popup.html",
14-
"default_icon": "icon-34.png"
13+
"default_icon": {
14+
"128": "icon-128.png"
15+
},
16+
"default_title": "A Translator"
1517
},
1618
"icons": {
1719
"128": "icon-128.png"
@@ -21,7 +23,7 @@
2123
"matches": ["http://*/*", "https://*/*", "<all_urls>"],
2224
"js": ["contentScript.bundle.js"],
2325
"css": ["contentScript.bundle.css"],
24-
"run_at": "document_start"
26+
"run_at": "document_end"
2527
}
2628
],
2729
"web_accessible_resources": [
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import cc from 'chrome-call'
2+
import { createClient } from 'connect.io'
3+
import logger from '../../../common/logger'
4+
5+
export const openExtension = (): void => {
6+
cc(chrome.tabs, 'query', { active: true, currentWindow: true })
7+
.then((tabs: chrome.tabs.Tab[]) => {
8+
const client = createClient(tabs[0].id)
9+
10+
client.send('open_extension')
11+
})
12+
.catch((err) => {
13+
logger.error({
14+
err,
15+
})
16+
})
17+
}

src/pages/Background/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ import '../../assets/img/icon-34.png'
22
import '../../assets/img/icon-128.png'
33

44
import './common/server'
5+
import { openExtension } from './common/utils'
6+
7+
chrome.browserAction.onClicked.addListener(openExtension)

src/pages/Content/components/App/index.tsx

Lines changed: 42 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,14 @@
1+
import clsx from 'clsx'
12
import React, { useCallback, useEffect, useState } from 'react'
2-
import Draggable from 'react-draggable'
3+
import Draggable, { DraggableEventHandler } from 'react-draggable'
34
import cc from 'chrome-call'
5+
// @ts-ignore
6+
import ScrollToBottom from 'react-scroll-to-bottom'
47

58
import logger from '../../../../common/logger'
69
import { Config } from '../../../../common/types'
10+
import IconButton from '../../../../components/IconButton'
11+
import CloseIcon from '../../../../components/svg/Close'
712
import translationStack from '../../common/translation-stack'
813
import { TranslateJob } from '../../common/types'
914
import { ConfigContext, ConfigState } from '../../providers/config'
@@ -12,6 +17,7 @@ import TranslationList from '../TranslationList'
1217

1318
const App: React.FC = () => {
1419
const [config, setConfig] = useState<ConfigState>()
20+
const [close, setClose] = useState(false)
1521
const dispatch = useTranslateJobsDispatch()
1622

1723
const onNewJob = useCallback(
@@ -33,6 +39,16 @@ const App: React.FC = () => {
3339
[dispatch],
3440
)
3541

42+
const onDragStart: DraggableEventHandler = (e) => {
43+
if (
44+
document
45+
.querySelector<HTMLButtonElement>('.ate_App__close-button')
46+
?.contains(e.target as Node)
47+
) {
48+
return false
49+
}
50+
}
51+
3652
useEffect(() => {
3753
translationStack.attachQueue(onNewJob)
3854

@@ -47,20 +63,40 @@ const App: React.FC = () => {
4763
targetLang: config.targetLang,
4864
})
4965
})
66+
67+
window.__ate_setClose = setClose
5068
}, [])
5169

5270
return (
5371
<ConfigContext.Provider value={config}>
54-
<Draggable handle=".ate_App__header" defaultPosition={{ x: 20, y: 20 }}>
55-
<div className="ate_App">
56-
<div className="ate_App__header">A Translator</div>
57-
<div className="ate_App__container">
58-
<TranslationList />
72+
<Draggable
73+
handle=".ate_App__header"
74+
onStart={onDragStart}
75+
defaultPosition={{ x: 20, y: 20 }}>
76+
<div className={clsx(['ate_App', close && 'ate_App--inactive'])}>
77+
<div className="ate_App__header">
78+
<span>A Translator</span>
79+
<span>
80+
<IconButton
81+
className="ate_App__close-button"
82+
onClick={() => setClose(true)}>
83+
<CloseIcon />
84+
</IconButton>
85+
</span>
5986
</div>
87+
<ScrollToBottom className="ate_App__container" debug={false}>
88+
<TranslationList />
89+
</ScrollToBottom>
6090
</div>
6191
</Draggable>
6292
</ConfigContext.Provider>
6393
)
6494
}
6595

6696
export default App
97+
98+
declare global {
99+
interface Window {
100+
__ate_setClose?: React.Dispatch<any>
101+
}
102+
}

0 commit comments

Comments
 (0)