wip
This commit is contained in:
parent
2839c1df0d
commit
e427f2160a
|
@ -1,8 +1,8 @@
|
||||||
<template>
|
<template>
|
||||||
<span class="eiwwqkts" :class="{ cat }" :title="acct(user)" v-if="disableLink" v-user-preview="disablePreview ? undefined : user.id" @click="onClick">
|
<span class="eiwwqkts" :class="{ cat }" :title="acct(user)" v-if="disableLink" @click="onClick">
|
||||||
<img class="inner" :src="url"/>
|
<img class="inner" :src="url"/>
|
||||||
</span>
|
</span>
|
||||||
<router-link class="eiwwqkts" :class="{ cat }" :to="userPage(user)" :title="acct(user)" :target="target" v-else v-user-preview="disablePreview ? undefined : user.id">
|
<router-link class="eiwwqkts" :class="{ cat }" :to="userPage(user)" :title="acct(user)" :target="target" v-else>
|
||||||
<img class="inner" :src="url"/>
|
<img class="inner" :src="url"/>
|
||||||
</router-link>
|
</router-link>
|
||||||
</template>
|
</template>
|
||||||
|
@ -10,11 +10,11 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
import { getStaticImageUrl } from '@/scripts/get-static-image-url';
|
||||||
|
import { UserPreview } from '@/scripts/user-preview';
|
||||||
import { acct, userPage } from '../filters/user';
|
import { acct, userPage } from '../filters/user';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
export default defineComponent({
|
export default defineComponent({
|
||||||
emits: ['click'],
|
|
||||||
props: {
|
props: {
|
||||||
user: {
|
user: {
|
||||||
type: Object,
|
type: Object,
|
||||||
|
@ -33,6 +33,7 @@ export default defineComponent({
|
||||||
default: false
|
default: false
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
emits: ['click'],
|
||||||
computed: {
|
computed: {
|
||||||
cat(): boolean {
|
cat(): boolean {
|
||||||
return this.user.isCat;
|
return this.user.isCat;
|
||||||
|
@ -50,6 +51,10 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
mounted() {
|
mounted() {
|
||||||
this.$el.style.color = this.getBlurhashAvgColor(this.user.avatarBlurhash);
|
this.$el.style.color = this.getBlurhashAvgColor(this.user.avatarBlurhash);
|
||||||
|
|
||||||
|
if (!this.disablePreview) {
|
||||||
|
new UserPreview(this.$el, this.user.id);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
getBlurhashAvgColor(s) {
|
getBlurhashAvgColor(s) {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
<template>
|
<template>
|
||||||
<router-link class="ldlomzub" :class="{ isMe }" :to="url" v-user-preview="canonical" v-if="url.startsWith('/')">
|
<router-link class="ldlomzub" :class="{ isMe }" :to="url" v-if="url.startsWith('/')">
|
||||||
<span class="me" v-if="isMe">{{ $t('you') }}</span>
|
<span class="me" v-if="isMe">{{ $t('you') }}</span>
|
||||||
<span class="main">
|
<span class="main">
|
||||||
<span class="username">@{{ username }}</span>
|
<span class="username">@{{ username }}</span>
|
||||||
|
@ -18,6 +18,7 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { toUnicode } from 'punycode';
|
import { toUnicode } from 'punycode';
|
||||||
import { host as localHost } from '@/config';
|
import { host as localHost } from '@/config';
|
||||||
|
import { UserPreview } from '@/scripts/user-preview';
|
||||||
import { wellKnownServices } from '../../well-known-services';
|
import { wellKnownServices } from '../../well-known-services';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
|
||||||
|
@ -55,6 +56,9 @@ export default defineComponent({
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
mounted() {
|
||||||
|
new UserPreview(this.$el, this.canonical);
|
||||||
|
},
|
||||||
methods: {
|
methods: {
|
||||||
toUnicode
|
toUnicode
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<header class="kkwtjztg">
|
<header class="kkwtjztg">
|
||||||
<router-link class="name" :to="userPage(note.user)" v-user-preview="note.user.id">
|
<router-link class="name" :to="userPage(note.user)" ref="name">
|
||||||
<mk-user-name :user="note.user"/>
|
<mk-user-name :user="note.user"/>
|
||||||
</router-link>
|
</router-link>
|
||||||
<span class="is-bot" v-if="note.user.isBot">bot</span>
|
<span class="is-bot" v-if="note.user.isBot">bot</span>
|
||||||
|
@ -26,6 +26,7 @@
|
||||||
import { defineComponent } from 'vue';
|
import { defineComponent } from 'vue';
|
||||||
import { faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, faBiohazard } from '@fortawesome/free-solid-svg-icons';
|
import { faHome, faUnlock, faEnvelope, faMobileAlt, faBookmark, faBiohazard } from '@fortawesome/free-solid-svg-icons';
|
||||||
import { faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons';
|
import { faBookmark as farBookmark } from '@fortawesome/free-regular-svg-icons';
|
||||||
|
import { UserPreview } from '@/scripts/user-preview';
|
||||||
import notePage from '../filters/note';
|
import notePage from '../filters/note';
|
||||||
import { userPage } from '../filters/user';
|
import { userPage } from '../filters/user';
|
||||||
import * as os from '@/os';
|
import * as os from '@/os';
|
||||||
|
@ -44,6 +45,10 @@ export default defineComponent({
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
|
|
||||||
|
mounted() {
|
||||||
|
new UserPreview(this.$refs.name.$el, this.note.user.id);
|
||||||
|
},
|
||||||
|
|
||||||
methods: {
|
methods: {
|
||||||
notePage,
|
notePage,
|
||||||
userPage
|
userPage
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
<template>
|
<template>
|
||||||
<transition name="popup" appear @after-leave="() => { $emit('closed'); destroyDom(); }">
|
<transition name="popup" appear @after-leave="$emit('closed')">
|
||||||
<div v-if="show" class="fxxzrfni _panel _shadow" ref="content" :style="{ top: top + 'px', left: left + 'px' }" @mouseover="() => { $emit('mouseover'); }" @mouseleave="() => { $emit('mouseleave'); }">
|
<div v-if="show && showing" class="fxxzrfni _panel _shadow" ref="content" :style="{ top: top + 'px', left: left + 'px' }" @mouseover="() => { $emit('mouseover'); }" @mouseleave="() => { $emit('mouseleave'); }">
|
||||||
<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl})` : ''"></div>
|
<div class="banner" :style="u.bannerUrl ? `background-image: url(${u.bannerUrl})` : ''"></div>
|
||||||
<mk-avatar class="avatar" :user="u" :disable-preview="true"/>
|
<mk-avatar class="avatar" :user="u" :disable-preview="true"/>
|
||||||
<div class="title">
|
<div class="title">
|
||||||
|
@ -39,6 +39,10 @@ export default defineComponent({
|
||||||
},
|
},
|
||||||
|
|
||||||
props: {
|
props: {
|
||||||
|
showing: {
|
||||||
|
type: Boolean,
|
||||||
|
required: true
|
||||||
|
},
|
||||||
user: {
|
user: {
|
||||||
type: [Object, String],
|
type: [Object, String],
|
||||||
required: true
|
required: true
|
||||||
|
@ -48,6 +52,8 @@ export default defineComponent({
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
emits: ['closed', 'mouseover', 'mouseleave'],
|
||||||
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
u: null,
|
u: null,
|
||||||
|
|
|
@ -1,13 +1,10 @@
|
||||||
import { App } from 'vue';
|
import { App } from 'vue';
|
||||||
|
|
||||||
import userPreview from './user-preview';
|
|
||||||
import size from './size';
|
import size from './size';
|
||||||
import particle from './particle';
|
import particle from './particle';
|
||||||
import tooltip from './tooltip';
|
import tooltip from './tooltip';
|
||||||
|
|
||||||
export default function(app: App) {
|
export default function(app: App) {
|
||||||
app.directive('userPreview', userPreview);
|
|
||||||
app.directive('user-preview', userPreview);
|
|
||||||
app.directive('size', size);
|
app.directive('size', size);
|
||||||
app.directive('particle', particle);
|
app.directive('particle', particle);
|
||||||
app.directive('tooltip', tooltip);
|
app.directive('tooltip', tooltip);
|
||||||
|
|
|
@ -1,75 +0,0 @@
|
||||||
import { Directive } from 'vue';
|
|
||||||
import MkUserPreview from '@/components/user-preview.vue';
|
|
||||||
|
|
||||||
export default {
|
|
||||||
// modal側でcontentのmouseoverイベントなどを発行してもらう必要がありそう
|
|
||||||
/*
|
|
||||||
mounted(el: HTMLElement, binding, vn) {
|
|
||||||
// TODO: 新たにプロパティを作るのをやめMapを使う
|
|
||||||
// ただメモリ的には↓の方が省メモリかもしれないので検討中
|
|
||||||
const self = (el as any)._userPreviewDirective_ = {} as any;
|
|
||||||
|
|
||||||
self.user = binding.value;
|
|
||||||
self.close = null;
|
|
||||||
self.showTimer = null;
|
|
||||||
self.hideTimer = null;
|
|
||||||
self.checkTimer = null;
|
|
||||||
|
|
||||||
self.close = () => {
|
|
||||||
if (self.close) {
|
|
||||||
clearInterval(self.checkTimer);
|
|
||||||
self.close.close();
|
|
||||||
self.close = null;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const show = () => {
|
|
||||||
if (!document.body.contains(el)) return;
|
|
||||||
if (self.close) return;
|
|
||||||
|
|
||||||
self.close = os.popup(MkUserPreview, {
|
|
||||||
user: self.user,
|
|
||||||
source: el
|
|
||||||
});
|
|
||||||
|
|
||||||
self.close.$on('mouseover', () => {
|
|
||||||
clearTimeout(self.hideTimer);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.close.$on('mouseleave', () => {
|
|
||||||
clearTimeout(self.showTimer);
|
|
||||||
self.hideTimer = setTimeout(self.close, 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
self.checkTimer = setInterval(() => {
|
|
||||||
if (!document.body.contains(el)) {
|
|
||||||
clearTimeout(self.showTimer);
|
|
||||||
clearTimeout(self.hideTimer);
|
|
||||||
self.close();
|
|
||||||
}
|
|
||||||
}, 1000);
|
|
||||||
};
|
|
||||||
|
|
||||||
el.addEventListener('mouseover', () => {
|
|
||||||
clearTimeout(self.showTimer);
|
|
||||||
clearTimeout(self.hideTimer);
|
|
||||||
self.showTimer = setTimeout(show, 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
el.addEventListener('mouseleave', () => {
|
|
||||||
clearTimeout(self.showTimer);
|
|
||||||
clearTimeout(self.hideTimer);
|
|
||||||
self.hideTimer = setTimeout(self.close, 500);
|
|
||||||
});
|
|
||||||
|
|
||||||
el.addEventListener('click', () => {
|
|
||||||
clearTimeout(self.showTimer);
|
|
||||||
self.close();
|
|
||||||
});
|
|
||||||
},
|
|
||||||
|
|
||||||
unmounted(el, binding, vn) {
|
|
||||||
const self = el._userPreviewDirective_;
|
|
||||||
clearInterval(self.checkTimer);
|
|
||||||
}*/
|
|
||||||
} as Directive;
|
|
|
@ -0,0 +1,89 @@
|
||||||
|
import autobind from 'autobind-decorator';
|
||||||
|
import { popup } from '@/os';
|
||||||
|
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
private async show() {
|
||||||
|
if (!document.body.contains(this.el)) return;
|
||||||
|
if (this.promise) return;
|
||||||
|
|
||||||
|
this.promise = popup(await import('@/components/user-preview.vue'), {
|
||||||
|
user: this.user,
|
||||||
|
source: this.el
|
||||||
|
}, {
|
||||||
|
mouseover: () => {
|
||||||
|
clearTimeout(this.hideTimer);
|
||||||
|
},
|
||||||
|
mouseleave: () => {
|
||||||
|
clearTimeout(this.showTimer);
|
||||||
|
this.hideTimer = setTimeout(this.close, 500);
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
private onMouseover() {
|
||||||
|
clearTimeout(this.showTimer);
|
||||||
|
clearTimeout(this.hideTimer);
|
||||||
|
this.showTimer = setTimeout(this.show, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
private onMouseleave() {
|
||||||
|
clearTimeout(this.showTimer);
|
||||||
|
clearTimeout(this.hideTimer);
|
||||||
|
this.hideTimer = setTimeout(this.close, 500);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
private onClick() {
|
||||||
|
clearTimeout(this.showTimer);
|
||||||
|
this.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public attach() {
|
||||||
|
this.el.addEventListener('mouseover', this.onMouseover);
|
||||||
|
this.el.addEventListener('mouseleave', this.onMouseleave);
|
||||||
|
this.el.addEventListener('click', this.onClick);
|
||||||
|
}
|
||||||
|
|
||||||
|
@autobind
|
||||||
|
public detach() {
|
||||||
|
this.el.removeEventListener('mouseover', this.onMouseover);
|
||||||
|
this.el.removeEventListener('mouseleave', this.onMouseleave);
|
||||||
|
this.el.removeEventListener('click', this.onClick);
|
||||||
|
clearInterval(this.checkTimer);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue