Make copyToClipboard and openExternalLink helpers (#2722)
This commit is contained in:
		
							parent
							
								
									26e40c51e7
								
							
						
					
					
						commit
						f970936d1e
					
				|  | @ -12,7 +12,7 @@ import FtProgressBar from './components/ft-progress-bar/ft-progress-bar.vue' | |||
| import { marked } from 'marked' | ||||
| import { IpcChannels } from '../constants' | ||||
| import packageDetails from '../../package.json' | ||||
| import { showToast } from './helpers/utils' | ||||
| import { openExternalLink, showToast } from './helpers/utils' | ||||
| 
 | ||||
| let ipcRenderer = null | ||||
| 
 | ||||
|  | @ -272,7 +272,7 @@ export default Vue.extend({ | |||
| 
 | ||||
|     handleNewBlogBannerClick: function (response) { | ||||
|       if (response) { | ||||
|         this.openExternalLink(this.latestBlogUrl) | ||||
|         openExternalLink(this.latestBlogUrl) | ||||
|       } | ||||
| 
 | ||||
|       this.showBlogBanner = false | ||||
|  | @ -280,7 +280,7 @@ export default Vue.extend({ | |||
| 
 | ||||
|     openDownloadsPage: function () { | ||||
|       const url = 'https://freetubeapp.io#download' | ||||
|       this.openExternalLink(url) | ||||
|       openExternalLink(url) | ||||
|       this.showReleaseNotes = false | ||||
|       this.showUpdatesBanner = false | ||||
|     }, | ||||
|  | @ -364,7 +364,7 @@ export default Vue.extend({ | |||
|         this.showExternalLinkOpeningPrompt = true | ||||
|       } else { | ||||
|         // Open links externally
 | ||||
|         this.openExternalLink(el.href) | ||||
|         openExternalLink(el.href) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|  | @ -515,7 +515,7 @@ export default Vue.extend({ | |||
|         // if `lastExternalLinkToBeOpened` is empty
 | ||||
| 
 | ||||
|         // Open links externally
 | ||||
|         this.openExternalLink(this.lastExternalLinkToBeOpened) | ||||
|         openExternalLink(this.lastExternalLinkToBeOpened) | ||||
|       } | ||||
|     }, | ||||
| 
 | ||||
|  | @ -530,7 +530,6 @@ export default Vue.extend({ | |||
|     ]), | ||||
| 
 | ||||
|     ...mapActions([ | ||||
|       'openExternalLink', | ||||
|       'grabUserSettings', | ||||
|       'grabAllProfiles', | ||||
|       'grabHistory', | ||||
|  |  | |||
|  | @ -11,7 +11,7 @@ import { MAIN_PROFILE_ID } from '../../../constants' | |||
| import fs from 'fs' | ||||
| import { opmlToJSON } from 'opml-to-json' | ||||
| import ytch from 'yt-channel-info' | ||||
| import { calculateColorLuminance, getRandomColor, showToast } from '../../helpers/utils' | ||||
| import { calculateColorLuminance, copyToClipboard, getRandomColor, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| // FIXME: Missing web logic branching
 | ||||
| 
 | ||||
|  | @ -1042,7 +1042,7 @@ export default Vue.extend({ | |||
|           console.error(err) | ||||
|           const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err.responseJSON.error}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err.responseJSON.error }) | ||||
|             copyToClipboard(err.responseJSON.error) | ||||
|           }) | ||||
| 
 | ||||
|           if (this.backendFallback && this.backendPreference === 'invidious') { | ||||
|  | @ -1063,7 +1063,7 @@ export default Vue.extend({ | |||
|           console.error(err) | ||||
|           const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err }) | ||||
|             copyToClipboard(err) | ||||
|           }) | ||||
| 
 | ||||
|           if (this.backendFallback && this.backendPreference === 'local') { | ||||
|  | @ -1145,8 +1145,7 @@ export default Vue.extend({ | |||
|       'showSaveDialog', | ||||
|       'getUserDataPath', | ||||
|       'addPlaylist', | ||||
|       'addVideo', | ||||
|       'copyToClipboard' | ||||
|       'addVideo' | ||||
|     ]), | ||||
| 
 | ||||
|     ...mapMutations([ | ||||
|  |  | |||
|  | @ -2,7 +2,7 @@ import Vue from 'vue' | |||
| import FtIconButton from '../ft-icon-button/ft-icon-button.vue' | ||||
| import { mapActions } from 'vuex' | ||||
| import i18n from '../../i18n/index' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { copyToClipboard, openExternalLink, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'FtListVideo', | ||||
|  | @ -300,34 +300,34 @@ export default Vue.extend({ | |||
|           } | ||||
|           break | ||||
|         case 'copyYoutube': | ||||
|           this.copyToClipboard({ content: this.youtubeShareUrl, messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') }) | ||||
|           copyToClipboard(this.youtubeShareUrl, { messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') }) | ||||
|           break | ||||
|         case 'openYoutube': | ||||
|           this.openExternalLink(this.youtubeUrl) | ||||
|           openExternalLink(this.youtubeUrl) | ||||
|           break | ||||
|         case 'copyYoutubeEmbed': | ||||
|           this.copyToClipboard({ content: this.youtubeEmbedUrl, messageOnSuccess: this.$t('Share.YouTube Embed URL copied to clipboard') }) | ||||
|           copyToClipboard(this.youtubeEmbedUrl, { messageOnSuccess: this.$t('Share.YouTube Embed URL copied to clipboard') }) | ||||
|           break | ||||
|         case 'openYoutubeEmbed': | ||||
|           this.openExternalLink(this.youtubeEmbedUrl) | ||||
|           openExternalLink(this.youtubeEmbedUrl) | ||||
|           break | ||||
|         case 'copyInvidious': | ||||
|           this.copyToClipboard({ content: this.invidiousUrl, messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') }) | ||||
|           copyToClipboard(this.invidiousUrl, { messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') }) | ||||
|           break | ||||
|         case 'openInvidious': | ||||
|           this.openExternalLink(this.invidiousUrl) | ||||
|           openExternalLink(this.invidiousUrl) | ||||
|           break | ||||
|         case 'copyYoutubeChannel': | ||||
|           this.copyToClipboard({ content: this.youtubeChannelUrl, messageOnSuccess: this.$t('Share.YouTube Channel URL copied to clipboard') }) | ||||
|           copyToClipboard(this.youtubeChannelUrl, { messageOnSuccess: this.$t('Share.YouTube Channel URL copied to clipboard') }) | ||||
|           break | ||||
|         case 'openYoutubeChannel': | ||||
|           this.openExternalLink(this.youtubeChannelUrl) | ||||
|           openExternalLink(this.youtubeChannelUrl) | ||||
|           break | ||||
|         case 'copyInvidiousChannel': | ||||
|           this.copyToClipboard({ content: this.invidiousChannelUrl, messageOnSuccess: this.$t('Share.Invidious Channel URL copied to clipboard') }) | ||||
|           copyToClipboard(this.invidiousChannelUrl, { messageOnSuccess: this.$t('Share.Invidious Channel URL copied to clipboard') }) | ||||
|           break | ||||
|         case 'openInvidiousChannel': | ||||
|           this.openExternalLink(this.invidiousChannelUrl) | ||||
|           openExternalLink(this.invidiousChannelUrl) | ||||
|           break | ||||
|       } | ||||
|     }, | ||||
|  | @ -508,9 +508,7 @@ export default Vue.extend({ | |||
|       'updateHistory', | ||||
|       'removeFromHistory', | ||||
|       'addVideo', | ||||
|       'removeVideo', | ||||
|       'openExternalLink', | ||||
|       'copyToClipboard' | ||||
|       'removeVideo' | ||||
|     ]) | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import FtFlexBox from '../ft-flex-box/ft-flex-box.vue' | |||
| import FtIconButton from '../ft-icon-button/ft-icon-button.vue' | ||||
| import FtButton from '../ft-button/ft-button.vue' | ||||
| import FtToggleSwitch from '../ft-toggle-switch/ft-toggle-switch.vue' | ||||
| import { mapActions } from 'vuex' | ||||
| import { copyToClipboard, openExternalLink } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'FtShareButton', | ||||
|  | @ -78,42 +78,42 @@ export default Vue.extend({ | |||
|   methods: { | ||||
| 
 | ||||
|     openInvidious() { | ||||
|       this.openExternalLink(this.getFinalUrl(this.invidiousURL)) | ||||
|       openExternalLink(this.getFinalUrl(this.invidiousURL)) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|     copyInvidious() { | ||||
|       this.copyToClipboard({ content: this.getFinalUrl(this.invidiousURL), messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') }) | ||||
|       copyToClipboard(this.getFinalUrl(this.invidiousURL), { messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') }) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|     openYoutube() { | ||||
|       this.openExternalLink(this.getFinalUrl(this.youtubeURL)) | ||||
|       openExternalLink(this.getFinalUrl(this.youtubeURL)) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|     copyYoutube() { | ||||
|       this.copyToClipboard({ content: this.getFinalUrl(this.youtubeShareURL), messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') }) | ||||
|       copyToClipboard(this.getFinalUrl(this.youtubeShareURL), { messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') }) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|     openYoutubeEmbed() { | ||||
|       this.openExternalLink(this.getFinalUrl(this.youtubeEmbedURL)) | ||||
|       openExternalLink(this.getFinalUrl(this.youtubeEmbedURL)) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|     copyYoutubeEmbed() { | ||||
|       this.copyToClipboard({ content: this.getFinalUrl(this.youtubeEmbedURL), messageOnSuccess: this.$t('Share.YouTube Embed URL copied to clipboard') }) | ||||
|       copyToClipboard(this.getFinalUrl(this.youtubeEmbedURL), { messageOnSuccess: this.$t('Share.YouTube Embed URL copied to clipboard') }) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|     openInvidiousEmbed() { | ||||
|       this.openExternalLink(this.getFinalUrl(this.invidiousEmbedURL)) | ||||
|       openExternalLink(this.getFinalUrl(this.invidiousEmbedURL)) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|     copyInvidiousEmbed() { | ||||
|       this.copyToClipboard({ content: this.getFinalUrl(this.invidiousEmbedURL), messageOnSuccess: this.$t('Share.Invidious Embed URL copied to clipboard') }) | ||||
|       copyToClipboard(this.getFinalUrl(this.invidiousEmbedURL), { messageOnSuccess: this.$t('Share.Invidious Embed URL copied to clipboard') }) | ||||
|       this.$refs.iconButton.hideDropdown() | ||||
|     }, | ||||
| 
 | ||||
|  | @ -126,11 +126,6 @@ export default Vue.extend({ | |||
|         return this.includeTimestamp ? `${url}?t=${this.getTimestamp()}` : url | ||||
|       } | ||||
|       return this.includeTimestamp ? `${url}&t=${this.getTimestamp()}` : url | ||||
|     }, | ||||
| 
 | ||||
|     ...mapActions([ | ||||
|       'openExternalLink', | ||||
|       'copyToClipboard' | ||||
|     ]) | ||||
|     } | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -128,7 +128,6 @@ export default Vue.extend({ | |||
|     }, | ||||
| 
 | ||||
|     ...mapActions([ | ||||
|       'openExternalLink', | ||||
|       'updateSponsorBlockSponsor', | ||||
|       'updateSponsorBlockSelfPromo', | ||||
|       'updateSponsorBlockInteraction', | ||||
|  |  | |||
|  | @ -1,7 +1,7 @@ | |||
| import Vue from 'vue' | ||||
| import { mapActions } from 'vuex' | ||||
| import FtListDropdown from '../ft-list-dropdown/ft-list-dropdown.vue' | ||||
| import i18n from '../../i18n/index' | ||||
| import { copyToClipboard, openExternalLink } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'PlaylistInfo', | ||||
|  | @ -110,16 +110,16 @@ export default Vue.extend({ | |||
| 
 | ||||
|       switch (method) { | ||||
|         case 'copyYoutube': | ||||
|           this.copyToClipboard({ content: youtubeUrl, messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') }) | ||||
|           copyToClipboard(youtubeUrl, { messageOnSuccess: this.$t('Share.YouTube URL copied to clipboard') }) | ||||
|           break | ||||
|         case 'openYoutube': | ||||
|           this.openExternalLink(youtubeUrl) | ||||
|           openExternalLink(youtubeUrl) | ||||
|           break | ||||
|         case 'copyInvidious': | ||||
|           this.copyToClipboard({ content: invidiousUrl, messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') }) | ||||
|           copyToClipboard(invidiousUrl, { messageOnSuccess: this.$t('Share.Invidious URL copied to clipboard') }) | ||||
|           break | ||||
|         case 'openInvidious': | ||||
|           this.openExternalLink(invidiousUrl) | ||||
|           openExternalLink(invidiousUrl) | ||||
|           break | ||||
|       } | ||||
|     }, | ||||
|  | @ -139,11 +139,6 @@ export default Vue.extend({ | |||
| 
 | ||||
|     goToChannel: function () { | ||||
|       this.$router.push({ path: `/channel/${this.channelId}` }) | ||||
|     }, | ||||
| 
 | ||||
|     ...mapActions([ | ||||
|       'openExternalLink', | ||||
|       'copyToClipboard' | ||||
|     ]) | ||||
|     } | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -6,7 +6,7 @@ import FtSelect from '../../components/ft-select/ft-select.vue' | |||
| import FtTimestampCatcher from '../../components/ft-timestamp-catcher/ft-timestamp-catcher.vue' | ||||
| import autolinker from 'autolinker' | ||||
| import ytcm from '@freetube/yt-comment-scraper' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { copyToClipboard, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'WatchVideoComments', | ||||
|  | @ -166,7 +166,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendFallback && this.backendPreference === 'local') { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -186,7 +186,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendFallback && this.backendPreference === 'local') { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -293,7 +293,7 @@ export default Vue.extend({ | |||
|         console.error(xhr) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: xhr.responseText }) | ||||
|           copyToClipboard(xhr.responseText) | ||||
|         }) | ||||
|         if (this.backendFallback && this.backendPreference === 'invidious') { | ||||
|           showToast(this.$t('Falling back to local API')) | ||||
|  | @ -341,7 +341,7 @@ export default Vue.extend({ | |||
|         console.error(xhr) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${xhr.responseText}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: xhr.responseText }) | ||||
|           copyToClipboard(xhr.responseText) | ||||
|         }) | ||||
|         this.isLoading = false | ||||
|       }) | ||||
|  | @ -353,8 +353,7 @@ export default Vue.extend({ | |||
| 
 | ||||
|     ...mapActions([ | ||||
|       'toLocalePublicationString', | ||||
|       'invidiousAPICall', | ||||
|       'copyToClipboard' | ||||
|       'invidiousAPICall' | ||||
|     ]) | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ import FtIconButton from '../ft-icon-button/ft-icon-button.vue' | |||
| import FtShareButton from '../ft-share-button/ft-share-button.vue' | ||||
| import { MAIN_PROFILE_ID } from '../../../constants' | ||||
| import i18n from '../../i18n/index' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { openExternalLink, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'WatchVideoInfo', | ||||
|  | @ -430,7 +430,7 @@ export default Vue.extend({ | |||
|       const extension = this.grabExtensionFromUrl(linkName) | ||||
| 
 | ||||
|       if (this.downloadBehavior === 'open') { | ||||
|         this.openExternalLink(url) | ||||
|         openExternalLink(url) | ||||
|       } else { | ||||
|         this.downloadMedia({ | ||||
|           url: url, | ||||
|  | @ -491,7 +491,6 @@ export default Vue.extend({ | |||
|       'updateProfile', | ||||
|       'addVideo', | ||||
|       'removeVideo', | ||||
|       'openExternalLink', | ||||
|       'downloadMedia' | ||||
|     ]) | ||||
|   } | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import FtLoader from '../ft-loader/ft-loader.vue' | |||
| import FtCard from '../ft-card/ft-card.vue' | ||||
| import FtFlexBox from '../ft-flex-box/ft-flex-box.vue' | ||||
| import FtListVideo from '../ft-list-video/ft-list-video.vue' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { copyToClipboard, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'WatchVideoPlaylist', | ||||
|  | @ -284,7 +284,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'local' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -316,7 +316,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'invidious' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Local API')) | ||||
|  | @ -350,8 +350,7 @@ export default Vue.extend({ | |||
| 
 | ||||
|     ...mapActions([ | ||||
|       'ytGetPlaylistInfo', | ||||
|       'invidiousGetPlaylistInfo', | ||||
|       'copyToClipboard' | ||||
|       'invidiousGetPlaylistInfo' | ||||
|     ]) | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -1,4 +1,6 @@ | |||
| import { IpcChannels } from '../../constants' | ||||
| import FtToastEvents from '../components/ft-toast/ft-toast-events' | ||||
| import i18n from '../i18n/index' | ||||
| 
 | ||||
| export const colors = [ | ||||
|   { name: 'Red', value: '#d50000' }, | ||||
|  | @ -157,3 +159,40 @@ export function buildVTTFileLocally(storyboard) { | |||
| export function showToast(message, time = null, action = null) { | ||||
|   FtToastEvents.$emit('toast-open', message, time, action) | ||||
| } | ||||
| 
 | ||||
| /** | ||||
|    * This writes to the clipboard. If an error occurs during the copy, | ||||
|    * a toast with the error is shown. If the copy is successful and | ||||
|    * there is a success message, a toast with that message is shown. | ||||
|    * @param {string} content the content to be copied to the clipboard | ||||
|    * @param {string} messageOnSuccess the message to be displayed as a toast when the copy succeeds (optional) | ||||
|    * @param {string} messageOnError the message to be displayed as a toast when the copy fails (optional) | ||||
|    */ | ||||
| export async function copyToClipboard(content, { messageOnSuccess = null, messageOnError = null }) { | ||||
|   if (navigator.clipboard !== undefined && window.isSecureContext) { | ||||
|     try { | ||||
|       await navigator.clipboard.writeText(content) | ||||
|       if (messageOnSuccess !== null) { | ||||
|         showToast(messageOnSuccess) | ||||
|       } | ||||
|     } catch (error) { | ||||
|       console.error(`Failed to copy ${content} to clipboard`, error) | ||||
|       if (messageOnError !== null) { | ||||
|         showToast(`${messageOnError}: ${error}`, 5000) | ||||
|       } else { | ||||
|         showToast(`${i18n.t('Clipboard.Copy failed')}: ${error}`, 5000) | ||||
|       } | ||||
|     } | ||||
|   } else { | ||||
|     showToast(i18n.t('Clipboard.Cannot access clipboard without a secure connection'), 5000) | ||||
|   } | ||||
| } | ||||
| 
 | ||||
| export function openExternalLink(url) { | ||||
|   if (process.env.IS_ELECTRON) { | ||||
|     const ipcRenderer = require('electron').ipcRenderer | ||||
|     ipcRenderer.send(IpcChannels.OPEN_EXTERNAL_LINK, url) | ||||
|   } else { | ||||
|     window.open(url, '_blank') | ||||
|   } | ||||
| } | ||||
|  |  | |||
|  | @ -4,7 +4,7 @@ import path from 'path' | |||
| import i18n from '../../i18n/index' | ||||
| 
 | ||||
| import { IpcChannels } from '../../../constants' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { openExternalLink, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| const state = { | ||||
|   isSideNavOpen: false, | ||||
|  | @ -117,15 +117,6 @@ async function invokeIRC(context, IRCtype, webCbk, payload = null) { | |||
| } | ||||
| 
 | ||||
| const actions = { | ||||
|   openExternalLink (_, url) { | ||||
|     if (process.env.IS_ELECTRON) { | ||||
|       const ipcRenderer = require('electron').ipcRenderer | ||||
|       ipcRenderer.send(IpcChannels.OPEN_EXTERNAL_LINK, url) | ||||
|     } else { | ||||
|       window.open(url, '_blank') | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   replaceFilenameForbiddenChars(_, filenameOriginal) { | ||||
|     let filenameNew = filenameOriginal | ||||
|     let forbiddenChars = {} | ||||
|  | @ -159,44 +150,16 @@ const actions = { | |||
|     return filenameNew | ||||
|   }, | ||||
| 
 | ||||
|   /** | ||||
|    * This writes to the clipboard. If an error occurs during the copy, | ||||
|    * a toast with the error is shown. If the copy is successful and | ||||
|    * there is a success message, a toast with that message is shown. | ||||
|    * @param {string} content the content to be copied to the clipboard | ||||
|    * @param {string} messageOnSuccess the message to be displayed as a toast when the copy succeeds (optional) | ||||
|    * @param {string} messageOnError the message to be displayed as a toast when the copy fails (optional) | ||||
|    */ | ||||
|   async copyToClipboard ({ dispatch }, { content, messageOnSuccess, messageOnError }) { | ||||
|     if (navigator.clipboard !== undefined && window.isSecureContext) { | ||||
|       try { | ||||
|         await navigator.clipboard.writeText(content) | ||||
|         if (messageOnSuccess !== undefined) { | ||||
|           showToast(messageOnSuccess) | ||||
|         } | ||||
|       } catch (error) { | ||||
|         console.error(`Failed to copy ${content} to clipboard`, error) | ||||
|         if (messageOnError !== undefined) { | ||||
|           showToast(`${messageOnError}: ${error}`, 5000) | ||||
|         } else { | ||||
|           showToast(`${i18n.t('Clipboard.Copy failed')}: ${error}`, 5000) | ||||
|         } | ||||
|       } | ||||
|     } else { | ||||
|       showToast(i18n.t('Clipboard.Cannot access clipboard without a secure connection'), 5000) | ||||
|     } | ||||
|   }, | ||||
| 
 | ||||
|   async downloadMedia({ rootState, dispatch }, { url, title, extension, fallingBackPath }) { | ||||
|     if (!process.env.IS_ELECTRON) { | ||||
|       openExternalLink(url) | ||||
|       return | ||||
|     } | ||||
| 
 | ||||
|     const fileName = `${await dispatch('replaceFilenameForbiddenChars', title)}.${extension}` | ||||
|     const errorMessage = i18n.t('Downloading failed', { videoTitle: title }) | ||||
|     let folderPath = rootState.settings.downloadFolderPath | ||||
| 
 | ||||
|     if (!process.env.IS_ELECTRON) { | ||||
|       dispatch('openExternalLink', url) | ||||
|       return | ||||
|     } | ||||
| 
 | ||||
|     if (folderPath === '') { | ||||
|       const options = { | ||||
|         defaultPath: fileName, | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ import ytch from 'yt-channel-info' | |||
| import autolinker from 'autolinker' | ||||
| import { MAIN_PROFILE_ID } from '../../../constants' | ||||
| import i18n from '../../i18n/index' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { copyToClipboard, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'Search', | ||||
|  | @ -308,7 +308,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'local' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -334,7 +334,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'local' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -353,7 +353,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | @ -403,7 +403,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err.responseJSON.error}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err.responseJSON.error }) | ||||
|           copyToClipboard(err.responseJSON.error) | ||||
|         }) | ||||
|         this.isLoading = false | ||||
|       }) | ||||
|  | @ -427,7 +427,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | @ -449,7 +449,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'local' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -468,7 +468,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|       }) | ||||
|     }, | ||||
|  | @ -490,7 +490,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err.responseJSON.error}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err.responseJSON.error }) | ||||
|           copyToClipboard(err.responseJSON.error) | ||||
|         }) | ||||
|         if (this.backendPreference === 'invidious' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Local API')) | ||||
|  | @ -527,7 +527,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err.responseJSON.error}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err.responseJSON.error }) | ||||
|           copyToClipboard(err.responseJSON.error) | ||||
|         }) | ||||
|         if (this.backendPreference === 'invidious' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Local API')) | ||||
|  | @ -680,7 +680,7 @@ export default Vue.extend({ | |||
|           console.error(err) | ||||
|           const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err }) | ||||
|             copyToClipboard(err) | ||||
|           }) | ||||
|           if (this.backendPreference === 'local' && this.backendFallback) { | ||||
|             showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -698,7 +698,7 @@ export default Vue.extend({ | |||
|           console.error(err) | ||||
|           const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err }) | ||||
|             copyToClipboard(err) | ||||
|           }) | ||||
|         }) | ||||
|       } | ||||
|  | @ -722,7 +722,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'invidious' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Local API')) | ||||
|  | @ -737,8 +737,7 @@ export default Vue.extend({ | |||
|       'updateProfile', | ||||
|       'invidiousGetChannelInfo', | ||||
|       'invidiousAPICall', | ||||
|       'updateSubscriptionDetails', | ||||
|       'copyToClipboard' | ||||
|       'updateSubscriptionDetails' | ||||
|     ]) | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -5,7 +5,7 @@ import FtLoader from '../../components/ft-loader/ft-loader.vue' | |||
| import FtCard from '../../components/ft-card/ft-card.vue' | ||||
| import FtElementList from '../../components/ft-element-list/ft-element-list.vue' | ||||
| import { calculateLengthInSeconds } from '@freetube/yt-trending-scraper/src/HtmlParser' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { copyToClipboard, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'Search', | ||||
|  | @ -201,7 +201,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'local' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -262,7 +262,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'invidious' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Local API')) | ||||
|  | @ -316,8 +316,7 @@ export default Vue.extend({ | |||
| 
 | ||||
|     ...mapActions([ | ||||
|       'ytSearch', | ||||
|       'invidiousAPICall', | ||||
|       'copyToClipboard' | ||||
|       'invidiousAPICall' | ||||
|     ]) | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -10,7 +10,7 @@ import FtChannelBubble from '../../components/ft-channel-bubble/ft-channel-bubbl | |||
| 
 | ||||
| import ytch from 'yt-channel-info' | ||||
| import { MAIN_PROFILE_ID } from '../../../constants' | ||||
| import { calculatePublishedDate, showToast } from '../../helpers/utils' | ||||
| import { calculatePublishedDate, copyToClipboard, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'Subscriptions', | ||||
|  | @ -274,7 +274,7 @@ export default Vue.extend({ | |||
|           console.error(err) | ||||
|           const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err }) | ||||
|             copyToClipboard(err) | ||||
|           }) | ||||
|           switch (failedAttempts) { | ||||
|             case 0: | ||||
|  | @ -314,7 +314,7 @@ export default Vue.extend({ | |||
|         console.error(error) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${error}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: error }) | ||||
|           copyToClipboard(error) | ||||
|         }) | ||||
|         switch (failedAttempts) { | ||||
|           case 0: | ||||
|  | @ -351,7 +351,7 @@ export default Vue.extend({ | |||
|           console.error(err) | ||||
|           const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err.responseText}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err.responseText }) | ||||
|             copyToClipboard(err.responseText) | ||||
|           }) | ||||
|           switch (failedAttempts) { | ||||
|             case 0: | ||||
|  | @ -391,7 +391,7 @@ export default Vue.extend({ | |||
|         console.error(error) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${error}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: error }) | ||||
|           copyToClipboard(error) | ||||
|         }) | ||||
|         switch (failedAttempts) { | ||||
|           case 0: | ||||
|  | @ -467,8 +467,7 @@ export default Vue.extend({ | |||
|       'invidiousAPICall', | ||||
|       'updateShowProgressBar', | ||||
|       'updateProfileSubscriptions', | ||||
|       'updateAllSubscriptionsList', | ||||
|       'copyToClipboard' | ||||
|       'updateAllSubscriptionsList' | ||||
|     ]), | ||||
| 
 | ||||
|     ...mapMutations([ | ||||
|  |  | |||
|  | @ -7,7 +7,7 @@ import FtIconButton from '../../components/ft-icon-button/ft-icon-button.vue' | |||
| import FtFlexBox from '../../components/ft-flex-box/ft-flex-box.vue' | ||||
| 
 | ||||
| import { scrapeTrendingPage } from '@freetube/yt-trending-scraper' | ||||
| import { showToast } from '../../helpers/utils' | ||||
| import { copyToClipboard, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| export default Vue.extend({ | ||||
|   name: 'Trending', | ||||
|  | @ -101,7 +101,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err }) | ||||
|           copyToClipboard(err) | ||||
|         }) | ||||
|         if (this.backendPreference === 'local' && this.backendFallback) { | ||||
|           showToast(this.$t('Falling back to Invidious API')) | ||||
|  | @ -157,7 +157,7 @@ export default Vue.extend({ | |||
|         console.error(err) | ||||
|         const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|         showToast(`${errorMessage}: ${err.responseText}`, 10000, () => { | ||||
|           this.copyToClipboard({ content: err.responseText }) | ||||
|           copyToClipboard(err.responseText) | ||||
|         }) | ||||
| 
 | ||||
|         if (process.env.IS_ELECTRON && (this.backendPreference === 'invidious' && this.backendFallback)) { | ||||
|  | @ -185,8 +185,7 @@ export default Vue.extend({ | |||
|     }, | ||||
| 
 | ||||
|     ...mapActions([ | ||||
|       'invidiousAPICall', | ||||
|       'copyToClipboard' | ||||
|       'invidiousAPICall' | ||||
|     ]) | ||||
|   } | ||||
| }) | ||||
|  |  | |||
|  | @ -15,7 +15,7 @@ import WatchVideoPlaylist from '../../components/watch-video-playlist/watch-vide | |||
| import WatchVideoRecommendations from '../../components/watch-video-recommendations/watch-video-recommendations.vue' | ||||
| import FtAgeRestricted from '../../components/ft-age-restricted/ft-age-restricted.vue' | ||||
| import i18n from '../../i18n/index' | ||||
| import { buildVTTFileLocally, showToast } from '../../helpers/utils' | ||||
| import { buildVTTFileLocally, copyToClipboard, showToast } from '../../helpers/utils' | ||||
| 
 | ||||
| const isDev = process.env.NODE_ENV === 'development' | ||||
| 
 | ||||
|  | @ -628,7 +628,7 @@ export default Vue.extend({ | |||
|         .catch(err => { | ||||
|           const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err }) | ||||
|             copyToClipboard(err) | ||||
|           }) | ||||
|           console.error(err) | ||||
|           if (this.backendPreference === 'local' && this.backendFallback && !err.toString().includes('private')) { | ||||
|  | @ -848,7 +848,7 @@ export default Vue.extend({ | |||
|           console.error(err) | ||||
|           const errorMessage = this.$t('Invidious API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err.responseText}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err.responseText }) | ||||
|             copyToClipboard(err.responseText) | ||||
|           }) | ||||
|           console.error(err) | ||||
|           if (this.backendPreference === 'invidious' && this.backendFallback) { | ||||
|  | @ -1035,7 +1035,7 @@ export default Vue.extend({ | |||
|         .catch(err => { | ||||
|           const errorMessage = this.$t('Local API Error (Click to copy)') | ||||
|           showToast(`${errorMessage}: ${err}`, 10000, () => { | ||||
|             this.copyToClipboard({ content: err }) | ||||
|             copyToClipboard(err) | ||||
|           }) | ||||
|           console.error(err) | ||||
|           if (!process.env.IS_ELECTRON || (this.backendPreference === 'local' && this.backendFallback)) { | ||||
|  | @ -1512,8 +1512,7 @@ export default Vue.extend({ | |||
|       'getUserDataPath', | ||||
|       'ytGetVideoInformation', | ||||
|       'invidiousGetVideoInformation', | ||||
|       'updateSubscriptionDetails', | ||||
|       'copyToClipboard' | ||||
|       'updateSubscriptionDetails' | ||||
|     ]) | ||||
|   } | ||||
| }) | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue