diff --git a/changes/changelog.d/814.enhancement b/changes/changelog.d/814.enhancement new file mode 100644 index 0000000000000000000000000000000000000000..c93b1983c954bbcec69ee5f3b0f6912d00ed7b5f --- /dev/null +++ b/changes/changelog.d/814.enhancement @@ -0,0 +1 @@ +Added copy-to-clipboard button with Subsonic password input (#814) diff --git a/front/src/components/auth/SubsonicTokenForm.vue b/front/src/components/auth/SubsonicTokenForm.vue index 0184074e294365a15e453db7184644d66d75796a..fdd9f5e107b2de27b28cb5099b56751b9be180a6 100644 --- a/front/src/components/auth/SubsonicTokenForm.vue +++ b/front/src/components/auth/SubsonicTokenForm.vue @@ -24,7 +24,12 @@ </div> <template v-if="subsonicEnabled"> <div v-if="token" class="field"> - <password-input v-model="token" /> + <password-input + ref="passwordInput" + v-model="token" + :key="token" + :copy-button="true" + :default-show="showToken"/> </div> <dangerous-button v-if="token" @@ -69,7 +74,8 @@ export default { errors: [], success: false, isLoading: false, - successMessage: '' + successMessage: '', + showToken: false } }, created () { @@ -98,6 +104,7 @@ export default { let self = this let url = `users/users/${this.$store.state.auth.username}/subsonic-token/` return axios.post(url, {}).then(response => { + self.showToken = true self.token = response.data['subsonic_api_token'] self.isLoading = false self.success = true diff --git a/front/src/components/forms/PasswordInput.vue b/front/src/components/forms/PasswordInput.vue index d57e3017f3010000e6e45932e25e2092982ef246..702be4f66a5642493012afd70ae3ea7d949dd134 100644 --- a/front/src/components/forms/PasswordInput.vue +++ b/front/src/components/forms/PasswordInput.vue @@ -10,20 +10,37 @@ <span @click="showPassword = !showPassword" :title="labels.title" class="ui icon button"> <i class="eye icon"></i> </span> + <button v-if="copyButton" @click.prevent="copy" class="ui icon button" :title="labels.copy"> + <i class="copy icon"></i> + </button> </div> </template> <script> + +function copyStringToClipboard (str) { + // cf https://techoverflow.net/2018/03/30/copying-strings-to-the-clipboard-using-pure-javascript/ + let el = document.createElement('textarea'); + el.value = str; + el.setAttribute('readonly', ''); + el.style = {position: 'absolute', left: '-9999px'}; + document.body.appendChild(el); + el.select(); + document.execCommand('copy'); + document.body.removeChild(el); +} + export default { - props: ['value', 'index'], + props: ['value', 'index', 'defaultShow', 'copyButton'], data () { return { - showPassword: false + showPassword: this.defaultShow || false, } }, computed: { labels () { return { - title: this.$pgettext('Content/Settings/Button.Tooltip/Verb', 'Show/hide password') + title: this.$pgettext('Content/Settings/Button.Tooltip/Verb', 'Show/hide password'), + copy: this.$pgettext('*/*/Button.Label/Short, Verb', 'Copy') } }, passwordInputType () { @@ -32,6 +49,11 @@ export default { } return 'password' } + }, + methods: { + copy () { + copyStringToClipboard(this.value) + } } } </script>