parent
							
								
									fa4dd59f01
								
							
						
					
					
						commit
						c0d0b4dd36
					
				
					 8 changed files with 219 additions and 99 deletions
				
			
		|  | @ -34,5 +34,6 @@ module.exports = [ | |||
|   {id: 'fa-pencil', src: 'node_modules/font-awesome-svg-png/white/svg/pencil.svg', title: 'Compose'}, | ||||
|   {id: 'fa-times', src: 'node_modules/font-awesome-svg-png/white/svg/times.svg', title: 'Close'}, | ||||
|   {id: 'fa-volume-off', src: 'node_modules/font-awesome-svg-png/white/svg/volume-off.svg', title: 'Mute'}, | ||||
|   {id: 'fa-volume-up', src: 'node_modules/font-awesome-svg-png/white/svg/volume-up.svg', title: 'Unmute'} | ||||
|   {id: 'fa-volume-up', src: 'node_modules/font-awesome-svg-png/white/svg/volume-up.svg', title: 'Unmute'}, | ||||
|   {id: 'fa-copy', src: 'node_modules/font-awesome-svg-png/white/svg/copy.svg', title: 'Copy'} | ||||
| ] | ||||
|  |  | |||
|  | @ -15,6 +15,7 @@ | |||
|     flex-direction: column; | ||||
|     align-items: center; | ||||
|     pointer-events: none; | ||||
|     z-index: 100000; | ||||
|   } | ||||
| 
 | ||||
|   .toast-container { | ||||
|  |  | |||
|  | @ -29,3 +29,7 @@ export const importShowStatusOptionsDialog = () => import( | |||
| export const importShowVideoDialog = () => import( | ||||
|   /* webpackChunkName: 'showVideoDialog' */ './creators/showVideoDialog' | ||||
|   ).then(mod => mod.default) | ||||
| 
 | ||||
| export const importShowCopyDialog = () => import( | ||||
|   /* webpackChunkName: 'showCopyDialog' */ './creators/showCopyDialog' | ||||
|   ).then(mod => mod.default) | ||||
|  | @ -10,7 +10,7 @@ | |||
| import ModalDialog from './ModalDialog.html' | ||||
| import { store } from '../../../_store/store' | ||||
| import GenericDialogList from './GenericDialogList.html' | ||||
| import { importShowComposeDialog } from '../asyncDialogs' | ||||
| import { importShowComposeDialog, importShowCopyDialog } from '../asyncDialogs' | ||||
| import { createDialogId } from '../helpers/createDialogId' | ||||
| import { show } from '../helpers/showDialog' | ||||
| import { close } from '../helpers/closeDialog' | ||||
|  | @ -26,7 +26,9 @@ export default { | |||
|     id: createDialogId() | ||||
|   }), | ||||
|   computed: { | ||||
|     // begin account data copypasta | ||||
|     // | ||||
|     // begin copypasta (StatusOptionsDialog.html / AccountProfileOptionsDialog.html) | ||||
|     // | ||||
|     verifyCredentialsId: ({ verifyCredentials }) => verifyCredentials.id, | ||||
|     following: ({ relationship }) => relationship && relationship.following, | ||||
|     followRequested: ({ relationship }) => relationship && relationship.requested, | ||||
|  | @ -42,46 +44,52 @@ export default { | |||
|         ? `Unfollow @${acct}` | ||||
|         : `Follow @${acct}` | ||||
|     }, | ||||
|     followIcon: ({ following, followRequested }) => { | ||||
|       return following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus' | ||||
|     }, | ||||
|     blockLabel: ({ blocking, acct }) => { | ||||
|       return blocking ? `Unblock @${acct}` : `Block @${acct}` | ||||
|     }, | ||||
|     followIcon: ({ following, followRequested }) => ( | ||||
|       following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus' | ||||
|     ), | ||||
|     blockLabel: ({ blocking, acct }) => ( | ||||
|       blocking ? `Unblock @${acct}` : `Block @${acct}` | ||||
|     ), | ||||
|     blockIcon: ({ blocking }) => blocking ? '#fa-unlock' : '#fa-ban', | ||||
|     muteLabel: ({ muting, acct }) => { | ||||
|       return muting ? `Unmute @${acct}` : `Mute @${acct}` | ||||
|     }, | ||||
|     muteLabel: ({ muting, acct }) => ( | ||||
|       muting ? `Unmute @${acct}` : `Mute @${acct}` | ||||
|     ), | ||||
|     muteIcon: ({ muting }) => muting ? '#fa-volume-up' : '#fa-volume-off', | ||||
|     // end account data copypasta | ||||
|     items: ({ blockLabel, blocking, blockIcon, muteLabel, muteIcon, | ||||
|     isUser: ({ accountId, verifyCredentialsId }) => accountId === verifyCredentialsId, | ||||
|     // | ||||
|     // end copypasta (StatusOptionsDialog.html / AccountProfileOptionsDialog.html) | ||||
|     // | ||||
|     items: ({ | ||||
|       blockLabel, blocking, blockIcon, muteLabel, muteIcon, | ||||
|       followLabel, followIcon, following, followRequested, | ||||
|       accountId, verifyCredentialsId, acct }) => { | ||||
|       let isUser = accountId === verifyCredentialsId | ||||
|       return [ | ||||
|         !isUser && { | ||||
|           key: 'mention', | ||||
|           label: `Mention @${acct}`, | ||||
|           icon: '#fa-comments' | ||||
|         }, | ||||
|         !isUser && !blocking && { | ||||
|           key: 'follow', | ||||
|           label: followLabel, | ||||
|           icon: followIcon | ||||
|         }, | ||||
|         !isUser && { | ||||
|           key: 'block', | ||||
|           label: blockLabel, | ||||
|           icon: blockIcon | ||||
|         }, | ||||
|         !isUser && !blocking && { | ||||
|           key: 'mute', | ||||
|           label: muteLabel, | ||||
|           icon: muteIcon | ||||
|         } | ||||
| 
 | ||||
|       ].filter(Boolean) | ||||
|     } | ||||
|       accountId, verifyCredentialsId, acct, isUser | ||||
|     }) => ([ | ||||
|       !isUser && { | ||||
|         key: 'mention', | ||||
|         label: `Mention @${acct}`, | ||||
|         icon: '#fa-comments' | ||||
|       }, | ||||
|       !isUser && !blocking && { | ||||
|         key: 'follow', | ||||
|         label: followLabel, | ||||
|         icon: followIcon | ||||
|       }, | ||||
|       !isUser && { | ||||
|         key: 'block', | ||||
|         label: blockLabel, | ||||
|         icon: blockIcon | ||||
|       }, | ||||
|       !isUser && !blocking && { | ||||
|         key: 'mute', | ||||
|         label: muteLabel, | ||||
|         icon: muteIcon | ||||
|       }, | ||||
|       { | ||||
|         key: 'copy', | ||||
|         label: 'Copy link to account', | ||||
|         icon: '#fa-copy' | ||||
|       } | ||||
|     ].filter(Boolean)) | ||||
|   }, | ||||
|   methods: { | ||||
|     show, | ||||
|  | @ -96,6 +104,8 @@ export default { | |||
|           return this.onBlockClicked() | ||||
|         case 'mute': | ||||
|           return this.onMuteClicked() | ||||
|         case 'copy': | ||||
|           return this.onCopyClicked() | ||||
|       } | ||||
|     }, | ||||
|     async onMentionClicked () { | ||||
|  | @ -121,6 +131,12 @@ export default { | |||
|       let { accountId, muting } = this.get() | ||||
|       this.close() | ||||
|       await setAccountMuted(accountId, !muting, true) | ||||
|     }, | ||||
|     async onCopyClicked () { | ||||
|       let { account } = this.get() | ||||
|       let { url } = account | ||||
|       let showCopyDialog = await importShowCopyDialog() | ||||
|       showCopyDialog(url) | ||||
|     } | ||||
|   }, | ||||
|   components: { | ||||
|  |  | |||
							
								
								
									
										64
									
								
								routes/_components/dialog/components/CopyDialog.html
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								routes/_components/dialog/components/CopyDialog.html
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,64 @@ | |||
| <ModalDialog | ||||
|   {id} | ||||
|   {label} | ||||
|   {title} | ||||
|   background="var(--main-bg)" | ||||
| > | ||||
|   <form class="copy-dialog-form"> | ||||
|     <input value={text} | ||||
|            ref:input | ||||
|     > | ||||
|     <button type="button" on:click="onClick()"> | ||||
|       Copy | ||||
|     </button> | ||||
|   </form> | ||||
| </ModalDialog> | ||||
| <style> | ||||
|   .copy-dialog-form { | ||||
|     display: grid; | ||||
|     grid-template-rows: min-content min-content; | ||||
|     grid-template-columns: 1fr; | ||||
|     grid-gap: 10px; | ||||
|     padding: 10px 20px; | ||||
|     width: 400px; | ||||
|     max-width: calc(100vw - 40px); | ||||
|   } | ||||
| </style> | ||||
| <script> | ||||
|   import ModalDialog from './ModalDialog.html' | ||||
|   import { show } from '../helpers/showDialog' | ||||
|   import { close } from '../helpers/closeDialog' | ||||
|   import { oncreate as onCreateDialog } from '../helpers/onCreateDialog' | ||||
|   import { toast } from '../../../_utils/toast' | ||||
|   import { doubleRAF } from '../../../_utils/doubleRAF' | ||||
| 
 | ||||
|   export default { | ||||
|     oncreate () { | ||||
|       onCreateDialog.call(this) | ||||
|       let { text } = this.get() | ||||
|       let { input } = this.refs | ||||
|       // double raf is to work around a11y-dialog trying to set the input | ||||
|       doubleRAF(() => { | ||||
|         input.focus() | ||||
|         input.setSelectionRange(0, text.length) | ||||
|       }) | ||||
|     }, | ||||
|     methods: { | ||||
|       show, | ||||
|       close, | ||||
|       onClick () { | ||||
|         let { input } = this.refs | ||||
|         input.select() | ||||
|         document.execCommand('copy') | ||||
|         toast.say('Copied to clipboard') | ||||
|         this.close() | ||||
|       } | ||||
|     }, | ||||
|     data: () => ({ | ||||
|       text: '' | ||||
|     }), | ||||
|     components: { | ||||
|       ModalDialog | ||||
|     } | ||||
|   } | ||||
| </script> | ||||
|  | @ -18,24 +18,27 @@ import { oncreate } from '../helpers/onCreateDialog' | |||
| import { setAccountBlocked } from '../../../_actions/block' | ||||
| import { setAccountMuted } from '../../../_actions/mute' | ||||
| import { setStatusPinnedOrUnpinned } from '../../../_actions/pin' | ||||
| import { importShowCopyDialog } from '../asyncDialogs' | ||||
| 
 | ||||
| export default { | ||||
|   oncreate, | ||||
|   computed: { | ||||
|     relationship: ({ $currentAccountRelationship }) => $currentAccountRelationship, | ||||
|     account: ({ $currentAccountProfile }) => $currentAccountProfile, | ||||
|     verifyCredentials: ({ $currentVerifyCredentials }) => $currentVerifyCredentials, | ||||
|     statusId: ({ status }) => status.id, | ||||
|     pinned: ({ status }) => status.pinned, | ||||
|     // begin account data copypasta | ||||
|     verifyCredentialsId: ({ verifyCredentials }) => verifyCredentials.id, | ||||
|     following: ({ relationship }) => relationship && relationship.following, | ||||
|     followRequested: ({ relationship }) => relationship && relationship.requested, | ||||
|     accountId: ({ account }) => account && account.id, | ||||
|     acct: ({ account }) => account.acct, | ||||
|     muting: ({ relationship }) => relationship.muting, | ||||
|     blocking: ({ relationship }) => relationship.blocking, | ||||
|     followLabel: ({ following, followRequested, account, acct }) => { | ||||
|     relationship: ({$currentAccountRelationship}) => $currentAccountRelationship, | ||||
|     account: ({$currentAccountProfile}) => $currentAccountProfile, | ||||
|     verifyCredentials: ({$currentVerifyCredentials}) => $currentVerifyCredentials, | ||||
|     statusId: ({status}) => status.id, | ||||
|     pinned: ({status}) => status.pinned, | ||||
|     // | ||||
|     // begin copypasta (StatusOptionsDialog.html / AccountProfileOptionsDialog.html) | ||||
|     // | ||||
|     verifyCredentialsId: ({verifyCredentials}) => verifyCredentials.id, | ||||
|     following: ({relationship}) => relationship && relationship.following, | ||||
|     followRequested: ({relationship}) => relationship && relationship.requested, | ||||
|     accountId: ({account}) => account && account.id, | ||||
|     acct: ({account}) => account.acct, | ||||
|     muting: ({relationship}) => relationship.muting, | ||||
|     blocking: ({relationship}) => relationship.blocking, | ||||
|     followLabel: ({following, followRequested, account, acct}) => { | ||||
|       if (typeof following === 'undefined' || !account) { | ||||
|         return '' | ||||
|       } | ||||
|  | @ -43,51 +46,57 @@ export default { | |||
|         ? `Unfollow @${acct}` | ||||
|         : `Follow @${acct}` | ||||
|     }, | ||||
|     followIcon: ({ following, followRequested }) => { | ||||
|       return following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus' | ||||
|     }, | ||||
|     blockLabel: ({ blocking, acct }) => { | ||||
|       return blocking ? `Unblock @${acct}` : `Block @${acct}` | ||||
|     }, | ||||
|     blockIcon: ({ blocking }) => blocking ? '#fa-unlock' : '#fa-ban', | ||||
|     muteLabel: ({ muting, acct }) => { | ||||
|       return muting ? `Unmute @${acct}` : `Mute @${acct}` | ||||
|     }, | ||||
|     muteIcon: ({ muting }) => muting ? '#fa-volume-up' : '#fa-volume-off', | ||||
|     // end account data copypasta | ||||
|     isUser: ({ accountId, verifyCredentialsId }) => accountId === verifyCredentialsId, | ||||
|     pinLabel: ({ pinned, isUser }) => isUser ? (pinned ? 'Unpin from profile' : 'Pin to profile') : '', | ||||
|     items: ({ blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon, | ||||
|       following, followRequested, pinLabel, isUser }) => { | ||||
|       return [ | ||||
|         isUser && { | ||||
|           key: 'delete', | ||||
|           label: 'Delete', | ||||
|           icon: '#fa-trash' | ||||
|         }, | ||||
|         isUser && { | ||||
|           key: 'pin', | ||||
|           label: pinLabel, | ||||
|           icon: '#fa-thumb-tack' | ||||
|         }, | ||||
|         !isUser && !blocking && { | ||||
|           key: 'follow', | ||||
|           label: followLabel, | ||||
|           icon: followIcon | ||||
|         }, | ||||
|         !isUser && { | ||||
|           key: 'block', | ||||
|           label: blockLabel, | ||||
|           icon: blockIcon | ||||
|         }, | ||||
|         !isUser && !blocking && { | ||||
|           key: 'mute', | ||||
|           label: muteLabel, | ||||
|           icon: muteIcon | ||||
|         } | ||||
| 
 | ||||
|       ].filter(Boolean) | ||||
|     } | ||||
|     followIcon: ({following, followRequested}) => ( | ||||
|       following ? '#fa-user-times' : followRequested ? '#fa-hourglass' : '#fa-user-plus' | ||||
|     ), | ||||
|     blockLabel: ({blocking, acct}) => ( | ||||
|       blocking ? `Unblock @${acct}` : `Block @${acct}` | ||||
|     ), | ||||
|     blockIcon: ({blocking}) => blocking ? '#fa-unlock' : '#fa-ban', | ||||
|     muteLabel: ({muting, acct}) => ( | ||||
|       muting ? `Unmute @${acct}` : `Mute @${acct}` | ||||
|     ), | ||||
|     muteIcon: ({muting}) => muting ? '#fa-volume-up' : '#fa-volume-off', | ||||
|     isUser: ({accountId, verifyCredentialsId}) => accountId === verifyCredentialsId, | ||||
|     // | ||||
|     // end copypasta (StatusOptionsDialog.html / AccountProfileOptionsDialog.html) | ||||
|     // | ||||
|     pinLabel: ({pinned, isUser}) => isUser ? (pinned ? 'Unpin from profile' : 'Pin to profile') : '', | ||||
|     items: ({ | ||||
|       blockLabel, blocking, blockIcon, muteLabel, muteIcon, followLabel, followIcon, | ||||
|       following, followRequested, pinLabel, isUser | ||||
|     }) => ([ | ||||
|       isUser && { | ||||
|         key: 'delete', | ||||
|         label: 'Delete', | ||||
|         icon: '#fa-trash' | ||||
|       }, | ||||
|       isUser && { | ||||
|         key: 'pin', | ||||
|         label: pinLabel, | ||||
|         icon: '#fa-thumb-tack' | ||||
|       }, | ||||
|       !isUser && !blocking && { | ||||
|         key: 'follow', | ||||
|         label: followLabel, | ||||
|         icon: followIcon | ||||
|       }, | ||||
|       !isUser && { | ||||
|         key: 'block', | ||||
|         label: blockLabel, | ||||
|         icon: blockIcon | ||||
|       }, | ||||
|       !isUser && !blocking && { | ||||
|         key: 'mute', | ||||
|         label: muteLabel, | ||||
|         icon: muteIcon | ||||
|       }, | ||||
|       { | ||||
|         key: 'copy', | ||||
|         label: 'Copy link to toot', | ||||
|         icon: '#fa-copy' | ||||
|       } | ||||
|     ].filter(Boolean)) | ||||
|   }, | ||||
|   components: { | ||||
|     ModalDialog, | ||||
|  | @ -109,6 +118,8 @@ export default { | |||
|           return this.onBlockClicked() | ||||
|         case 'mute': | ||||
|           return this.onMuteClicked() | ||||
|         case 'copy': | ||||
|           return this.onCopyClicked() | ||||
|       } | ||||
|     }, | ||||
|     async onDeleteClicked () { | ||||
|  | @ -135,6 +146,12 @@ export default { | |||
|       let { accountId, muting } = this.get() | ||||
|       this.close() | ||||
|       await setAccountMuted(accountId, !muting, true) | ||||
|     }, | ||||
|     async onCopyClicked () { | ||||
|       let { status } = this.get() | ||||
|       let { url } = status | ||||
|       let showCopyDialog = await importShowCopyDialog() | ||||
|       showCopyDialog(url) | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  |  | |||
							
								
								
									
										16
									
								
								routes/_components/dialog/creators/showCopyDialog.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								routes/_components/dialog/creators/showCopyDialog.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,16 @@ | |||
| import CopyDialog from '../components/CopyDialog.html' | ||||
| import { createDialogElement } from '../helpers/createDialogElement' | ||||
| import { createDialogId } from '../helpers/createDialogId' | ||||
| 
 | ||||
| export default function showCopyDialog (text) { | ||||
|   let dialog = new CopyDialog({ | ||||
|     target: createDialogElement(), | ||||
|     data: { | ||||
|       id: createDialogId(), | ||||
|       label: 'Copy dialog', | ||||
|       title: 'Copy link', | ||||
|       text | ||||
|     } | ||||
|   }) | ||||
|   dialog.show() | ||||
| } | ||||
|  | @ -117,6 +117,7 @@ if (!localStorage.store_currentInstance) { | |||
| <symbol id="fa-times" viewBox="0 0 1792 1792"><title>Close</title><path d="M1490 1322q0 40-28 68l-136 136q-28 28-68 28t-68-28l-294-294-294 294q-28 28-68 28t-68-28l-136-136q-28-28-28-68t28-68l294-294-294-294q-28-28-28-68t28-68l136-136q28-28 68-28t68 28l294 294 294-294q28-28 68-28t68 28l136 136q28 28 28 68t-28 68l-294 294 294 294q28 28 28 68z"></path></symbol> | ||||
| <symbol id="fa-volume-off" viewBox="0 0 1792 1792"><title>Mute</title><path d="M1280 352v1088q0 26-19 45t-45 19-45-19l-333-333H576q-26 0-45-19t-19-45V704q0-26 19-45t45-19h262l333-333q19-19 45-19t45 19 19 45z"></path></symbol> | ||||
| <symbol id="fa-volume-up" viewBox="0 0 1792 1792"><title>Unmute</title><path d="M832 352v1088q0 26-19 45t-45 19-45-19l-333-333H128q-26 0-45-19t-19-45V704q0-26 19-45t45-19h262l333-333q19-19 45-19t45 19 19 45zm384 544q0 76-42.5 141.5T1061 1131q-10 5-25 5-26 0-45-18.5t-19-45.5q0-21 12-35.5t29-25 34-23 29-36 12-56.5-12-56.5-29-36-34-23-29-25-12-35.5q0-27 19-45.5t45-18.5q15 0 25 5 70 27 112.5 93t42.5 142zm256 0q0 153-85 282.5T1162 1367q-13 5-25 5-27 0-46-19t-19-45q0-39 39-59 56-29 76-44 74-54 115.5-135.5T1344 896t-41.5-173.5T1187 587q-20-15-76-44-39-20-39-59 0-26 19-45t45-19q13 0 26 5 140 59 225 188.5t85 282.5zm256 0q0 230-127 422.5T1263 1602q-13 5-26 5-26 0-45-19t-19-45q0-36 39-59 7-4 22.5-10.5t22.5-10.5q46-25 82-51 123-91 192-227t69-289-69-289-192-227q-36-26-82-51-7-4-22.5-10.5T1212 308q-39-23-39-59 0-26 19-45t45-19q13 0 26 5 211 91 338 283.5T1728 896z"></path></symbol> | ||||
| <symbol id="fa-copy" viewBox="0 0 1792 1792"><title>Copy</title><path d="M1696 384q40 0 68 28t28 68v1216q0 40-28 68t-68 28H736q-40 0-68-28t-28-68v-288H96q-40 0-68-28t-28-68V640q0-40 20-88t48-76L476 68q28-28 76-48t88-20h416q40 0 68 28t28 68v328q68-40 128-40h416zm-544 213L853 896h299V597zM512 213L213 512h299V213zm196 647l316-316V128H640v416q0 40-28 68t-68 28H128v640h512v-256q0-40 20-88t48-76zm956 804V512h-384v416q0 40-28 68t-68 28H768v640h896z"></path></symbol> | ||||
| </svg><!-- end insert svg here --> | ||||
|   </svg> | ||||
|   <!-- The application will be rendered inside this element, | ||||
|  |  | |||
		Loading…
	
	Add table
		
		Reference in a new issue