Skip to content

Commit

Permalink
fix: use paste event instead of keyboard event
Browse files Browse the repository at this point in the history
Signed-off-by: Robin Appelman <[email protected]>
  • Loading branch information
icewind1991 committed Feb 13, 2024
1 parent 88ecb2c commit ab1dc3e
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 62 deletions.
18 changes: 10 additions & 8 deletions src/App.vue
Original file line number Diff line number Diff line change
Expand Up @@ -82,19 +82,21 @@ const onShowServerLog = () => {
}
/**
* Handle pressing ctrl + v to paste log entries
* Handle paste events with log entries
* @param event The keyboard event
*/
const onHandlePaste = (event: KeyboardEvent) => {
// Check Ctrl + v (be tolerant: ignore caps lock) and only intercept if target is no input for pasting
if ((event.key === 'v' || event.key === 'V') && event.ctrlKey && (event.target as HTMLElement)?.tagName !== 'INPUT') {
loggingStore.loadClipboard()
event.stopPropagation()
const onHandlePaste = (event: ClipboardEvent) => {
event.preventDefault()
if (event.clipboardData) {
const paste = event.clipboardData.getData('text')
loggingStore.loadText(paste)
}
}
// Add / remove event listeners
onMounted(() => window.addEventListener('keyup', onHandlePaste))
onUnmounted(() => window.removeEventListener('keyup', onHandlePaste))
onMounted(() => window.addEventListener('paste', onHandlePaste))
onUnmounted(() => window.removeEventListener('paste', onHandlePaste))
/**
* Toggle polling if live log is dis- / enabled
Expand Down
46 changes: 3 additions & 43 deletions src/store/logging.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -238,50 +238,17 @@ describe('store:logging', () => {
})

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

const store = useLogStore()
const settings = useSettingsStore()

store.hasRemainingEntries = true
expect(store.hasRemainingEntries).toBe(true)

await store.loadClipboard()
await store.loadText(clipboard)

// File parsed, so there are no remaining entries
expect(store.hasRemainingEntries).toBe(false)
expect(window.navigator.clipboard.readText).toBeCalled()
expect(settings.localFileName).toBe('Clipboard')
expect(mocks.parseLogString).toBeCalledWith(clipboard)
expect(store.allEntries).toEqual([{ message: 'hello' }])
})

it('handles unsupported Clipboard API', async () => {
mocks.parseLogString.mockImplementationOnce(() => [{ message: 'hello' }])

// clean pinia
createTestingPinia({
fakeApp: true,
createSpy: vi.fn,
stubActions: false,
})

const clipboard = '{message: "hello"}'
window.navigator.clipboard.readText = vi.fn(() => Promise.reject(new Error()))
window.prompt = vi.fn(() => clipboard)

const store = useLogStore()
const settings = useSettingsStore()

store.hasRemainingEntries = true
expect(store.hasRemainingEntries).toBe(true)

await store.loadClipboard()

// File parsed, so there are no remaining entries
expect(store.hasRemainingEntries).toBe(false)
expect(window.navigator.clipboard.readText).toBeCalled()
expect(window.prompt).toBeCalled()
expect(settings.localFileName).toBe('Clipboard')
expect(mocks.parseLogString).toBeCalledWith(clipboard)
expect(store.allEntries).toEqual([{ message: 'hello' }])
Expand All @@ -295,21 +262,16 @@ describe('store:logging', () => {
stubActions: false,
})

window.navigator.clipboard.readText = vi.fn(() => Promise.reject(new Error()))
window.prompt = vi.fn(() => null)

const store = useLogStore()
const settings = useSettingsStore()

store.hasRemainingEntries = true
expect(store.hasRemainingEntries).toBe(true)

await store.loadClipboard()
await store.loadText('')

// File parsed, so there are no remaining entries
expect(store.hasRemainingEntries).toBe(true)
expect(window.navigator.clipboard.readText).toBeCalled()
expect(window.prompt).toBeCalled()
expect(settings.localFile).toBe(undefined)
expect(settings.localFileName).toBe('')
})
Expand All @@ -322,7 +284,6 @@ describe('store:logging', () => {
stubActions: false,
})

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

Expand All @@ -332,11 +293,10 @@ describe('store:logging', () => {
store.hasRemainingEntries = true
expect(store.hasRemainingEntries).toBe(true)

await store.loadClipboard()
await store.loadText('invalid')

// File parsed, so there are no remaining entries
expect(store.hasRemainingEntries).toBe(true)
expect(window.navigator.clipboard.readText).toBeCalled()
expect(mocks.showError).toBeCalled()
expect(settings.localFile).toBe(undefined)
expect(settings.localFileName).toBe('')
Expand Down
14 changes: 3 additions & 11 deletions src/store/logging.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,17 +102,9 @@ export const useLogStore = defineStore('logreader-logs', () => {
}

/**
* Load entries from clipboard
* Load entries from string
*/
async function loadClipboard() {
// try if the browser supports the async clipboard api, e.g. firefox does not.
let text = ''
try {
text = await window.navigator.clipboard.readText()
} catch (e) {
text = window.prompt(t('logreader', 'Your browser does not support pasting entries directly. Please paste the log entry manually.')) ?? ''
}

async function loadText(text: string) {
// Skip if aborted
if (text === '') {
return
Expand Down Expand Up @@ -199,5 +191,5 @@ export const useLogStore = defineStore('logreader-logs', () => {
}
}

return { allEntries, entries, hasRemainingEntries, query, loadMore, loadClipboard, loadFile, startPolling, stopPolling, searchLogs }
return { allEntries, entries, hasRemainingEntries, query, loadMore, loadText, loadFile, startPolling, stopPolling, searchLogs }
})

0 comments on commit ab1dc3e

Please sign in to comment.