enhance: show recipients of notes with specified visibility (#8949)
* enhance: reusable visibility component * rename renote tooltip component The tooltip that is used for renotes can be used in other cases as well. * add tooltip for specified recipients * add changelog entry * Update visibility.vue Co-authored-by: syuilo <Syuilotan@yahoo.co.jp>
This commit is contained in:
		
							parent
							
								
									e560601815
								
							
						
					
					
						commit
						a1b8587ab2
					
				
					 7 changed files with 62 additions and 49 deletions
				
			
		|  | @ -33,6 +33,7 @@ You should also include the user name that made the change. | ||||||
| - Client: Word mute also checks content warnings @Johann150 | - Client: Word mute also checks content warnings @Johann150 | ||||||
| - Client: メニューからページをリロードできるように @syuilo | - Client: メニューからページをリロードできるように @syuilo | ||||||
| - Client: Improve emoji picker performance @syuilo | - Client: Improve emoji picker performance @syuilo | ||||||
|  | - Client: For notes with specified visibility, show recipients when hovering over visibility symbol. @Johann150 | ||||||
| - Client: Make widgets available again on a tablet @syuilo | - Client: Make widgets available again on a tablet @syuilo | ||||||
| - ユーザーにモデレーションメモを残せる機能 @syuilo | - ユーザーにモデレーションメモを残せる機能 @syuilo | ||||||
| - Make possible to delete an account by admin @syuilo | - Make possible to delete an account by admin @syuilo | ||||||
|  |  | ||||||
|  | @ -26,12 +26,7 @@ | ||||||
| 				<i v-if="isMyRenote" class="fas fa-ellipsis-h dropdownIcon"></i> | 				<i v-if="isMyRenote" class="fas fa-ellipsis-h dropdownIcon"></i> | ||||||
| 				<MkTime :time="note.createdAt"/> | 				<MkTime :time="note.createdAt"/> | ||||||
| 			</button> | 			</button> | ||||||
| 			<span v-if="note.visibility !== 'public'" class="visibility"> | 			<MkVisibility :note="note"/> | ||||||
| 				<i v-if="note.visibility === 'home'" class="fas fa-home"></i> |  | ||||||
| 				<i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i> |  | ||||||
| 				<i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i> |  | ||||||
| 			</span> |  | ||||||
| 			<span v-if="note.localOnly" class="localOnly"><i class="fas fa-biohazard"></i></span> |  | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<article class="article" @contextmenu.stop="onContextmenu"> | 	<article class="article" @contextmenu.stop="onContextmenu"> | ||||||
|  | @ -43,12 +38,9 @@ | ||||||
| 						<MkUserName :user="appearNote.user"/> | 						<MkUserName :user="appearNote.user"/> | ||||||
| 					</MkA> | 					</MkA> | ||||||
| 					<span v-if="appearNote.user.isBot" class="is-bot">bot</span> | 					<span v-if="appearNote.user.isBot" class="is-bot">bot</span> | ||||||
| 					<span v-if="appearNote.visibility !== 'public'" class="visibility"> | 					<div class="info"> | ||||||
| 						<i v-if="appearNote.visibility === 'home'" class="fas fa-home"></i> | 						<MkVisibility :note="appearNote"/> | ||||||
| 						<i v-else-if="appearNote.visibility === 'followers'" class="fas fa-unlock"></i> | 					</div> | ||||||
| 						<i v-else-if="appearNote.visibility === 'specified'" class="fas fa-envelope"></i> |  | ||||||
| 					</span> |  | ||||||
| 					<span v-if="appearNote.localOnly" class="localOnly"><i class="fas fa-biohazard"></i></span> |  | ||||||
| 				</div> | 				</div> | ||||||
| 				<div class="username"><MkAcct :user="appearNote.user"/></div> | 				<div class="username"><MkAcct :user="appearNote.user"/></div> | ||||||
| 				<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/> | 				<MkInstanceTicker v-if="showTicker" class="ticker" :instance="appearNote.user.instance"/> | ||||||
|  | @ -134,6 +126,7 @@ import XPoll from './poll.vue'; | ||||||
| import XRenoteButton from './renote-button.vue'; | import XRenoteButton from './renote-button.vue'; | ||||||
| import MkUrlPreview from '@/components/url-preview.vue'; | import MkUrlPreview from '@/components/url-preview.vue'; | ||||||
| import MkInstanceTicker from '@/components/instance-ticker.vue'; | import MkInstanceTicker from '@/components/instance-ticker.vue'; | ||||||
|  | import MkVisibility from '@/components/visibility.vue'; | ||||||
| import { pleaseLogin } from '@/scripts/please-login'; | import { pleaseLogin } from '@/scripts/please-login'; | ||||||
| import { checkWordMute } from '@/scripts/check-word-mute'; | import { checkWordMute } from '@/scripts/check-word-mute'; | ||||||
| import { userPage } from '@/filters/user'; | import { userPage } from '@/filters/user'; | ||||||
|  | @ -388,14 +381,6 @@ if (appearNote.replyId) { | ||||||
| 					margin-right: 4px; | 					margin-right: 4px; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 			> .visibility { |  | ||||||
| 				margin-left: 8px; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			> .localOnly { |  | ||||||
| 				margin-left: 8px; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  | @ -441,6 +426,10 @@ if (appearNote.replyId) { | ||||||
| 						border: solid 0.5px var(--divider); | 						border: solid 0.5px var(--divider); | ||||||
| 						border-radius: 4px; | 						border-radius: 4px; | ||||||
| 					} | 					} | ||||||
|  | 
 | ||||||
|  | 					> .info { | ||||||
|  | 						float: right; | ||||||
|  | 					} | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 		} | 		} | ||||||
|  |  | ||||||
|  | @ -9,12 +9,7 @@ | ||||||
| 		<MkA class="created-at" :to="notePage(note)"> | 		<MkA class="created-at" :to="notePage(note)"> | ||||||
| 			<MkTime :time="note.createdAt"/> | 			<MkTime :time="note.createdAt"/> | ||||||
| 		</MkA> | 		</MkA> | ||||||
| 		<span v-if="note.visibility !== 'public'" class="visibility"> | 		<MkVisibility :note="note"/> | ||||||
| 			<i v-if="note.visibility === 'home'" class="fas fa-home"></i> |  | ||||||
| 			<i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i> |  | ||||||
| 			<i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i> |  | ||||||
| 		</span> |  | ||||||
| 		<span v-if="note.localOnly" class="localOnly"><i class="fas fa-biohazard"></i></span> |  | ||||||
| 	</div> | 	</div> | ||||||
| </header> | </header> | ||||||
| </template> | </template> | ||||||
|  | @ -22,6 +17,7 @@ | ||||||
| <script lang="ts" setup> | <script lang="ts" setup> | ||||||
| import { } from 'vue'; | import { } from 'vue'; | ||||||
| import * as misskey from 'misskey-js'; | import * as misskey from 'misskey-js'; | ||||||
|  | import MkVisibility from '@/components/visibility.vue'; | ||||||
| import { notePage } from '@/filters/note'; | import { notePage } from '@/filters/note'; | ||||||
| import { userPage } from '@/filters/user'; | import { userPage } from '@/filters/user'; | ||||||
| 
 | 
 | ||||||
|  | @ -74,14 +70,6 @@ defineProps<{ | ||||||
| 		flex-shrink: 0; | 		flex-shrink: 0; | ||||||
| 		margin-left: auto; | 		margin-left: auto; | ||||||
| 		font-size: 0.9em; | 		font-size: 0.9em; | ||||||
| 
 |  | ||||||
| 		> .visibility { |  | ||||||
| 			margin-left: 8px; |  | ||||||
| 		} |  | ||||||
| 
 |  | ||||||
| 		> .localOnly { |  | ||||||
| 			margin-left: 8px; |  | ||||||
| 		} |  | ||||||
| 	} | 	} | ||||||
| } | } | ||||||
| </style> | </style> | ||||||
|  |  | ||||||
|  | @ -28,12 +28,7 @@ | ||||||
| 				<i v-if="isMyRenote" class="fas fa-ellipsis-h dropdownIcon"></i> | 				<i v-if="isMyRenote" class="fas fa-ellipsis-h dropdownIcon"></i> | ||||||
| 				<MkTime :time="note.createdAt"/> | 				<MkTime :time="note.createdAt"/> | ||||||
| 			</button> | 			</button> | ||||||
| 			<span v-if="note.visibility !== 'public'" class="visibility"> | 			<MkVisibility :note="note"/> | ||||||
| 				<i v-if="note.visibility === 'home'" class="fas fa-home"></i> |  | ||||||
| 				<i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i> |  | ||||||
| 				<i v-else-if="note.visibility === 'specified'" class="fas fa-envelope"></i> |  | ||||||
| 			</span> |  | ||||||
| 			<span v-if="note.localOnly" class="localOnly"><i class="fas fa-biohazard"></i></span> |  | ||||||
| 		</div> | 		</div> | ||||||
| 	</div> | 	</div> | ||||||
| 	<article class="article" @contextmenu.stop="onContextmenu"> | 	<article class="article" @contextmenu.stop="onContextmenu"> | ||||||
|  | @ -118,6 +113,7 @@ import XPoll from './poll.vue'; | ||||||
| import XRenoteButton from './renote-button.vue'; | import XRenoteButton from './renote-button.vue'; | ||||||
| import MkUrlPreview from '@/components/url-preview.vue'; | import MkUrlPreview from '@/components/url-preview.vue'; | ||||||
| import MkInstanceTicker from '@/components/instance-ticker.vue'; | import MkInstanceTicker from '@/components/instance-ticker.vue'; | ||||||
|  | import MkVisibility from '@/components/visibility.vue'; | ||||||
| import { pleaseLogin } from '@/scripts/please-login'; | import { pleaseLogin } from '@/scripts/please-login'; | ||||||
| import { focusPrev, focusNext } from '@/scripts/focus'; | import { focusPrev, focusNext } from '@/scripts/focus'; | ||||||
| import { checkWordMute } from '@/scripts/check-word-mute'; | import { checkWordMute } from '@/scripts/check-word-mute'; | ||||||
|  | @ -406,14 +402,6 @@ function readPromo() { | ||||||
| 					margin-right: 4px; | 					margin-right: 4px; | ||||||
| 				} | 				} | ||||||
| 			} | 			} | ||||||
| 
 |  | ||||||
| 			> .visibility { |  | ||||||
| 				margin-left: 8px; |  | ||||||
| 			} |  | ||||||
| 
 |  | ||||||
| 			> .localOnly { |  | ||||||
| 				margin-left: 8px; |  | ||||||
| 			} |  | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -14,7 +14,7 @@ | ||||||
| 
 | 
 | ||||||
| <script lang="ts"> | <script lang="ts"> | ||||||
| import { computed, defineComponent, ref } from 'vue'; | import { computed, defineComponent, ref } from 'vue'; | ||||||
| import XDetails from '@/components/renote.details.vue'; | import XDetails from '@/components/users-tooltip.vue'; | ||||||
| import { pleaseLogin } from '@/scripts/please-login'; | import { pleaseLogin } from '@/scripts/please-login'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { $i } from '@/account'; | import { $i } from '@/account'; | ||||||
|  |  | ||||||
							
								
								
									
										47
									
								
								packages/client/src/components/visibility.vue
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								packages/client/src/components/visibility.vue
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | ||||||
|  | <template> | ||||||
|  | <span v-if="note.visibility !== 'public'" :class="$style.visibility"> | ||||||
|  | 	<i v-if="note.visibility === 'home'" class="fas fa-home"></i> | ||||||
|  | 	<i v-else-if="note.visibility === 'followers'" class="fas fa-unlock"></i> | ||||||
|  | 	<i v-else-if="note.visibility === 'specified'" ref="specified" class="fas fa-envelope"></i> | ||||||
|  | </span> | ||||||
|  | <span v-if="note.localOnly" :class="$style.localOnly"><i class="fas fa-biohazard"></i></span> | ||||||
|  | </template> | ||||||
|  | 
 | ||||||
|  | <script lang="ts" setup> | ||||||
|  | import { ref } from 'vue'; | ||||||
|  | import XDetails from '@/components/users-tooltip.vue'; | ||||||
|  | import * as os from '@/os'; | ||||||
|  | import { useTooltip } from '@/scripts/use-tooltip'; | ||||||
|  | 
 | ||||||
|  | const props = defineProps<{ | ||||||
|  | 	note: { | ||||||
|  | 		visibility: string; | ||||||
|  | 		localOnly?: boolean; | ||||||
|  | 		visibleUserIds?: string[]; | ||||||
|  | 	}, | ||||||
|  | }>(); | ||||||
|  | 
 | ||||||
|  | const specified = $ref<HTMLElement>(); | ||||||
|  | 
 | ||||||
|  | if (props.note.visibility === 'specified') { | ||||||
|  | 	useTooltip($$(specified), async (showing) => { | ||||||
|  | 		const users = await os.api('users/show', { | ||||||
|  | 			userIds: props.note.visibleUserIds, | ||||||
|  | 			limit: 10, | ||||||
|  | 		}); | ||||||
|  | 
 | ||||||
|  | 		os.popup(XDetails, { | ||||||
|  | 			showing, | ||||||
|  | 			users, | ||||||
|  | 			count: props.note.visibleUserIds.length, | ||||||
|  | 			targetElement: specified, | ||||||
|  | 		}, {}, 'closed'); | ||||||
|  | 	}); | ||||||
|  | } | ||||||
|  | </script> | ||||||
|  | 
 | ||||||
|  | <style lang="scss" module> | ||||||
|  | .visibility, .localOnly { | ||||||
|  | 	margin-left: 0.5em; | ||||||
|  | } | ||||||
|  | </style> | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue