Skip to content

Commit

Permalink
Feature/8134 - copy to clipboard
Browse files Browse the repository at this point in the history
  • Loading branch information
pascalwengerter committed Dec 22, 2022
1 parent 931cb9f commit fa8e18c
Show file tree
Hide file tree
Showing 13 changed files with 41 additions and 47 deletions.
6 changes: 6 additions & 0 deletions changelog/unreleased/enhancement-clipboard-copy
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
Enhancement: Make clipboard copy available to more browsers

We've removed a thirdparty library and now rely on the standard browser API for copying (e.g. links) to the user's clipboard.

https://github.com/owncloud/web/pull/8136
https://github.com/owncloud/web/issues/8134
1 change: 0 additions & 1 deletion packages/web-app-files/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
"description": "ownCloud web files",
"license": "AGPL-3.0",
"dependencies": {
"copy-to-clipboard": "^3.3.1",
"mark.js": "^8.11.1"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ import {
useUserContext
} from 'web-pkg/src/composables'
import { getIndicators } from '../../../helpers/statusIndicators'
import copyToClipboard from 'copy-to-clipboard'
import { copyToClipboard } from 'web-pkg/src/helpers'
import { encodePath } from 'web-pkg/src/utils'
import { formatDateFromHTTP, formatFileSize } from 'web-pkg/src/helpers'
import { eventBus } from 'web-pkg/src/services/eventBus'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
</template>

<script>
import { mapActions } from 'vuex'
import copyToClipboard from 'copy-to-clipboard'
import { unref } from 'vue'
import { mapActions } from 'vuex'
import { copyToClipboard } from 'web-pkg/src/helpers'
export default {
name: 'PrivateLinkItem',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@
<script>
import { mapActions } from 'vuex'
import { defineComponent } from 'vue'
import copyToClipboard from 'copy-to-clipboard'
import { copyToClipboard } from 'web-pkg/src/helpers'
export default defineComponent({
name: 'NameAndCopy',
Expand Down
2 changes: 1 addition & 1 deletion packages/web-app-files/src/helpers/share/link.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { DateTime } from 'luxon'
import { Share } from 'web-client/src/helpers/share'
import { Store } from 'vuex'
import { clientService } from 'web-pkg/src/services'
import copyToClipboard from 'copy-to-clipboard'
import { copyToClipboard } from 'web-pkg/src/helpers'

interface CreateQuicklink {
store: Store<any>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,23 +1,39 @@
import PrivateLinkItem from 'web-app-files/src/components/SideBar/PrivateLinkItem.vue'
import { mockDeep } from 'jest-mock-extended'
import { mock } from 'jest-mock-extended'
import { Resource } from 'web-client'
import { createStore, defaultPlugins, mount, defaultStoreMockOptions } from 'web-test-helpers'
import PrivateLinkItem from 'web-app-files/src/components/SideBar/PrivateLinkItem.vue'

jest.useFakeTimers()

const folder = mock<Resource>({
type: 'folder',
ownerId: 'marie',
ownerDisplayName: 'Marie',
mdate: 'Wed, 21 Oct 2015 07:28:00 GMT',
size: '740',
name: 'lorem.txt',
privateLink: 'https://example.com/fake-private-link'
})

describe('PrivateLinkItem', () => {
it('should render a button', () => {
const { wrapper } = getWrapper()
expect(wrapper.html()).toMatchSnapshot()
})
it('upon clicking it should copy the private link to the clipboard button, render a success message and change icon for half a second', async () => {
jest.spyOn(window, 'prompt').mockImplementation()
Object.assign(window.navigator, {
clipboard: {
writeText: jest.fn().mockImplementation(() => Promise.resolve())
}
})

const { wrapper } = getWrapper()
const spyShowMessage = jest.spyOn(wrapper.vm, 'showMessage')
expect(spyShowMessage).not.toHaveBeenCalled()

await wrapper.trigger('click')
expect(wrapper.html()).toMatchSnapshot()
expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith(folder.privateLink)
expect(spyShowMessage).toHaveBeenCalledTimes(1)

jest.advanceTimersByTime(550)
Expand All @@ -29,15 +45,6 @@ describe('PrivateLinkItem', () => {
})

function getWrapper() {
const folder = mockDeep<Resource>({
type: 'folder',
ownerId: 'marie',
ownerDisplayName: 'Marie',
mdate: 'Wed, 21 Oct 2015 07:28:00 GMT',
size: '740',
name: 'lorem.txt',
privateLink: 'https://example.com/fake-private-link'
})
const storeOptions = { ...defaultStoreMockOptions }
storeOptions.getters.capabilities.mockImplementation(() => ({ files: { privateLinks: true } }))
storeOptions.modules.Files.getters.highlightedFile.mockImplementation(() => folder)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,17 +16,20 @@ describe('NameAndCopy', () => {
expect(wrapper.html()).toMatchSnapshot()
})
it('upon clicking it should copy the private link to the clipboard button, render a success message and change icon for half a second', async () => {
const windowSpy = jest.spyOn(window, 'prompt').mockImplementation()
Object.assign(window.navigator, {
clipboard: {
writeText: jest.fn().mockImplementation(() => Promise.resolve())
}
})

const { wrapper } = getWrapper()
const spyShowMessage = jest.spyOn(wrapper.vm, 'showMessage')
expect(spyShowMessage).not.toHaveBeenCalled()
expect(windowSpy).not.toHaveBeenCalled()

await wrapper.find('.oc-files-public-link-copy-url').trigger('click')
expect(window.navigator.clipboard.writeText).toHaveBeenCalledWith(exampleLink.url)
expect(wrapper.html()).toMatchSnapshot()
expect(spyShowMessage).toHaveBeenCalledTimes(1)
expect(windowSpy).toHaveBeenCalledTimes(1)
expect(windowSpy).toHaveBeenCalledWith('Copy to clipboard: Ctrl+C, Enter', exampleLink.url)

jest.advanceTimersByTime(550)

Expand Down
3 changes: 3 additions & 0 deletions packages/web-pkg/src/helpers/clipboard.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export function copyToClipboard(string): Promise<void> {
return navigator.clipboard.writeText(string)
}
1 change: 1 addition & 0 deletions packages/web-pkg/src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from './cache'
export * from './clipboard'
export * from './preview'
export * from './datetime'
export * from './filesize'
Expand Down
2 changes: 0 additions & 2 deletions packages/web-runtime/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,9 @@
"uuid": "^9.0.0",
"vue-async-computed": "^3.9.0",
"vue-concurrency": "4.0.0",
"vue-events": "^3.1.0",
"vue-gettext": "2.1.12",
"vue-inline-svg": "^2.0.0",
"vue-meta": "^2.2.2",
"vue-resize": "^1.0.1",
"vue-router": "3.6.5",
"vue-scrollto": "^2.15.0",
"vue-select": "^3.18.3",
Expand Down
3 changes: 0 additions & 3 deletions packages/web-runtime/src/defaults/vue.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,9 @@
import 'vue-resize/dist/vue-resize.css'
import Vue from 'vue'
import WebPlugin from '../plugins/web'
import Avatar from '../components/Avatar.vue'
import focusMixin from '../mixins/focusMixin'
import lifecycleMixin from '../mixins/lifecycleMixin'
import VueEvents from 'vue-events'
import VueScrollTo from 'vue-scrollto'
import VueResize from 'vue-resize'
import VueMeta from 'vue-meta'
import PortalVue from 'portal-vue'
import AsyncComputed from 'vue-async-computed'
Expand Down
20 changes: 0 additions & 20 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit fa8e18c

Please sign in to comment.