Skip to content

Commit eef80f7

Browse files
committed
fix: use paste event instead of keyboard event
Signed-off-by: Robin Appelman <[email protected]>
1 parent 88ecb2c commit eef80f7

File tree

3 files changed

+15
-57
lines changed

3 files changed

+15
-57
lines changed

src/App.vue

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -85,16 +85,18 @@ const onShowServerLog = () => {
8585
* Handle pressing ctrl + v to paste log entries
8686
* @param event The keyboard event
8787
*/
88-
const onHandlePaste = (event: KeyboardEvent) => {
89-
// Check Ctrl + v (be tolerant: ignore caps lock) and only intercept if target is no input for pasting
90-
if ((event.key === 'v' || event.key === 'V') && event.ctrlKey && (event.target as HTMLElement)?.tagName !== 'INPUT') {
91-
loggingStore.loadClipboard()
92-
event.stopPropagation()
88+
const onHandlePaste = (event: ClipboardEvent) => {
89+
event.preventDefault();
90+
91+
if (event.clipboardData) {
92+
let paste = event.clipboardData.getData("text")
93+
loggingStore.loadText(paste)
9394
}
95+
9496
}
9597
// Add / remove event listeners
96-
onMounted(() => window.addEventListener('keyup', onHandlePaste))
97-
onUnmounted(() => window.removeEventListener('keyup', onHandlePaste))
98+
onMounted(() => window.addEventListener('paste', onHandlePaste))
99+
onUnmounted(() => window.removeEventListener('paste', onHandlePaste))
98100
99101
/**
100102
* Toggle polling if live log is dis- / enabled

src/store/logging.spec.ts

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -238,15 +238,14 @@ describe('store:logging', () => {
238238
})
239239

240240
const clipboard = '{message: "hello"}'
241-
window.navigator.clipboard.readText = vi.fn(() => Promise.resolve(clipboard))
242241

243242
const store = useLogStore()
244243
const settings = useSettingsStore()
245244

246245
store.hasRemainingEntries = true
247246
expect(store.hasRemainingEntries).toBe(true)
248247

249-
await store.loadClipboard()
248+
await store.loadText(clipboard)
250249

251250
// File parsed, so there are no remaining entries
252251
expect(store.hasRemainingEntries).toBe(false)
@@ -256,37 +255,6 @@ describe('store:logging', () => {
256255
expect(store.allEntries).toEqual([{ message: 'hello' }])
257256
})
258257

259-
it('handles unsupported Clipboard API', async () => {
260-
mocks.parseLogString.mockImplementationOnce(() => [{ message: 'hello' }])
261-
262-
// clean pinia
263-
createTestingPinia({
264-
fakeApp: true,
265-
createSpy: vi.fn,
266-
stubActions: false,
267-
})
268-
269-
const clipboard = '{message: "hello"}'
270-
window.navigator.clipboard.readText = vi.fn(() => Promise.reject(new Error()))
271-
window.prompt = vi.fn(() => clipboard)
272-
273-
const store = useLogStore()
274-
const settings = useSettingsStore()
275-
276-
store.hasRemainingEntries = true
277-
expect(store.hasRemainingEntries).toBe(true)
278-
279-
await store.loadClipboard()
280-
281-
// File parsed, so there are no remaining entries
282-
expect(store.hasRemainingEntries).toBe(false)
283-
expect(window.navigator.clipboard.readText).toBeCalled()
284-
expect(window.prompt).toBeCalled()
285-
expect(settings.localFileName).toBe('Clipboard')
286-
expect(mocks.parseLogString).toBeCalledWith(clipboard)
287-
expect(store.allEntries).toEqual([{ message: 'hello' }])
288-
})
289-
290258
it('handles empty clipboard paste', async () => {
291259
// clean pinia
292260
createTestingPinia({
@@ -295,16 +263,13 @@ describe('store:logging', () => {
295263
stubActions: false,
296264
})
297265

298-
window.navigator.clipboard.readText = vi.fn(() => Promise.reject(new Error()))
299-
window.prompt = vi.fn(() => null)
300-
301266
const store = useLogStore()
302267
const settings = useSettingsStore()
303268

304269
store.hasRemainingEntries = true
305270
expect(store.hasRemainingEntries).toBe(true)
306271

307-
await store.loadClipboard()
272+
await store.loadText('')
308273

309274
// File parsed, so there are no remaining entries
310275
expect(store.hasRemainingEntries).toBe(true)
@@ -322,7 +287,6 @@ describe('store:logging', () => {
322287
stubActions: false,
323288
})
324289

325-
window.navigator.clipboard.readText = vi.fn(() => Promise.resolve('invalid'))
326290
// throw an error
327291
mocks.parseLogString.mockImplementationOnce(() => { throw new Error() })
328292

@@ -332,7 +296,7 @@ describe('store:logging', () => {
332296
store.hasRemainingEntries = true
333297
expect(store.hasRemainingEntries).toBe(true)
334298

335-
await store.loadClipboard()
299+
await store.loadText('invalid')
336300

337301
// File parsed, so there are no remaining entries
338302
expect(store.hasRemainingEntries).toBe(true)

src/store/logging.ts

Lines changed: 3 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,9 @@ export const useLogStore = defineStore('logreader-logs', () => {
102102
}
103103

104104
/**
105-
* Load entries from clipboard
105+
* Load entries from string
106106
*/
107-
async function loadClipboard() {
108-
// try if the browser supports the async clipboard api, e.g. firefox does not.
109-
let text = ''
110-
try {
111-
text = await window.navigator.clipboard.readText()
112-
} catch (e) {
113-
text = window.prompt(t('logreader', 'Your browser does not support pasting entries directly. Please paste the log entry manually.')) ?? ''
114-
}
115-
107+
async function loadText(text: string) {
116108
// Skip if aborted
117109
if (text === '') {
118110
return
@@ -199,5 +191,5 @@ export const useLogStore = defineStore('logreader-logs', () => {
199191
}
200192
}
201193

202-
return { allEntries, entries, hasRemainingEntries, query, loadMore, loadClipboard, loadFile, startPolling, stopPolling, searchLogs }
194+
return { allEntries, entries, hasRemainingEntries, query, loadMore, loadText, loadFile, startPolling, stopPolling, searchLogs }
203195
})

0 commit comments

Comments
 (0)