summaryrefslogtreecommitdiff
path: root/src/client/directives/user-preview.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/directives/user-preview.ts')
-rw-r--r--src/client/directives/user-preview.ts157
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;