Skip to content

Commit b5026cd

Browse files
committed
feat: make floating window of selectionTools dockable
1 parent a5daacf commit b5026cd

File tree

3 files changed

+36
-13
lines changed

3 files changed

+36
-13
lines changed

src/components/ConversationCard/index.jsx

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import InputBox from '../InputBox'
55
import ConversationItem from '../ConversationItem'
66
import { createElementAtPosition, initSession, isSafari } from '../../utils'
77
import { DownloadIcon } from '@primer/octicons-react'
8-
import { WindowDesktop, XLg } from 'react-bootstrap-icons'
8+
import { WindowDesktop, XLg, Pin } from 'react-bootstrap-icons'
99
import FileSaver from 'file-saver'
1010
import { render } from 'preact'
1111
import FloatingToolbar from '../FloatingToolbar'
@@ -175,9 +175,7 @@ function ConversationCard(props) {
175175
return (
176176
<div className="gpt-inner">
177177
<div className="gpt-header">
178-
{!props.closeable ? (
179-
<img src={logo} width="20" height="20" style="margin:5px 15px 0px;user-select:none;" />
180-
) : (
178+
{props.closeable ? (
181179
<XLg
182180
className="gpt-util-icon"
183181
style="margin:5px 15px 0px;"
@@ -187,6 +185,18 @@ function ConversationCard(props) {
187185
if (props.onClose) props.onClose()
188186
}}
189187
/>
188+
) : props.dockable ? (
189+
<Pin
190+
className="gpt-util-icon"
191+
style="margin:5px 15px 0px;"
192+
title="Pin the Window"
193+
size={16}
194+
onClick={() => {
195+
if (props.onDock) props.onDock()
196+
}}
197+
/>
198+
) : (
199+
<img src={logo} width="20" height="20" style="margin:5px 15px 0px;user-select:none;" />
190200
)}
191201
{props.draggable ? (
192202
<div className="dragbar" />
@@ -207,7 +217,6 @@ function ConversationCard(props) {
207217
container={toolbarContainer}
208218
closeable={true}
209219
triggered={true}
210-
onClose={() => toolbarContainer.remove()}
211220
/>,
212221
toolbarContainer,
213222
)
@@ -278,6 +287,8 @@ ConversationCard.propTypes = {
278287
draggable: PropTypes.bool,
279288
closeable: PropTypes.bool,
280289
onClose: PropTypes.func,
290+
dockable: PropTypes.bool,
291+
onDock: PropTypes.func,
281292
}
282293

283294
export default memo(ConversationCard)

src/components/FloatingToolbar/index.jsx

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ function FloatingToolbar(props) {
1717
const [config, setConfig] = useState(defaultConfig)
1818
const [render, setRender] = useState(false)
1919
const [position, setPosition] = useState(props.position)
20+
const [closeable, setCloseable] = useState(props.closeable)
2021
const [virtualPosition, setVirtualPosition] = useState({ x: 0, y: 0 })
2122
const windowSize = useClampWindowSize([750, 1500], [0, Infinity])
2223

@@ -94,8 +95,15 @@ function FloatingToolbar(props) {
9495
session={props.session}
9596
question={prompt}
9697
draggable={true}
97-
closeable={props.closeable}
98-
onClose={props.onClose}
98+
closeable={closeable}
99+
onClose={() => {
100+
props.container.remove()
101+
}}
102+
dockable={props.dockable}
103+
onDock={() => {
104+
props.container.className = 'chatgptbox-toolbar-container-not-queryable'
105+
setCloseable(true)
106+
}}
99107
onUpdate={() => {
100108
updatePosition()
101109
}}
@@ -145,7 +153,7 @@ FloatingToolbar.propTypes = {
145153
container: PropTypes.object.isRequired,
146154
triggered: PropTypes.bool,
147155
closeable: PropTypes.bool,
148-
onClose: PropTypes.func,
156+
dockable: PropTypes.bool,
149157
prompt: PropTypes.string,
150158
}
151159

src/content-script/index.jsx

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,10 @@ async function prepareForSafari() {
102102
}
103103

104104
let toolbarContainer
105+
const deleteToolbar = () => {
106+
if (toolbarContainer && toolbarContainer.className === 'chatgptbox-toolbar-container')
107+
toolbarContainer.remove()
108+
}
105109

106110
async function prepareForSelectionTools() {
107111
document.addEventListener('mouseup', (e) => {
@@ -113,7 +117,7 @@ async function prepareForSelectionTools() {
113117
)
114118
return
115119

116-
if (toolbarContainer) toolbarContainer.remove()
120+
deleteToolbar()
117121
setTimeout(() => {
118122
const selection = window.getSelection()?.toString()
119123
if (selection) {
@@ -126,6 +130,7 @@ async function prepareForSelectionTools() {
126130
selection={selection}
127131
position={position}
128132
container={toolbarContainer}
133+
dockable={true}
129134
/>,
130135
toolbarContainer,
131136
)
@@ -144,7 +149,7 @@ async function prepareForSelectionTools() {
144149
(e.target.nodeName === 'INPUT' || e.target.nodeName === 'TEXTAREA')
145150
) {
146151
setTimeout(() => {
147-
if (!window.getSelection()?.toString()) toolbarContainer.remove()
152+
if (!window.getSelection()?.toString()) deleteToolbar()
148153
})
149154
}
150155
})
@@ -160,7 +165,7 @@ async function prepareForSelectionToolsTouch() {
160165
)
161166
return
162167

163-
if (toolbarContainer) toolbarContainer.remove()
168+
deleteToolbar()
164169
setTimeout(() => {
165170
const selection = window.getSelection()?.toString()
166171
if (selection) {
@@ -176,6 +181,7 @@ async function prepareForSelectionToolsTouch() {
176181
selection={selection}
177182
position={position}
178183
container={toolbarContainer}
184+
dockable={true}
179185
/>,
180186
toolbarContainer,
181187
)
@@ -212,7 +218,6 @@ async function prepareForRightClickMenu() {
212218
container={container}
213219
triggered={true}
214220
closeable={true}
215-
onClose={() => container.remove()}
216221
/>,
217222
container,
218223
)
@@ -228,7 +233,6 @@ async function prepareForRightClickMenu() {
228233
container={container}
229234
triggered={true}
230235
closeable={true}
231-
onClose={() => container.remove()}
232236
prompt={await toolsConfig[data.itemId].genPrompt(data.selectionText)}
233237
/>,
234238
container,

0 commit comments

Comments
 (0)