diff --git a/src/client/components/index.ts b/src/client/components/index.ts index 87547599a9..f71816d904 100644 --- a/src/client/components/index.ts +++ b/src/client/components/index.ts @@ -1,4 +1,4 @@ -import Vue from 'vue'; +import { App } from 'vue'; import mfm from './misskey-flavored-markdown.vue'; import acct from './acct.vue'; @@ -12,14 +12,16 @@ import loading from './loading.vue'; import error from './error.vue'; import streamIndicator from './stream-indicator.vue'; -Vue.component('mfm', mfm); -Vue.component('mk-acct', acct); -Vue.component('mk-avatar', avatar); -Vue.component('mk-emoji', emoji); -Vue.component('mk-user-name', userName); -Vue.component('mk-ellipsis', ellipsis); -Vue.component('mk-time', time); -Vue.component('mk-url', url); -Vue.component('mk-loading', loading); -Vue.component('mk-error', error); -Vue.component('stream-indicator', streamIndicator); +export default function(app: App) { + app.component('mfm', mfm); + app.component('mk-acct', acct); + app.component('mk-avatar', avatar); + app.component('mk-emoji', emoji); + app.component('mk-user-name', userName); + app.component('mk-ellipsis', ellipsis); + app.component('mk-time', time); + app.component('mk-url', url); + app.component('mk-loading', loading); + app.component('mk-error', error); + app.component('stream-indicator', streamIndicator); +} diff --git a/src/client/components/mfm.ts b/src/client/components/mfm.ts index af2651533e..f78947a914 100644 --- a/src/client/components/mfm.ts +++ b/src/client/components/mfm.ts @@ -1,4 +1,4 @@ -import Vue, { VNode } from 'vue'; +import { VNode, defineComponent, h } from 'vue'; import { MfmForest } from '../../mfm/prelude'; import { parse, parsePlain } from '../../mfm/parse'; import MkUrl from './url.vue'; @@ -10,7 +10,7 @@ import MkCode from './code.vue'; import MkGoogle from './google.vue'; import { host } from '../config'; -export default Vue.component('misskey-flavored-markdown', { +export default defineComponent({ props: { text: { type: String, @@ -41,7 +41,7 @@ export default Vue.component('misskey-flavored-markdown', { }, }, - render(createElement) { + render() { if (this.text == null || this.text == '') return; const ast = (this.plain ? parsePlain : parse)(this.text); @@ -53,7 +53,7 @@ export default Vue.component('misskey-flavored-markdown', { if (!this.plain) { const x = text.split('\n') - .map(t => t == '' ? [createElement('br')] : [this._v(t), createElement('br')]); // NOTE: this._vはHACK SEE: https://github.com/syuilo/misskey/pull/6399#issuecomment-632820283 + .map(t => t == '' ? [h('br')] : [this._v(t), h('br')]); // NOTE: this._vはHACK SEE: https://github.com/syuilo/misskey/pull/6399#issuecomment-632820283 x[x.length - 1].pop(); return x; } else { @@ -62,15 +62,15 @@ export default Vue.component('misskey-flavored-markdown', { } case 'bold': { - return [createElement('b', genEl(token.children))]; + return [h('b', genEl(token.children))]; } case 'strike': { - return [createElement('del', genEl(token.children))]; + return [h('del', genEl(token.children))]; } case 'italic': { - return (createElement as any)('i', { + return h('i', { attrs: { style: 'font-style: oblique;' }, @@ -78,7 +78,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'big': { - return (createElement as any)('strong', { + return h('strong', { attrs: { style: `display: inline-block; font-size: 150%;` }, @@ -90,7 +90,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'small': { - return [createElement('small', { + return [h('small', { attrs: { style: 'opacity: 0.7;' }, @@ -98,7 +98,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'center': { - return [createElement('div', { + return [h('div', { attrs: { style: 'text-align:center;' } @@ -106,7 +106,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'motion': { - return (createElement as any)('span', { + return h('span', { attrs: { style: 'display: inline-block;' }, @@ -124,7 +124,7 @@ export default Vue.component('misskey-flavored-markdown', { 'normal'; const style = this.$store.state.device.animatedMfm ? `animation: spin 1.5s linear infinite; animation-direction: ${direction};` : ''; - return (createElement as any)('span', { + return h('span', { attrs: { style: 'display: inline-block;' + style }, @@ -132,7 +132,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'jump': { - return (createElement as any)('span', { + return h('span', { attrs: { style: this.$store.state.device.animatedMfm ? 'display: inline-block; animation: jump 0.75s linear infinite;' : 'display: inline-block;' }, @@ -140,7 +140,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'flip': { - return (createElement as any)('span', { + return h('span', { attrs: { style: 'display: inline-block; transform: scaleX(-1);' }, @@ -148,7 +148,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'url': { - return [createElement(MkUrl, { + return [h(MkUrl, { key: Math.random(), props: { url: token.node.props.url, @@ -158,7 +158,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'link': { - return [createElement(MkLink, { + return [h(MkLink, { key: Math.random(), props: { url: token.node.props.url, @@ -168,7 +168,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'mention': { - return [createElement(MkMention, { + return [h(MkMention, { key: Math.random(), props: { host: (token.node.props.host == null && this.author && this.author.host != null ? this.author.host : token.node.props.host) || host, @@ -178,7 +178,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'hashtag': { - return [createElement('router-link', { + return [h('router-link', { key: Math.random(), attrs: { to: this.isNote ? `/tags/${encodeURIComponent(token.node.props.hashtag)}` : `/explore/tags/${encodeURIComponent(token.node.props.hashtag)}`, @@ -188,7 +188,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'blockCode': { - return [createElement(MkCode, { + return [h(MkCode, { key: Math.random(), props: { code: token.node.props.code, @@ -198,7 +198,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'inlineCode': { - return [createElement(MkCode, { + return [h(MkCode, { key: Math.random(), props: { code: token.node.props.code, @@ -210,13 +210,13 @@ export default Vue.component('misskey-flavored-markdown', { case 'quote': { if (this.shouldBreak) { - return [createElement('div', { + return [h('div', { attrs: { class: 'quote' } }, genEl(token.children))]; } else { - return [createElement('span', { + return [h('span', { attrs: { class: 'quote' } @@ -225,7 +225,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'title': { - return [createElement('div', { + return [h('div', { attrs: { class: 'title' } @@ -233,7 +233,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'emoji': { - return [createElement('mk-emoji', { + return [h('mk-emoji', { key: Math.random(), attrs: { emoji: token.node.props.emoji, @@ -247,7 +247,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'mathInline': { - return [createElement(MkFormula, { + return [h(MkFormula, { key: Math.random(), props: { formula: token.node.props.formula, @@ -257,7 +257,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'mathBlock': { - return [createElement(MkFormula, { + return [h(MkFormula, { key: Math.random(), props: { formula: token.node.props.formula, @@ -267,7 +267,7 @@ export default Vue.component('misskey-flavored-markdown', { } case 'search': { - return [createElement(MkGoogle, { + return [h(MkGoogle, { key: Math.random(), props: { q: token.node.props.query @@ -284,6 +284,6 @@ export default Vue.component('misskey-flavored-markdown', { })); // Parse ast to DOM - return createElement('span', genEl(ast)); + return h('span', genEl(ast)); } }); diff --git a/src/client/components/timeline.vue b/src/client/components/timeline.vue index cbdd08906c..252025f48a 100644 --- a/src/client/components/timeline.vue +++ b/src/client/components/timeline.vue @@ -46,11 +46,6 @@ export default defineComponent({ }, created() { - this.$once('hook:beforeDestroy', () => { - this.connection.dispose(); - if (this.connection2) this.connection2.dispose(); - }); - const prepend = note => { const _note = JSON.parse(JSON.stringify(note)); // deepcopy (this.$refs.tl as any).prepend(_note); @@ -130,6 +125,11 @@ export default defineComponent({ }; }, + beforeUnmount() { + this.connection.dispose(); + if (this.connection2) this.connection2.dispose(); + }, + methods: { focus() { this.$refs.tl.focus(); diff --git a/src/client/directives/autocomplete.ts b/src/client/directives/autocomplete.ts index 44043017ef..a3e16135df 100644 --- a/src/client/directives/autocomplete.ts +++ b/src/client/directives/autocomplete.ts @@ -1,18 +1,19 @@ +import { Directive } from 'vue'; import * as getCaretCoordinates from 'textarea-caret'; import { toASCII } from 'punycode'; export default { - bind(el, binding, vn) { + mounted(el, binding, vn) { const self = el._autoCompleteDirective_ = {} as any; self.x = new Autocomplete(el, vn.context, binding.value); self.x.attach(); }, - unbind(el, binding, vn) { + unmounted(el, binding, vn) { const self = el._autoCompleteDirective_; self.x.detach(); } -}; +} as Directive; /** * オートコンプリートを管理するクラス。 diff --git a/src/client/directives/index.ts b/src/client/directives/index.ts index 24db5cc152..8d6116f975 100644 --- a/src/client/directives/index.ts +++ b/src/client/directives/index.ts @@ -7,9 +7,9 @@ import particle from './particle'; import tooltip from './tooltip'; export default function(app: App) { - //app.directive('autocomplete', autocomplete); - //app.directive('userPreview', userPreview); - //app.directive('user-preview', userPreview); + app.directive('autocomplete', autocomplete); + app.directive('userPreview', userPreview); + app.directive('user-preview', userPreview); app.directive('size', size); //app.directive('particle', particle); //app.directive('tooltip', tooltip); diff --git a/src/client/directives/user-preview.ts b/src/client/directives/user-preview.ts index 4db0d67c4a..a22ccb8eed 100644 --- a/src/client/directives/user-preview.ts +++ b/src/client/directives/user-preview.ts @@ -1,7 +1,10 @@ +import { Directive } from 'vue'; import MkUserPreview from '../components/user-preview.vue'; export default { - bind(el: HTMLElement, binding, vn) { + mounted(el: HTMLElement, binding, vn) { + // TODO: 新たにプロパティを作るのをやめMapを使う + // ただメモリ的には↓の方が省メモリかもしれないので検討中 const self = (el as any)._userPreviewDirective_ = {} as any; self.user = binding.value; @@ -68,8 +71,8 @@ export default { }); }, - unbind(el, binding, vn) { + unmounted(el, binding, vn) { const self = el._userPreviewDirective_; clearInterval(self.checkTimer); } -}; +} as Directive; diff --git a/src/client/init.ts b/src/client/init.ts index ea35493aac..e5d5b72467 100644 --- a/src/client/init.ts +++ b/src/client/init.ts @@ -16,6 +16,7 @@ import FontAwesomeIcon from './components/fa.vue'; import Stream from './scripts/stream'; import widgets from './widgets'; import directives from './directives'; +import components from './components'; import { version, langs, getLocale, apiUrl } from './config'; import { store } from './store'; import { router } from './router'; @@ -172,8 +173,7 @@ app.component('fa', FontAwesomeIcon); widgets(app); directives(app); - -//require('./components'); +components(app); document.body.innerHTML = '
'; diff --git a/src/client/root.vue b/src/client/root.vue index 8d8bf3f7af..bd7391a0e4 100644 --- a/src/client/root.vue +++ b/src/client/root.vue @@ -40,6 +40,10 @@ export default defineComponent({ }, methods: { + api(endpoint: string, data: { [x: string]: any } = {}, token?) { + return this.$store.dispatch('api', { endpoint, data, token }); + }, + dialog(opts) { this.$store.commit('showDialog', opts); } diff --git a/src/client/scripts/paging.ts b/src/client/scripts/paging.ts index 832f0720e0..5755cfe611 100644 --- a/src/client/scripts/paging.ts +++ b/src/client/scripts/paging.ts @@ -1,4 +1,3 @@ -import Vue from 'vue'; import { getScrollPosition, onScrollTop } from './scroll'; const SECOND_FETCH_LIMIT = 30; @@ -48,14 +47,14 @@ export default (opts) => ({ created() { opts.displayLimit = opts.displayLimit || 30; this.init(); + }, - this.$on('hook:activated', () => { - this.isBackTop = false; - }); + activated() { + this.isBackTop = false; + }, - this.$on('hook:deactivated', () => { - this.isBackTop = window.scrollY === 0; - }); + deactivated() { + this.isBackTop = window.scrollY === 0; }, mounted() { @@ -75,7 +74,7 @@ export default (opts) => ({ methods: { updateItem(i, item) { - Vue.set((this as any).items, i, item); + (this as any).items[i] = item; }, reload() {