diff options
Diffstat (limited to 'src/client/directives/user-preview.ts')
| -rw-r--r-- | src/client/directives/user-preview.ts | 157 |
1 files changed, 100 insertions, 57 deletions
diff --git a/src/client/directives/user-preview.ts b/src/client/directives/user-preview.ts index 4db0d67c4a..0fe05aca40 100644 --- a/src/client/directives/user-preview.ts +++ b/src/client/directives/user-preview.ts @@ -1,75 +1,118 @@ -import MkUserPreview from '../components/user-preview.vue'; +import { Directive, ref } from 'vue'; +import autobind from 'autobind-decorator'; +import { popup } from '@/os'; -export default { - bind(el: HTMLElement, binding, vn) { - const self = (el as any)._userPreviewDirective_ = {} as any; +export class UserPreview { + private el; + private user; + private showTimer; + private hideTimer; + private checkTimer; + private promise; + + constructor(el, user) { + this.el = el; + this.user = user; + + this.attach(); + } - self.user = binding.value; - self.tag = null; - self.showTimer = null; - self.hideTimer = null; - self.checkTimer = null; + @autobind + private async show() { + if (!document.body.contains(this.el)) return; + if (this.promise) return; - self.close = () => { - if (self.tag) { - clearInterval(self.checkTimer); - self.tag.close(); - self.tag = null; + const showing = ref(true); + + popup(await import('@/components/user-preview.vue'), { + showing, + q: this.user, + source: this.el + }, { + mouseover: () => { + clearTimeout(this.hideTimer); + }, + mouseleave: () => { + clearTimeout(this.showTimer); + this.hideTimer = setTimeout(this.close, 500); + }, + }, 'closed'); + + this.promise = { + cancel: () => { + showing.value = false; } }; - const show = () => { - if (!document.body.contains(el)) return; - if (self.tag) return; + this.checkTimer = setInterval(() => { + if (!document.body.contains(this.el)) { + clearTimeout(this.showTimer); + clearTimeout(this.hideTimer); + this.close(); + } + }, 1000); + } + + @autobind + private close() { + if (this.promise) { + clearInterval(this.checkTimer); + this.promise.cancel(); + this.promise = null; + } + } - self.tag = new MkUserPreview({ - parent: vn.context, - propsData: { - user: self.user, - source: el - } - }).$mount(); + @autobind + private onMouseover() { + clearTimeout(this.showTimer); + clearTimeout(this.hideTimer); + this.showTimer = setTimeout(this.show, 500); + } - self.tag.$on('mouseover', () => { - clearTimeout(self.hideTimer); - }); + @autobind + private onMouseleave() { + clearTimeout(this.showTimer); + clearTimeout(this.hideTimer); + this.hideTimer = setTimeout(this.close, 500); + } - self.tag.$on('mouseleave', () => { - clearTimeout(self.showTimer); - self.hideTimer = setTimeout(self.close, 500); - }); + @autobind + private onClick() { + clearTimeout(this.showTimer); + this.close(); + } - document.body.appendChild(self.tag.$el); + @autobind + public attach() { + this.el.addEventListener('mouseover', this.onMouseover); + this.el.addEventListener('mouseleave', this.onMouseleave); + this.el.addEventListener('click', this.onClick); + } - self.checkTimer = setInterval(() => { - if (!document.body.contains(el)) { - clearTimeout(self.showTimer); - clearTimeout(self.hideTimer); - self.close(); - } - }, 1000); - }; + @autobind + public detach() { + this.el.removeEventListener('mouseover', this.onMouseover); + this.el.removeEventListener('mouseleave', this.onMouseleave); + this.el.removeEventListener('click', this.onClick); + clearInterval(this.checkTimer); + } +} - el.addEventListener('mouseover', () => { - clearTimeout(self.showTimer); - clearTimeout(self.hideTimer); - self.showTimer = setTimeout(show, 500); - }); +export default { + mounted(el: HTMLElement, binding, vn) { + if (binding.value == null) return; - el.addEventListener('mouseleave', () => { - clearTimeout(self.showTimer); - clearTimeout(self.hideTimer); - self.hideTimer = setTimeout(self.close, 500); - }); + // TODO: 新たにプロパティを作るのをやめMapを使う + // ただメモリ的には↓の方が省メモリかもしれないので検討中 + const self = (el as any)._userPreviewDirective_ = {} as any; - el.addEventListener('click', () => { - clearTimeout(self.showTimer); - self.close(); - }); + self.preview = new UserPreview(el, binding.value); }, - unbind(el, binding, vn) { + unmounted(el, binding, vn) { + if (binding.value == null) return; + const self = el._userPreviewDirective_; - clearInterval(self.checkTimer); + self.preview.detach(); } -}; +} as Directive; |