chore(client): tweak ui
This commit is contained in:
		| @@ -12,106 +12,81 @@ | |||||||
| </button> | </button> | ||||||
| </template> | </template> | ||||||
|  |  | ||||||
| <script lang="ts"> | <script lang="ts" setup> | ||||||
| import { computed, defineComponent, onMounted, ref, watch } from 'vue'; | import { computed, onMounted, ref, watch } from 'vue'; | ||||||
|  | import * as misskey from 'misskey-js'; | ||||||
| import XDetails from '@/components/reactions-viewer.details.vue'; | import XDetails from '@/components/reactions-viewer.details.vue'; | ||||||
| import XReactionIcon from '@/components/reaction-icon.vue'; | import XReactionIcon from '@/components/reaction-icon.vue'; | ||||||
| import * as os from '@/os'; | import * as os from '@/os'; | ||||||
| import { useTooltip } from '@/scripts/use-tooltip'; | import { useTooltip } from '@/scripts/use-tooltip'; | ||||||
| import { $i } from '@/account'; | import { $i } from '@/account'; | ||||||
|  |  | ||||||
| export default defineComponent({ | const props = defineProps<{ | ||||||
| 	components: { | 	reaction: string; | ||||||
| 		XReactionIcon | 	count: number; | ||||||
| 	}, | 	isInitial: boolean; | ||||||
|  | 	note: misskey.entities.Note; | ||||||
|  | }>(); | ||||||
|  |  | ||||||
| 	props: { | const buttonRef = ref<HTMLElement>(); | ||||||
| 		reaction: { |  | ||||||
| 			type: String, |  | ||||||
| 			required: true, |  | ||||||
| 		}, |  | ||||||
| 		count: { |  | ||||||
| 			type: Number, |  | ||||||
| 			required: true, |  | ||||||
| 		}, |  | ||||||
| 		isInitial: { |  | ||||||
| 			type: Boolean, |  | ||||||
| 			required: true, |  | ||||||
| 		}, |  | ||||||
| 		note: { |  | ||||||
| 			type: Object, |  | ||||||
| 			required: true, |  | ||||||
| 		}, |  | ||||||
| 	}, |  | ||||||
|  |  | ||||||
| 	setup(props) { | const canToggle = computed(() => !props.reaction.match(/@\w/) && $i); | ||||||
| 		const buttonRef = ref<HTMLElement>(); |  | ||||||
|  |  | ||||||
| 		const canToggle = computed(() => !props.reaction.match(/@\w/) && $i); | const toggleReaction = () => { | ||||||
|  | 	if (!canToggle.value) return; | ||||||
|  |  | ||||||
| 		const toggleReaction = () => { | 	const oldReaction = props.note.myReaction; | ||||||
| 			if (!canToggle.value) return; | 	if (oldReaction) { | ||||||
|  | 		os.api('notes/reactions/delete', { | ||||||
| 			const oldReaction = props.note.myReaction; | 			noteId: props.note.id, | ||||||
| 			if (oldReaction) { | 		}).then(() => { | ||||||
| 				os.api('notes/reactions/delete', { | 			if (oldReaction !== props.reaction) { | ||||||
| 					noteId: props.note.id |  | ||||||
| 				}).then(() => { |  | ||||||
| 					if (oldReaction !== props.reaction) { |  | ||||||
| 						os.api('notes/reactions/create', { |  | ||||||
| 							noteId: props.note.id, |  | ||||||
| 							reaction: props.reaction |  | ||||||
| 						}); |  | ||||||
| 					} |  | ||||||
| 				}); |  | ||||||
| 			} else { |  | ||||||
| 				os.api('notes/reactions/create', { | 				os.api('notes/reactions/create', { | ||||||
| 					noteId: props.note.id, | 					noteId: props.note.id, | ||||||
| 					reaction: props.reaction | 					reaction: props.reaction, | ||||||
| 				}); | 				}); | ||||||
| 			} | 			} | ||||||
| 		}; |  | ||||||
|  |  | ||||||
| 		const anime = () => { |  | ||||||
| 			if (document.hidden) return; |  | ||||||
|  |  | ||||||
| 			// TODO: 新しくリアクションが付いたことが視覚的に分かりやすいアニメーション |  | ||||||
| 		}; |  | ||||||
|  |  | ||||||
| 		watch(() => props.count, (newCount, oldCount) => { |  | ||||||
| 			if (oldCount < newCount) anime(); |  | ||||||
| 		}); | 		}); | ||||||
|  | 	} else { | ||||||
| 		onMounted(() => { | 		os.api('notes/reactions/create', { | ||||||
| 			if (!props.isInitial) anime(); | 			noteId: props.note.id, | ||||||
|  | 			reaction: props.reaction, | ||||||
| 		}); | 		}); | ||||||
|  | 	} | ||||||
|  | }; | ||||||
|  |  | ||||||
| 		useTooltip(buttonRef, async (showing) => { | const anime = () => { | ||||||
| 			const reactions = await os.api('notes/reactions', { | 	if (document.hidden) return; | ||||||
| 				noteId: props.note.id, |  | ||||||
| 				type: props.reaction, |  | ||||||
| 				limit: 11 |  | ||||||
| 			}); |  | ||||||
|  |  | ||||||
| 			const users = reactions.map(x => x.user); | 	// TODO: 新しくリアクションが付いたことが視覚的に分かりやすいアニメーション | ||||||
|  | }; | ||||||
|  |  | ||||||
| 			os.popup(XDetails, { | watch(() => props.count, (newCount, oldCount) => { | ||||||
| 				showing, | 	if (oldCount < newCount) anime(); | ||||||
| 				reaction: props.reaction, |  | ||||||
| 				emojis: props.note.emojis, |  | ||||||
| 				users, |  | ||||||
| 				count: props.count, |  | ||||||
| 				targetElement: buttonRef.value, |  | ||||||
| 			}, {}, 'closed'); |  | ||||||
| 		}); |  | ||||||
|  |  | ||||||
| 		return { |  | ||||||
| 			buttonRef, |  | ||||||
| 			canToggle, |  | ||||||
| 			toggleReaction, |  | ||||||
| 		}; |  | ||||||
| 	}, |  | ||||||
| }); | }); | ||||||
|  |  | ||||||
|  | onMounted(() => { | ||||||
|  | 	if (!props.isInitial) anime(); | ||||||
|  | }); | ||||||
|  |  | ||||||
|  | useTooltip(buttonRef, async (showing) => { | ||||||
|  | 	const reactions = await os.api('notes/reactions', { | ||||||
|  | 		noteId: props.note.id, | ||||||
|  | 		type: props.reaction, | ||||||
|  | 		limit: 11, | ||||||
|  | 	}); | ||||||
|  |  | ||||||
|  | 	const users = reactions.map(x => x.user); | ||||||
|  |  | ||||||
|  | 	os.popup(XDetails, { | ||||||
|  | 		showing, | ||||||
|  | 		reaction: props.reaction, | ||||||
|  | 		emojis: props.note.emojis, | ||||||
|  | 		users, | ||||||
|  | 		count: props.count, | ||||||
|  | 		targetElement: buttonRef.value, | ||||||
|  | 	}, {}, 'closed'); | ||||||
|  | }, 100); | ||||||
| </script> | </script> | ||||||
|  |  | ||||||
| <style lang="scss" scoped> | <style lang="scss" scoped> | ||||||
|   | |||||||
| @@ -3,6 +3,7 @@ import { Ref, ref, watch, onUnmounted } from 'vue'; | |||||||
| export function useTooltip( | export function useTooltip( | ||||||
| 	elRef: Ref<HTMLElement | { $el: HTMLElement } | null | undefined>, | 	elRef: Ref<HTMLElement | { $el: HTMLElement } | null | undefined>, | ||||||
| 	onShow: (showing: Ref<boolean>) => void, | 	onShow: (showing: Ref<boolean>) => void, | ||||||
|  | 	delay = 300, | ||||||
| ): void { | ): void { | ||||||
| 	let isHovering = false; | 	let isHovering = false; | ||||||
|  |  | ||||||
| @@ -40,7 +41,7 @@ export function useTooltip( | |||||||
| 		if (isHovering) return; | 		if (isHovering) return; | ||||||
| 		if (shouldIgnoreMouseover) return; | 		if (shouldIgnoreMouseover) return; | ||||||
| 		isHovering = true; | 		isHovering = true; | ||||||
| 		timeoutId = window.setTimeout(open, 300); | 		timeoutId = window.setTimeout(open, delay); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	const onMouseleave = () => { | 	const onMouseleave = () => { | ||||||
| @@ -54,7 +55,7 @@ export function useTooltip( | |||||||
| 		shouldIgnoreMouseover = true; | 		shouldIgnoreMouseover = true; | ||||||
| 		if (isHovering) return; | 		if (isHovering) return; | ||||||
| 		isHovering = true; | 		isHovering = true; | ||||||
| 		timeoutId = window.setTimeout(open, 300); | 		timeoutId = window.setTimeout(open, delay); | ||||||
| 	}; | 	}; | ||||||
|  |  | ||||||
| 	const onTouchend = () => { | 	const onTouchend = () => { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user
	 syuilo
					syuilo