Merge branch 'develop' into vue3

This commit is contained in:
syuilo 2020-07-25 12:03:05 +09:00
commit 66cc7a28ba
10 changed files with 185 additions and 21 deletions

View File

@ -732,6 +732,7 @@ _widgets:
activity: "アクティビティ" activity: "アクティビティ"
photos: "フォト" photos: "フォト"
digitalClock: "デジタル時計" digitalClock: "デジタル時計"
federation: "連合"
_cw: _cw:
hide: "隠す" hide: "隠す"

View File

@ -40,7 +40,24 @@ export default defineComponent({
: this.user.avatarUrl; : this.user.avatarUrl;
}, },
}, },
watch: {
'user.avatarBlurhash'() {
this.$el.style.color = this.getBlurhashAvgColor(this.user.avatarBlurhash);
}
},
mounted() {
this.$el.style.color = this.getBlurhashAvgColor(this.user.avatarBlurhash);
},
methods: { methods: {
getBlurhashAvgColor(s) {
return typeof s == 'string'
? '#' + [...s.slice(2, 6)]
.map(x => '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~'.indexOf(x))
.reduce((a, c) => a * 83 + c, 0)
.toString(16)
.padStart(6, '0')
: undefined;
},
onClick(e) { onClick(e) {
this.$emit('click', e); this.$emit('click', e);
} }

View File

@ -2,20 +2,21 @@
<x-column :name="name" :column="column" :is-stacked="isStacked" :menu="menu"> <x-column :name="name" :column="column" :is-stacked="isStacked" :menu="menu">
<template #header><fa :icon="faEnvelope" style="margin-right: 8px;"/>{{ column.name }}</template> <template #header><fa :icon="faEnvelope" style="margin-right: 8px;"/>{{ column.name }}</template>
<x-direct/> <x-notes :pagination="pagination" @before="before()" @after="after()"/>
</x-column> </x-column>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faEnvelope } from '@fortawesome/free-solid-svg-icons'; import { faEnvelope } from '@fortawesome/free-solid-svg-icons';
import Progress from '../../scripts/loading';
import XColumn from './column.vue'; import XColumn from './column.vue';
import XDirect from '../../pages/messages.vue'; import XNotes from '../notes.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
XColumn, XColumn,
XDirect XNotes
}, },
props: { props: {
@ -32,8 +33,25 @@ export default defineComponent({
data() { data() {
return { return {
menu: null, menu: null,
pagination: {
endpoint: 'notes/mentions',
limit: 10,
params: () => ({
visibility: 'specified'
})
},
faEnvelope faEnvelope
} }
}, },
methods: {
before() {
Progress.start();
},
after() {
Progress.done();
}
}
}); });
</script> </script>

View File

@ -2,20 +2,21 @@
<x-column :column="column" :is-stacked="isStacked" :menu="menu"> <x-column :column="column" :is-stacked="isStacked" :menu="menu">
<template #header><fa :icon="faAt" style="margin-right: 8px;"/>{{ column.name }}</template> <template #header><fa :icon="faAt" style="margin-right: 8px;"/>{{ column.name }}</template>
<x-mentions/> <x-notes :pagination="pagination" @before="before()" @after="after()"/>
</x-column> </x-column>
</template> </template>
<script lang="ts"> <script lang="ts">
import { defineComponent } from 'vue'; import { defineComponent } from 'vue';
import { faAt } from '@fortawesome/free-solid-svg-icons'; import { faAt } from '@fortawesome/free-solid-svg-icons';
import Progress from '../../scripts/loading';
import XColumn from './column.vue'; import XColumn from './column.vue';
import XMentions from '../../pages/mentions.vue'; import XNotes from '../notes.vue';
export default defineComponent({ export default defineComponent({
components: { components: {
XColumn, XColumn,
XMentions XNotes
}, },
props: { props: {
@ -32,8 +33,22 @@ export default defineComponent({
data() { data() {
return { return {
menu: null, menu: null,
pagination: {
endpoint: 'notes/mentions',
limit: 10,
},
faAt faAt
} }
}, },
methods: {
before() {
Progress.start();
},
after() {
Progress.done();
}
}
}); });
</script> </script>

View File

@ -34,19 +34,19 @@
</div> </div>
</div> </div>
<article class="article"> <article class="article">
<mk-avatar class="avatar" :user="appearNote.user"/> <mk-avatar class="avatar" :user="appearNote.user" v-once/>
<div class="main"> <div class="main">
<x-note-header class="header" :note="appearNote" :mini="true"/> <x-note-header class="header" :note="appearNote" :mini="true"/>
<div class="body" v-if="appearNote.deletedAt == null" ref="noteBody"> <div class="body" v-if="appearNote.deletedAt == null" ref="noteBody">
<p v-if="appearNote.cw != null" class="cw"> <p v-if="appearNote.cw != null" class="cw">
<mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" /> <mfm v-if="appearNote.cw != ''" class="text" :text="appearNote.cw" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" v-once/>
<x-cw-button v-model="showContent" :note="appearNote"/> <x-cw-button v-model="showContent" :note="appearNote"/>
</p> </p>
<div class="content" v-show="appearNote.cw == null || showContent"> <div class="content" v-show="appearNote.cw == null || showContent">
<div class="text"> <div class="text">
<span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $t('private') }})</span> <span v-if="appearNote.isHidden" style="opacity: 0.5">({{ $t('private') }})</span>
<router-link class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><fa :icon="faReply"/></router-link> <router-link class="reply" v-if="appearNote.replyId" :to="`/notes/${appearNote.replyId}`"><fa :icon="faReply"/></router-link>
<mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis"/> <mfm v-if="appearNote.text" :text="appearNote.text" :author="appearNote.user" :i="$store.state.i" :custom-emojis="appearNote.emojis" v-once/>
<a class="rp" v-if="appearNote.renote != null">RN:</a> <a class="rp" v-if="appearNote.renote != null">RN:</a>
</div> </div>
<div class="files" v-if="appearNote.files.length > 0"> <div class="files" v-if="appearNote.files.length > 0">

View File

@ -1,5 +1,5 @@
<template> <template>
<x-window @closed="() => { $emit('closed'); destroyDom(); }" :no-padding="true"> <x-window @closed="() => { $emit('closed'); destroyDom(); }" :no-padding="true" :width="520" :height="500">
<template #header>{{ instance.host }}</template> <template #header>{{ instance.host }}</template>
<div class="mk-instance-info"> <div class="mk-instance-info">
<div class="table info"> <div class="table info">

View File

@ -0,0 +1,111 @@
<template>
<mk-container :show-header="props.showHeader">
<template #header><fa :icon="faGlobe"/>{{ $t('_widgets.federation') }}</template>
<div class="wbrkwalb">
<mk-loading v-if="fetching"/>
<transition-group tag="div" name="chart" class="instances" v-else>
<div v-for="instance in instances" :key="instance.id">
<div class="instance">
<a class="a" :href="'https://' + instance.host" target="_blank" :title="instance.host">#{{ instance.host }}</a>
<p>{{ instance.softwareName }} {{ instance.softwareVersion }}</p>
</div>
<x-chart class="chart" :src="stat.chart"/>
</div>
</transition-group>
</div>
</mk-container>
</template>
<script lang="ts">
import { faGlobe } from '@fortawesome/free-solid-svg-icons';
import MkContainer from '../components/ui/container.vue';
import define from './define';
import XChart from './trends.chart.vue';
export default define({
name: 'federation',
props: () => ({
showHeader: {
type: 'boolean',
default: true,
},
})
}).extend({
components: {
MkContainer, XChart
},
data() {
return {
instances: [],
fetching: true,
faGlobe
};
},
mounted() {
this.fetch();
this.clock = setInterval(this.fetch, 1000 * 60);
},
beforeDestroy() {
clearInterval(this.clock);
},
methods: {
fetch() {
this.$root.api('federation/instances', {
sort: '+lastCommunicatedAt',
limit: 5
}).then(instances => {
this.instances = instances;
this.fetching = false;
});
}
}
});
</script>
<style lang="scss" scoped>
.wbrkwalb {
height: (62px + 1px) + (62px + 1px) + (62px + 1px) + (62px + 1px) + 62px;
overflow: hidden;
> .instances {
.chart-move {
transition: transform 1s ease;
}
> div {
display: flex;
align-items: center;
padding: 14px 16px;
border-bottom: solid 1px var(--divider);
> .instance {
flex: 1;
overflow: hidden;
font-size: 0.9em;
color: var(--fg);
> .a {
display: block;
width: 100%;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
line-height: 18px;
}
> p {
margin: 0;
font-size: 75%;
opacity: 0.7;
line-height: 16px;
}
}
> .chart {
height: 30px;
}
}
}
}
</style>

View File

@ -12,6 +12,7 @@ export default function(app: App) {
app.component('mkw-activity', defineAsyncComponent(() => import('./activity.vue').then(m => m.default))); app.component('mkw-activity', defineAsyncComponent(() => import('./activity.vue').then(m => m.default)));
app.component('mkw-photos', defineAsyncComponent(() => import('./photos.vue').then(m => m.default))); app.component('mkw-photos', defineAsyncComponent(() => import('./photos.vue').then(m => m.default)));
app.component('mkw-digitalClock', defineAsyncComponent(() => import('./digital-clock.vue').then(m => m.default))); app.component('mkw-digitalClock', defineAsyncComponent(() => import('./digital-clock.vue').then(m => m.default)));
app.component('mkw-federation', defineAsyncComponent(() => import('./federation.vue').then(m => m.default)));
} }
export const widgets = [ export const widgets = [
@ -25,4 +26,5 @@ export const widgets = [
'activity', 'activity',
'photos', 'photos',
'digitalClock', 'digitalClock',
'federation',
]; ];

View File

@ -26,7 +26,7 @@ describe('Get file info', () => {
}, },
width: undefined, width: undefined,
height: undefined, height: undefined,
blurhash: null blurhash: undefined
}); });
})); }));
@ -43,7 +43,7 @@ describe('Get file info', () => {
}, },
width: 512, width: 512,
height: 512, height: 512,
blurhash: '' // TODO blurhash: 'yFLxJjH[NE}@^PRiN_}Y=aVZNvFxxZ#SwIt7Eg%KIp-ospv~Nex[R6t3xZI:iwt6kWxDafoySgsAfR$*oyM|S2t7$iV[tQNbaKn%xt'
}); });
})); }));
@ -60,7 +60,7 @@ describe('Get file info', () => {
}, },
width: 256, width: 256,
height: 256, height: 256,
blurhash: '' // TODO blurhash: 'y8S?Mr-;=~~Xs;%foL?bWVs;xbR%NFay^ms;I-InI-xbs;%gofj[I-s;-WxbI-WUayxb$,NFR*~Wa{R%xbayNFI.oMj[oMNFWB$,WU'
}); });
})); }));
@ -77,7 +77,7 @@ describe('Get file info', () => {
}, },
width: 256, width: 256,
height: 256, height: 256,
blurhash: '' // TODO blurhash: 'y8S?Mr-;=~~Xs;%foL?bWVs;xbR%NFay^ms;I-InI-xbs;%gofj[I-s;-WxbI-WUayxb$,NFR*~Wa{R%xbayNFI.oMj[oMNFWB$,WU'
}); });
})); }));
@ -94,7 +94,7 @@ describe('Get file info', () => {
}, },
width: 256, width: 256,
height: 256, height: 256,
blurhash: '' // TODO blurhash: 'y74P29kDpdp{k?VDZ#krkCaefkf6fQf5HXZ$krkqadaKaJkCaKkXfkkCf5fkQ8kXZ#VDaKk?krZ~kCf6kDf6f5f6U]krZ#Z#aekrkq'
}); });
})); }));
@ -111,7 +111,7 @@ describe('Get file info', () => {
}, },
width: 256, width: 256,
height: 256, height: 256,
blurhash: '' // TODO blurhash: 'yMEKyd1U1?=nZN-2EwofR*oHnijYX6S50J=m]WEVl9JE$SR*xHR;XSX8nQxB-WS6Nts*aKskWnaxR%s*i_n~X6S5=#NgOAs*enoIWU'
}); });
})); }));
@ -129,7 +129,7 @@ describe('Get file info', () => {
}, },
width: 256, width: 256,
height: 256, height: 256,
blurhash: '' // TODO blurhash: 'yMEKyd1U1?=nZN-2EwofR*oHnijYX6S50J=m]WEVl9JE$SR*xHR;XSX8nQxB-WS6Nts*aKskWnaxR%s*i_n~X6S5=#NgOAs*enoIWU'
}); });
})); }));
@ -146,7 +146,7 @@ describe('Get file info', () => {
}, },
width: 25000, width: 25000,
height: 25000, height: 25000,
blurhash: '' // TODO blurhash: undefined
}); });
})); }));
}); });

View File

@ -1312,9 +1312,9 @@ ajv-keywords@^3.1.0, ajv-keywords@^3.4.1:
integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ== integrity sha512-RO1ibKvd27e6FEShVFfPALuHI3WjSVNeK5FIsmme/LYRNxjKuNj+Dt7bucLa6NdSv3JcVTyMlm9kGR84z1XpaQ==
ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.5.5: ajv@^6.1.0, ajv@^6.10.0, ajv@^6.10.2, ajv@^6.12.0, ajv@^6.12.2, ajv@^6.5.5:
version "6.12.2" version "6.12.3"
resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.2.tgz#c629c5eced17baf314437918d2da88c99d5958cd" resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.3.tgz#18c5af38a111ddeb4f2697bd78d68abc1cabd706"
integrity sha512-k+V+hzjm5q/Mr8ef/1Y9goCmlsK4I6Sm74teeyGvFk1XrOsbsKLjEdrvny42CZ+a8sXbk8KWpY/bDwS+FLL2UQ== integrity sha512-4K0cK3L1hsqk9xIb2z9vs/XU+PGJZ9PNpJRDS9YLzmNdX6jmVPfamLvTJr0aDAusnHyCHO6MjzlkAsgtqp9teA==
dependencies: dependencies:
fast-deep-equal "^3.1.1" fast-deep-equal "^3.1.1"
fast-json-stable-stringify "^2.0.0" fast-json-stable-stringify "^2.0.0"