summaryrefslogtreecommitdiff
path: root/src/client/app/common/views
diff options
context:
space:
mode:
authortamaina <tamaina@hotmail.co.jp>2018-09-15 22:15:56 +0900
committerGitHub <noreply@github.com>2018-09-15 22:15:56 +0900
commit8f8c67ad6d33eb9ced1844bb372d517204df6c6f (patch)
treebcaedee83bb5960a6b63291795dd95f9ed603a99 /src/client/app/common/views
parentfix mk-media darkmode (diff)
parent8.41.0 (diff)
downloadmisskey-8f8c67ad6d33eb9ced1844bb372d517204df6c6f.tar.gz
misskey-8f8c67ad6d33eb9ced1844bb372d517204df6c6f.tar.bz2
misskey-8f8c67ad6d33eb9ced1844bb372d517204df6c6f.zip
Merge branch 'develop' into improve-media
Diffstat (limited to 'src/client/app/common/views')
-rw-r--r--src/client/app/common/views/components/acct.vue12
-rw-r--r--src/client/app/common/views/components/avatar.vue21
-rw-r--r--src/client/app/common/views/components/cw-button.vue44
-rw-r--r--src/client/app/common/views/components/games/reversi/reversi.game.vue16
-rw-r--r--src/client/app/common/views/components/games/reversi/reversi.index.vue1
-rw-r--r--src/client/app/common/views/components/games/reversi/reversi.room.vue7
-rw-r--r--src/client/app/common/views/components/index.ts4
-rw-r--r--src/client/app/common/views/components/menu.vue2
-rw-r--r--src/client/app/common/views/components/misskey-flavored-markdown.ts57
-rw-r--r--src/client/app/common/views/components/note-menu.vue8
-rw-r--r--src/client/app/common/views/components/poll-editor.vue3
-rw-r--r--src/client/app/common/views/components/poll.vue3
-rw-r--r--src/client/app/common/views/components/reaction-icon.vue22
-rw-r--r--src/client/app/common/views/components/reaction-picker.vue4
-rw-r--r--src/client/app/common/views/components/tag-cloud.vue90
-rw-r--r--src/client/app/common/views/components/ui/card.vue27
-rw-r--r--src/client/app/common/views/components/ui/radio.vue2
-rw-r--r--src/client/app/common/views/components/ui/switch.vue7
-rw-r--r--src/client/app/common/views/components/url-preview.vue2
-rw-r--r--src/client/app/common/views/components/visibility-chooser.vue10
-rw-r--r--src/client/app/common/views/components/welcome-timeline.vue131
-rw-r--r--src/client/app/common/views/directives/autocomplete.ts2
-rw-r--r--src/client/app/common/views/pages/follow.vue1
-rw-r--r--src/client/app/common/views/widgets/analog-clock.vue9
-rw-r--r--src/client/app/common/views/widgets/broadcast.vue18
25 files changed, 340 insertions, 163 deletions
diff --git a/src/client/app/common/views/components/acct.vue b/src/client/app/common/views/components/acct.vue
index 1ad222afdd..542fbb4296 100644
--- a/src/client/app/common/views/components/acct.vue
+++ b/src/client/app/common/views/components/acct.vue
@@ -1,19 +1,25 @@
<template>
<span class="mk-acct">
<span class="name">@{{ user.username }}</span>
- <span class="host" v-if="user.host">@{{ user.host }}</span>
+ <span class="host" :class="{ fade: $store.state.settings.contrastedAcct }" v-if="user.host || detail || $store.state.settings.showFullAcct">@{{ user.host || host }}</span>
</span>
</template>
<script lang="ts">
import Vue from 'vue';
+import { host } from '../../../config';
export default Vue.extend({
- props: ['user']
+ props: ['user', 'detail'],
+ data() {
+ return {
+ host
+ };
+ }
});
</script>
<style lang="stylus" scoped>
.mk-acct
- > .host
+ > .host.fade
opacity 0.5
</style>
diff --git a/src/client/app/common/views/components/avatar.vue b/src/client/app/common/views/components/avatar.vue
index c5ac74e537..a2b0fc6bd3 100644
--- a/src/client/app/common/views/components/avatar.vue
+++ b/src/client/app/common/views/components/avatar.vue
@@ -1,15 +1,15 @@
<template>
- <span class="mk-avatar" :class="{ cat }" :title="user | acct" v-if="disableLink && !disablePreview" v-user-preview="user.id" @click="onClick">
- <span class="inner" :style="style"></span>
+ <span class="mk-avatar" :style="style" :class="{ cat }" :title="user | acct" v-if="disableLink && !disablePreview" v-user-preview="user.id" @click="onClick">
+ <span class="inner" :style="icon"></span>
</span>
- <span class="mk-avatar" :class="{ cat }" :title="user | acct" v-else-if="disableLink && disablePreview" @click="onClick">
- <span class="inner" :style="style"></span>
+ <span class="mk-avatar" :style="style" :class="{ cat }" :title="user | acct" v-else-if="disableLink && disablePreview" @click="onClick">
+ <span class="inner" :style="icon"></span>
</span>
- <router-link class="mk-avatar" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && !disablePreview" v-user-preview="user.id">
- <span class="inner" :style="style"></span>
+ <router-link class="mk-avatar" :style="style" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && !disablePreview" v-user-preview="user.id">
+ <span class="inner" :style="icon"></span>
</router-link>
- <router-link class="mk-avatar" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && disablePreview">
- <span class="inner" :style="style"></span>
+ <router-link class="mk-avatar" :style="style" :class="{ cat }" :to="user | userPage" :title="user | acct" :target="target" v-else-if="!disableLink && disablePreview">
+ <span class="inner" :style="icon"></span>
</router-link>
</template>
@@ -43,6 +43,11 @@ export default Vue.extend({
},
style(): any {
return {
+ borderRadius: this.$store.state.settings.circleIcons ? '100%' : null
+ };
+ },
+ icon(): any {
+ return {
backgroundColor: this.lightmode
? `rgb(${this.user.avatarColor.slice(0, 3).join(',')})`
: this.user.avatarColor && this.user.avatarColor.length == 3
diff --git a/src/client/app/common/views/components/cw-button.vue b/src/client/app/common/views/components/cw-button.vue
new file mode 100644
index 0000000000..06087edc93
--- /dev/null
+++ b/src/client/app/common/views/components/cw-button.vue
@@ -0,0 +1,44 @@
+<template>
+<button class="nrvgflfuaxwgkxoynpnumyookecqrrvh" @click="toggle">{{ value ? '%i18n:@hide%' : '%i18n:@show%' }}</button>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+
+export default Vue.extend({
+ props: {
+ value: {
+ type: Boolean,
+ required: true
+ }
+ },
+
+ methods: {
+ toggle() {
+ this.$emit('input', !this.value);
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+root(isDark)
+ display inline-block
+ padding 4px 8px
+ font-size 0.7em
+ color isDark ? #393f4f : #fff
+ background isDark ? #687390 : #b1b9c1
+ border-radius 2px
+ cursor pointer
+ user-select none
+
+ &:hover
+ background isDark ? #707b97 : #bbc4ce
+
+.nrvgflfuaxwgkxoynpnumyookecqrrvh[data-darkmode]
+ root(true)
+
+.nrvgflfuaxwgkxoynpnumyookecqrrvh:not([data-darkmode])
+ root(false)
+
+</style>
diff --git a/src/client/app/common/views/components/games/reversi/reversi.game.vue b/src/client/app/common/views/components/games/reversi/reversi.game.vue
index 673879a435..fea19d917e 100644
--- a/src/client/app/common/views/components/games/reversi/reversi.game.vue
+++ b/src/client/app/common/views/components/games/reversi/reversi.game.vue
@@ -50,15 +50,15 @@
</div>
<div class="player" v-if="game.isEnded">
- <el-button-group>
- <el-button type="primary" @click="logPos = 0" :disabled="logPos == 0">%fa:angle-double-left%</el-button>
- <el-button type="primary" @click="logPos--" :disabled="logPos == 0">%fa:angle-left%</el-button>
- </el-button-group>
+ <div>
+ <button @click="logPos = 0" :disabled="logPos == 0">%fa:angle-double-left%</button>
+ <button @click="logPos--" :disabled="logPos == 0">%fa:angle-left%</button>
+ </div>
<span>{{ logPos }} / {{ logs.length }}</span>
- <el-button-group>
- <el-button type="primary" @click="logPos++" :disabled="logPos == logs.length">%fa:angle-right%</el-button>
- <el-button type="primary" @click="logPos = logs.length" :disabled="logPos == logs.length">%fa:angle-double-right%</el-button>
- </el-button-group>
+ <div>
+ <button @click="logPos++" :disabled="logPos == logs.length">%fa:angle-right%</button>
+ <button @click="logPos = logs.length" :disabled="logPos == logs.length">%fa:angle-double-right%</button>
+ </div>
</div>
<div class="info">
diff --git a/src/client/app/common/views/components/games/reversi/reversi.index.vue b/src/client/app/common/views/components/games/reversi/reversi.index.vue
index fa88aeaaf4..d23902aae7 100644
--- a/src/client/app/common/views/components/games/reversi/reversi.index.vue
+++ b/src/client/app/common/views/components/games/reversi/reversi.index.vue
@@ -3,7 +3,6 @@
<h1>%i18n:@title%</h1>
<p>%i18n:@sub-title%</p>
<div class="play">
- <!--<el-button round>フリーマッチ(準備中)</el-button>-->
<form-button primary round @click="match">%i18n:@invite%</form-button>
<details>
<summary>%i18n:@rule%</summary>
diff --git a/src/client/app/common/views/components/games/reversi/reversi.room.vue b/src/client/app/common/views/components/games/reversi/reversi.room.vue
index aed8718dd0..fef833d63e 100644
--- a/src/client/app/common/views/components/games/reversi/reversi.room.vue
+++ b/src/client/app/common/views/components/games/reversi/reversi.room.vue
@@ -59,11 +59,6 @@
</header>
<div>
- <el-alert v-for="message in messages"
- :title="message.text"
- :type="message.type"
- :key="message.id"/>
-
<template v-for="item in form">
<mk-switch v-if="item.type == 'switch'" v-model="item.value" :key="item.id" :text="item.label" @change="onChangeForm(item)">{{ item.desc || '' }}</mk-switch>
@@ -93,7 +88,7 @@
</header>
<div>
- <el-input v-model="item.value" @change="onChangeForm(item)"/>
+ <input v-model="item.value" @change="onChangeForm(item)"/>
</div>
</div>
</template>
diff --git a/src/client/app/common/views/components/index.ts b/src/client/app/common/views/components/index.ts
index 43cde6c54f..21af4ec846 100644
--- a/src/client/app/common/views/components/index.ts
+++ b/src/client/app/common/views/components/index.ts
@@ -1,5 +1,7 @@
import Vue from 'vue';
+import cwButton from './cw-button.vue';
+import tagCloud from './tag-cloud.vue';
import trends from './trends.vue';
import analogClock from './analog-clock.vue';
import menu from './menu.vue';
@@ -42,6 +44,8 @@ import uiSelect from './ui/select.vue';
import formButton from './ui/form/button.vue';
import formRadio from './ui/form/radio.vue';
+Vue.component('mk-cw-button', cwButton);
+Vue.component('mk-tag-cloud', tagCloud);
Vue.component('mk-trends', trends);
Vue.component('mk-analog-clock', analogClock);
Vue.component('mk-menu', menu);
diff --git a/src/client/app/common/views/components/menu.vue b/src/client/app/common/views/components/menu.vue
index e99bfcbd26..fba7e235e0 100644
--- a/src/client/app/common/views/components/menu.vue
+++ b/src/client/app/common/views/components/menu.vue
@@ -108,7 +108,7 @@ export default Vue.extend({
easing: 'easeInBack',
complete: () => {
this.$emit('closed');
- this.$destroy();
+ this.destroyDom();
}
});
}
diff --git a/src/client/app/common/views/components/misskey-flavored-markdown.ts b/src/client/app/common/views/components/misskey-flavored-markdown.ts
index 44680751f7..224bd6f5de 100644
--- a/src/client/app/common/views/components/misskey-flavored-markdown.ts
+++ b/src/client/app/common/views/components/misskey-flavored-markdown.ts
@@ -1,4 +1,4 @@
-import Vue from 'vue';
+import Vue, { VNode } from 'vue';
import * as emojilib from 'emojilib';
import { length } from 'stringz';
import parse from '../../../../../mfm/parse';
@@ -6,10 +6,7 @@ import getAcct from '../../../../../misc/acct/render';
import { url } from '../../../config';
import MkUrl from './url.vue';
import MkGoogle from './google.vue';
-
-const flatten = list => list.reduce(
- (a, b) => a.concat(Array.isArray(b) ? flatten(b) : b), []
-);
+import { concat } from '../../../../../prelude/array';
export default Vue.component('misskey-flavored-markdown', {
props: {
@@ -32,20 +29,20 @@ export default Vue.component('misskey-flavored-markdown', {
},
render(createElement) {
- let ast;
+ let ast: any[];
if (this.ast == null) {
// Parse text to ast
ast = parse(this.text);
} else {
- ast = this.ast;
+ ast = this.ast as any[];
}
let bigCount = 0;
let motionCount = 0;
// Parse ast to DOM
- const els = flatten(ast.map(token => {
+ const els = concat(ast.map((token): VNode[] => {
switch (token.type) {
case 'text': {
const text = token.content.replace(/(\r\n|\n|\r)/g, '\n');
@@ -56,12 +53,12 @@ export default Vue.component('misskey-flavored-markdown', {
x[x.length - 1].pop();
return x;
} else {
- return createElement('span', text.replace(/\n/g, ' '));
+ return [createElement('span', text.replace(/\n/g, ' '))];
}
}
case 'bold': {
- return createElement('b', token.bold);
+ return [createElement('b', token.bold)];
}
case 'big': {
@@ -95,23 +92,23 @@ export default Vue.component('misskey-flavored-markdown', {
}
case 'url': {
- return createElement(MkUrl, {
+ return [createElement(MkUrl, {
props: {
url: token.content,
target: '_blank'
}
- });
+ })];
}
case 'link': {
- return createElement('a', {
+ return [createElement('a', {
attrs: {
class: 'link',
href: token.url,
target: '_blank',
title: token.url
}
- }, token.title);
+ }, token.title)];
}
case 'mention': {
@@ -129,16 +126,16 @@ export default Vue.component('misskey-flavored-markdown', {
}
case 'hashtag': {
- return createElement('a', {
+ return [createElement('a', {
attrs: {
href: `${url}/tags/${encodeURIComponent(token.hashtag)}`,
target: '_blank'
}
- }, token.content);
+ }, token.content)];
}
case 'code': {
- return createElement('pre', {
+ return [createElement('pre', {
class: 'code'
}, [
createElement('code', {
@@ -146,15 +143,15 @@ export default Vue.component('misskey-flavored-markdown', {
innerHTML: token.html
}
})
- ]);
+ ])];
}
case 'inline-code': {
- return createElement('code', {
+ return [createElement('code', {
domProps: {
innerHTML: token.html
}
- });
+ })];
}
case 'quote': {
@@ -164,43 +161,45 @@ export default Vue.component('misskey-flavored-markdown', {
const x = text2.split('\n')
.map(t => [createElement('span', t), createElement('br')]);
x[x.length - 1].pop();
- return createElement('div', {
+ return [createElement('div', {
attrs: {
class: 'quote'
}
- }, x);
+ }, x)];
} else {
- return createElement('span', {
+ return [createElement('span', {
attrs: {
class: 'quote'
}
- }, text2.replace(/\n/g, ' '));
+ }, text2.replace(/\n/g, ' '))];
}
}
case 'title': {
- return createElement('div', {
+ return [createElement('div', {
attrs: {
class: 'title'
}
- }, token.title);
+ }, token.title)];
}
case 'emoji': {
const emoji = emojilib.lib[token.emoji];
- return createElement('span', emoji ? emoji.char : token.content);
+ return [createElement('span', emoji ? emoji.char : token.content)];
}
case 'search': {
- return createElement(MkGoogle, {
+ return [createElement(MkGoogle, {
props: {
q: token.query
}
- });
+ })];
}
default: {
console.log('unknown ast type:', token.type);
+
+ return [];
}
}
}));
diff --git a/src/client/app/common/views/components/note-menu.vue b/src/client/app/common/views/components/note-menu.vue
index 0b0609ac4e..c9912fb1e2 100644
--- a/src/client/app/common/views/components/note-menu.vue
+++ b/src/client/app/common/views/components/note-menu.vue
@@ -64,7 +64,7 @@ export default Vue.extend({
(this as any).api('i/pin', {
noteId: this.note.id
}).then(() => {
- this.$destroy();
+ this.destroyDom();
});
},
@@ -73,7 +73,7 @@ export default Vue.extend({
(this as any).api('notes/delete', {
noteId: this.note.id
}).then(() => {
- this.$destroy();
+ this.destroyDom();
});
},
@@ -81,13 +81,13 @@ export default Vue.extend({
(this as any).api('notes/favorites/create', {
noteId: this.note.id
}).then(() => {
- this.$destroy();
+ this.destroyDom();
});
},
closed() {
this.$nextTick(() => {
- this.$destroy();
+ this.destroyDom();
});
}
}
diff --git a/src/client/app/common/views/components/poll-editor.vue b/src/client/app/common/views/components/poll-editor.vue
index 115c934c8b..30d9799fec 100644
--- a/src/client/app/common/views/components/poll-editor.vue
+++ b/src/client/app/common/views/components/poll-editor.vue
@@ -20,6 +20,7 @@
<script lang="ts">
import Vue from 'vue';
+import { erase } from '../../../../../prelude/array';
export default Vue.extend({
data() {
return {
@@ -53,7 +54,7 @@ export default Vue.extend({
get() {
return {
- choices: this.choices.filter(choice => choice != '')
+ choices: erase('', this.choices)
}
},
diff --git a/src/client/app/common/views/components/poll.vue b/src/client/app/common/views/components/poll.vue
index 660247edbc..4fe51d219b 100644
--- a/src/client/app/common/views/components/poll.vue
+++ b/src/client/app/common/views/components/poll.vue
@@ -21,6 +21,7 @@
<script lang="ts">
import Vue from 'vue';
+import { sum } from '../../../../../prelude/array';
export default Vue.extend({
props: ['note'],
data() {
@@ -33,7 +34,7 @@ export default Vue.extend({
return this.note.poll;
},
total(): number {
- return this.poll.choices.reduce((a, b) => a + b.votes, 0);
+ return sum(this.poll.choices.map(x => x.votes));
},
isVoted(): boolean {
return this.poll.choices.some(c => c.isVoted);
diff --git a/src/client/app/common/views/components/reaction-icon.vue b/src/client/app/common/views/components/reaction-icon.vue
index 46886b8ab2..c668efac6b 100644
--- a/src/client/app/common/views/components/reaction-icon.vue
+++ b/src/client/app/common/views/components/reaction-icon.vue
@@ -1,17 +1,17 @@
<template>
<span class="mk-reaction-icon">
- <img v-if="reaction == 'like'" src="/assets/reactions/like.png" alt="%i18n:common.reactions.like%">
- <img v-if="reaction == 'love'" src="/assets/reactions/love.png" alt="%i18n:common.reactions.love%">
- <img v-if="reaction == 'laugh'" src="/assets/reactions/laugh.png" alt="%i18n:common.reactions.laugh%">
- <img v-if="reaction == 'hmm'" src="/assets/reactions/hmm.png" alt="%i18n:common.reactions.hmm%">
- <img v-if="reaction == 'surprise'" src="/assets/reactions/surprise.png" alt="%i18n:common.reactions.surprise%">
- <img v-if="reaction == 'congrats'" src="/assets/reactions/congrats.png" alt="%i18n:common.reactions.congrats%">
- <img v-if="reaction == 'angry'" src="/assets/reactions/angry.png" alt="%i18n:common.reactions.angry%">
- <img v-if="reaction == 'confused'" src="/assets/reactions/confused.png" alt="%i18n:common.reactions.confused%">
- <img v-if="reaction == 'rip'" src="/assets/reactions/rip.png" alt="%i18n:common.reactions.rip%">
+ <img v-if="reaction == 'like'" src="https://twemoji.maxcdn.com/2/svg/1f44d.svg" alt="%i18n:common.reactions.like%">
+ <img v-if="reaction == 'love'" src="https://twemoji.maxcdn.com/2/svg/2764.svg" alt="%i18n:common.reactions.love%">
+ <img v-if="reaction == 'laugh'" src="https://twemoji.maxcdn.com/2/svg/1f606.svg" alt="%i18n:common.reactions.laugh%">
+ <img v-if="reaction == 'hmm'" src="https://twemoji.maxcdn.com/2/svg/1f914.svg" alt="%i18n:common.reactions.hmm%">
+ <img v-if="reaction == 'surprise'" src="https://twemoji.maxcdn.com/2/svg/1f62e.svg" alt="%i18n:common.reactions.surprise%">
+ <img v-if="reaction == 'congrats'" src="https://twemoji.maxcdn.com/2/svg/1f389.svg" alt="%i18n:common.reactions.congrats%">
+ <img v-if="reaction == 'angry'" src="https://twemoji.maxcdn.com/2/svg/1f4a2.svg" alt="%i18n:common.reactions.angry%">
+ <img v-if="reaction == 'confused'" src="https://twemoji.maxcdn.com/2/svg/1f625.svg" alt="%i18n:common.reactions.confused%">
+ <img v-if="reaction == 'rip'" src="https://twemoji.maxcdn.com/2/svg/1f607.svg" alt="%i18n:common.reactions.rip%">
<template v-if="reaction == 'pudding'">
- <img v-if="$store.getters.isSignedIn && $store.state.settings.iLikeSushi" src="/assets/reactions/sushi.png" alt="%i18n:common.reactions.pudding%">
- <img v-else src="/assets/reactions/pudding.png" alt="%i18n:common.reactions.pudding%">
+ <img v-if="$store.getters.isSignedIn && $store.state.settings.iLikeSushi" src="https://twemoji.maxcdn.com/2/svg/1f363.svg" alt="%i18n:common.reactions.pudding%">
+ <img v-else src="https://twemoji.maxcdn.com/2/svg/1f36e.svg" alt="%i18n:common.reactions.pudding%">
</template>
</span>
</template>
diff --git a/src/client/app/common/views/components/reaction-picker.vue b/src/client/app/common/views/components/reaction-picker.vue
index a455afbf7d..a4828c987b 100644
--- a/src/client/app/common/views/components/reaction-picker.vue
+++ b/src/client/app/common/views/components/reaction-picker.vue
@@ -95,7 +95,7 @@ export default Vue.extend({
reaction: reaction
}).then(() => {
if (this.cb) this.cb();
- this.$destroy();
+ this.destroyDom();
});
},
onMouseover(e) {
@@ -120,7 +120,7 @@ export default Vue.extend({
scale: 0.5,
duration: 200,
easing: 'easeInBack',
- complete: () => this.$destroy()
+ complete: () => this.destroyDom()
});
}
}
diff --git a/src/client/app/common/views/components/tag-cloud.vue b/src/client/app/common/views/components/tag-cloud.vue
new file mode 100644
index 0000000000..5f2cc5276a
--- /dev/null
+++ b/src/client/app/common/views/components/tag-cloud.vue
@@ -0,0 +1,90 @@
+<template>
+<div class="jtivnzhfwquxpsfidertopbmwmchmnmo">
+ <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
+ <p class="empty" v-else-if="tags.length == 0">%fa:exclamation-circle%%i18n:@empty%</p>
+ <div v-else>
+ <vue-word-cloud
+ :words="tags.slice(0, 20).map(x => [x.name, x.count])"
+ :color="color"
+ :spacing="1">
+ <template slot-scope="{word, text, weight}">
+ <div style="cursor: pointer;" :title="weight">
+ {{ text }}
+ </div>
+ </template>
+ </vue-word-cloud>
+ </div>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+import * as VueWordCloud from 'vuewordcloud';
+
+export default Vue.extend({
+ components: {
+ [VueWordCloud.name]: VueWordCloud
+ },
+ data() {
+ return {
+ tags: [],
+ fetching: true,
+ clock: null
+ };
+ },
+ mounted() {
+ this.fetch();
+ this.clock = setInterval(this.fetch, 1000 * 60);
+ },
+ beforeDestroy() {
+ clearInterval(this.clock);
+ },
+ methods: {
+ fetch() {
+ (this as any).api('aggregation/hashtags').then(tags => {
+ this.tags = tags;
+ this.fetching = false;
+ });
+ },
+ color([, weight]) {
+ const peak = Math.max.apply(null, this.tags.map(x => x.count));
+ const w = weight / peak;
+
+ if (w > 0.9) {
+ return this.$store.state.device.darkmode ? '#ff4e69' : '#ff4e69';
+ } else if (w > 0.5) {
+ return this.$store.state.device.darkmode ? '#3bc4c7' : '#3bc4c7';
+ } else {
+ return this.$store.state.device.darkmode ? '#fff' : '#555';
+ }
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+root(isDark)
+ height 100%
+ width 100%
+
+ > .fetching
+ > .empty
+ margin 0
+ padding 16px
+ text-align center
+ color #aaa
+
+ > [data-fa]
+ margin-right 4px
+
+ > div
+ height 100%
+ width 100%
+
+.jtivnzhfwquxpsfidertopbmwmchmnmo[data-darkmode]
+ root(true)
+
+.jtivnzhfwquxpsfidertopbmwmchmnmo:not([data-darkmode])
+ root(false)
+
+</style>
diff --git a/src/client/app/common/views/components/ui/card.vue b/src/client/app/common/views/components/ui/card.vue
index 05c51bca6b..aa16b557e1 100644
--- a/src/client/app/common/views/components/ui/card.vue
+++ b/src/client/app/common/views/components/ui/card.vue
@@ -24,19 +24,34 @@ export default Vue.extend({
root(isDark)
margin 16px
- padding 16px
color isDark ? #fff : #000
background isDark ? #282C37 : #fff
box-shadow 0 3px 1px -2px rgba(#000, 0.2), 0 2px 2px 0 rgba(#000, 0.14), 0 1px 5px 0 rgba(#000, 0.12)
- @media (min-width 500px)
- padding 32px
-
> header
- font-weight normal
- font-size 24px
+ padding 16px
+ font-weight bold
+ font-size 20px
color isDark ? #fff : #444
+ @media (min-width 500px)
+ padding 24px 32px
+
+ > section
+ padding 20px 16px
+ border-top solid 1px isDark ? rgba(#000, 0.3) : rgba(#000, 0.1)
+
+ @media (min-width 500px)
+ padding 32px
+
+ &.fit-top
+ padding-top 0
+
+ > header
+ margin-bottom 16px
+ font-weight bold
+ color isDark ? #fff : #444
+
.ui-card[data-darkmode]
root(true)
diff --git a/src/client/app/common/views/components/ui/radio.vue b/src/client/app/common/views/components/ui/radio.vue
index 04a46c5a96..dcdda1cf0e 100644
--- a/src/client/app/common/views/components/ui/radio.vue
+++ b/src/client/app/common/views/components/ui/radio.vue
@@ -55,7 +55,7 @@ export default Vue.extend({
root(isDark)
display inline-block
- margin 32px 32px 32px 0
+ margin 0 32px 0 0
cursor pointer
transition all 0.3s
diff --git a/src/client/app/common/views/components/ui/switch.vue b/src/client/app/common/views/components/ui/switch.vue
index a9e00d73d2..e88b867801 100644
--- a/src/client/app/common/views/components/ui/switch.vue
+++ b/src/client/app/common/views/components/ui/switch.vue
@@ -64,6 +64,12 @@ root(isDark)
cursor pointer
transition all 0.3s
+ &:first-child
+ margin-top 0
+
+ &:last-child
+ margin-bottom 0
+
> *
user-select none
@@ -89,6 +95,7 @@ root(isDark)
> .button
display inline-block
+ flex-shrink 0
margin 3px 0 0 0
width 34px
height 14px
diff --git a/src/client/app/common/views/components/url-preview.vue b/src/client/app/common/views/components/url-preview.vue
index e182e7f8cb..f9b8415b5b 100644
--- a/src/client/app/common/views/components/url-preview.vue
+++ b/src/client/app/common/views/components/url-preview.vue
@@ -14,7 +14,7 @@
<header>
<h1>{{ title }}</h1>
</header>
- <p>{{ description }}</p>
+ <p>{{ description.length > 85 ? description.slice(0, 85) + '…' : description }}</p>
<footer>
<img class="icon" v-if="icon" :src="icon"/>
<p>{{ sitename }}</p>
diff --git a/src/client/app/common/views/components/visibility-chooser.vue b/src/client/app/common/views/components/visibility-chooser.vue
index 4691604e57..1830b1832e 100644
--- a/src/client/app/common/views/components/visibility-chooser.vue
+++ b/src/client/app/common/views/components/visibility-chooser.vue
@@ -47,7 +47,7 @@ export default Vue.extend({
props: ['source', 'compact'],
data() {
return {
- v: this.$store.state.device.visibility || 'public'
+ v: this.$store.state.settings.rememberNoteVisibility ? (this.$store.state.device.visibility || this.$store.state.settings.defaultNoteVisibility) : this.$store.state.settings.defaultNoteVisibility
}
},
mounted() {
@@ -97,9 +97,11 @@ export default Vue.extend({
},
methods: {
choose(visibility) {
- this.$store.commit('device/setVisibility', visibility);
+ if (this.$store.state.settings.rememberNoteVisibility) {
+ this.$store.commit('device/setVisibility', visibility);
+ }
this.$emit('chosen', visibility);
- this.$destroy();
+ this.destroyDom();
},
close() {
(this.$refs.backdrop as any).style.pointerEvents = 'none';
@@ -117,7 +119,7 @@ export default Vue.extend({
scale: 0.5,
duration: 200,
easing: 'easeInBack',
- complete: () => this.$destroy()
+ complete: () => this.destroyDom()
});
}
}
diff --git a/src/client/app/common/views/components/welcome-timeline.vue b/src/client/app/common/views/components/welcome-timeline.vue
index d4e7902c7b..965ec78559 100644
--- a/src/client/app/common/views/components/welcome-timeline.vue
+++ b/src/client/app/common/views/components/welcome-timeline.vue
@@ -1,22 +1,24 @@
<template>
<div class="mk-welcome-timeline">
- <div v-for="note in notes">
- <mk-avatar class="avatar" :user="note.user" target="_blank"/>
- <div class="body">
- <header>
- <router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link>
- <span class="username">@{{ note.user | acct }}</span>
- <div class="info">
- <router-link class="created-at" :to="note | notePage">
- <mk-time :time="note.createdAt"/>
- </router-link>
+ <transition-group name="ldzpakcixzickvggyixyrhqwjaefknon" tag="div">
+ <div v-for="note in notes" :key="note.id">
+ <mk-avatar class="avatar" :user="note.user" target="_blank"/>
+ <div class="body">
+ <header>
+ <router-link class="name" :to="note.user | userPage" v-user-preview="note.user.id">{{ note.user | userName }}</router-link>
+ <span class="username">@{{ note.user | acct }}</span>
+ <div class="info">
+ <router-link class="created-at" :to="note | notePage">
+ <mk-time :time="note.createdAt"/>
+ </router-link>
+ </div>
+ </header>
+ <div class="text">
+ <misskey-flavored-markdown v-if="note.text" :text="note.text"/>
</div>
- </header>
- <div class="text">
- <misskey-flavored-markdown v-if="note.text" :text="note.text"/>
</div>
</div>
- </div>
+ </transition-group>
</div>
</template>
@@ -63,7 +65,7 @@ export default Vue.extend({
local: true,
reply: false,
renote: false,
- media: false,
+ file: false,
poll: false
}).then(notes => {
this.notes = notes;
@@ -83,64 +85,73 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
+.ldzpakcixzickvggyixyrhqwjaefknon-enter
+.ldzpakcixzickvggyixyrhqwjaefknon-leave-to
+ opacity 0
+ transform translateY(-30px)
+
root(isDark)
background isDark ? #282C37 : #fff
> div
- padding 16px
- overflow-wrap break-word
- font-size .9em
- color isDark ? #fff : #4C4C4C
- border-bottom 1px solid isDark ? rgba(#000, 0.1) : rgba(#000, 0.05)
+ > *
+ transition transform .3s ease, opacity .3s ease
+
+ > div
+ padding 16px
+ overflow-wrap break-word
+ font-size .9em
+ color isDark ? #fff : #4C4C4C
+ border-bottom 1px solid isDark ? rgba(#000, 0.1) : rgba(#000, 0.05)
- &:after
- content ""
- display block
- clear both
+ &:after
+ content ""
+ display block
+ clear both
- > .avatar
- display block
- float left
- position -webkit-sticky
- position sticky
- top 16px
- width 42px
- height 42px
- border-radius 6px
+ > .avatar
+ display block
+ float left
+ position -webkit-sticky
+ position sticky
+ top 16px
+ width 42px
+ height 42px
+ border-radius 6px
- > .body
- float right
- width calc(100% - 42px)
- padding-left 12px
+ > .body
+ float right
+ width calc(100% - 42px)
+ padding-left 12px
- > header
- display flex
- align-items center
- margin-bottom 4px
- white-space nowrap
+ > header
+ display flex
+ align-items center
+ margin-bottom 4px
+ white-space nowrap
- > .name
- display block
- margin 0 .5em 0 0
- padding 0
- overflow hidden
- font-weight bold
- text-overflow ellipsis
- color isDark ? #fff : #627079
+ > .name
+ display block
+ margin 0 .5em 0 0
+ padding 0
+ overflow hidden
+ font-weight bold
+ text-overflow ellipsis
+ color isDark ? #fff : #627079
- > .username
- margin 0 .5em 0 0
- color isDark ? #606984 : #ccc
+ > .username
+ margin 0 .5em 0 0
+ color isDark ? #606984 : #ccc
- > .info
- margin-left auto
- font-size 0.9em
+ > .info
+ margin-left auto
+ font-size 0.9em
- > .created-at
- color isDark ? #606984 : #c0c0c0
+ > .created-at
+ color isDark ? #606984 : #c0c0c0
- > .text
- text-align left
+ > .text
+ text-align left
.mk-welcome-timeline[data-darkmode]
root(true)
diff --git a/src/client/app/common/views/directives/autocomplete.ts b/src/client/app/common/views/directives/autocomplete.ts
index 26bc13871d..f7f8e9bf16 100644
--- a/src/client/app/common/views/directives/autocomplete.ts
+++ b/src/client/app/common/views/directives/autocomplete.ts
@@ -167,7 +167,7 @@ class Autocomplete {
private close() {
if (this.suggestion == null) return;
- this.suggestion.$destroy();
+ this.suggestion.destroyDom();
this.suggestion = null;
this.textarea.focus();
diff --git a/src/client/app/common/views/pages/follow.vue b/src/client/app/common/views/pages/follow.vue
index 05c1329f6d..80a870a257 100644
--- a/src/client/app/common/views/pages/follow.vue
+++ b/src/client/app/common/views/pages/follow.vue
@@ -32,7 +32,6 @@
<script lang="ts">
import Vue from 'vue';
import parseAcct from '../../../../../misc/acct/parse';
-import getUserName from '../../../../../misc/get-user-name';
import Progress from '../../../common/scripts/loading';
export default Vue.extend({
diff --git a/src/client/app/common/views/widgets/analog-clock.vue b/src/client/app/common/views/widgets/analog-clock.vue
index 0de30228b3..04223f0d21 100644
--- a/src/client/app/common/views/widgets/analog-clock.vue
+++ b/src/client/app/common/views/widgets/analog-clock.vue
@@ -1,8 +1,8 @@
<template>
<div class="mkw-analog-clock">
- <mk-widget-container :naked="!(props.design % 2)" :show-header="false">
+ <mk-widget-container :naked="props.style % 2 === 0" :show-header="false">
<div class="mkw-analog-clock--body">
- <mk-analog-clock :dark="$store.state.device.darkmode" :smooth="!(props.design && ~props.design)"/>
+ <mk-analog-clock :dark="$store.state.device.darkmode" :smooth="props.style < 2"/>
</div>
</mk-widget-container>
</div>
@@ -13,13 +13,12 @@ import define from '../../../common/define-widget';
export default define({
name: 'analog-clock',
props: () => ({
- design: -1
+ style: 0
})
}).extend({
methods: {
func() {
- if (++this.props.design > 2)
- this.props.design = -1;
+ this.props.style = (this.props.style + 1) % 4;
this.save();
}
}
diff --git a/src/client/app/common/views/widgets/broadcast.vue b/src/client/app/common/views/widgets/broadcast.vue
index e4e77263e5..f2fa720f52 100644
--- a/src/client/app/common/views/widgets/broadcast.vue
+++ b/src/client/app/common/views/widgets/broadcast.vue
@@ -1,6 +1,6 @@
<template>
<div class="anltbovirfeutcigvwgmgxipejaeozxi"
- :data-found="broadcasts.length != 0"
+ :data-found="announcements && announcements.length != 0"
:data-melt="props.design == 1"
:data-mobile="platform == 'mobile'"
>
@@ -14,12 +14,12 @@
</svg>
</div>
<p class="fetching" v-if="fetching">%i18n:@fetching%<mk-ellipsis/></p>
- <h1 v-if="!fetching">{{ broadcasts.length == 0 ? '%i18n:@no-broadcasts%' : broadcasts[i].title }}</h1>
+ <h1 v-if="!fetching">{{ announcements.length == 0 ? '%i18n:@no-broadcasts%' : announcements[i].title }}</h1>
<p v-if="!fetching">
- <span v-if="broadcasts.length != 0" v-html="broadcasts[i].text"></span>
- <template v-if="broadcasts.length == 0">%i18n:@have-a-nice-day%</template>
+ <span v-if="announcements.length != 0" v-html="announcements[i].text"></span>
+ <template v-if="announcements.length == 0">%i18n:@have-a-nice-day%</template>
</p>
- <a v-if="broadcasts.length > 1" @click="next">%i18n:@next% &gt;&gt;</a>
+ <a v-if="announcements.length > 1" @click="next">%i18n:@next% &gt;&gt;</a>
</div>
</template>
@@ -36,18 +36,18 @@ export default define({
return {
i: 0,
fetching: true,
- broadcasts: []
+ announcements: []
};
},
mounted() {
(this as any).os.getMeta().then(meta => {
- this.broadcasts = meta.broadcasts;
+ this.announcements = meta.broadcasts;
this.fetching = false;
});
},
methods: {
next() {
- if (this.i == this.broadcasts.length - 1) {
+ if (this.i == this.announcements.length - 1) {
this.i = 0;
} else {
this.i++;
@@ -126,7 +126,7 @@ root(isDark)
margin 0
font-size 0.95em
font-weight normal
- color #4078c0
+ color isDark ? #539eff : #4078c0
> p
display block