mirror of
https://github.com/misskey-dev/misskey.git
synced 2024-12-11 08:32:47 +01:00
wip
This commit is contained in:
parent
55273807d2
commit
69a8e4f4b2
40 changed files with 356 additions and 303 deletions
|
@ -28,7 +28,6 @@
|
|||
this.$root.$data.os.api('i/authorized_apps').then(apps => {
|
||||
this.apps = apps;
|
||||
this.fetching = false;
|
||||
this.update();
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
|
|
@ -78,8 +78,8 @@ export default Vue.extend({
|
|||
this.connection.on('read', this.onRead);
|
||||
|
||||
(this as any).api('messaging/history').then(messages => {
|
||||
this.fetching = false;
|
||||
this.messages = messages;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
|
|
|
@ -1,246 +0,0 @@
|
|||
<mk-activity-widget data-melt={ design == 2 }>
|
||||
<template v-if="design == 0">
|
||||
<p class="title">%fa:chart-bar%%i18n:desktop.tags.mk-activity-widget.title%</p>
|
||||
<button @click="toggle" title="%i18n:desktop.tags.mk-activity-widget.toggle%">%fa:sort%</button>
|
||||
</template>
|
||||
<p class="initializing" v-if="initializing">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
|
||||
<mk-activity-widget-calender v-if="!initializing && view == 0" data={ [].concat(activity) }/>
|
||||
<mk-activity-widget-chart v-if="!initializing && view == 1" data={ [].concat(activity) }/>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
background #fff
|
||||
border solid 1px rgba(0, 0, 0, 0.075)
|
||||
border-radius 6px
|
||||
|
||||
&[data-melt]
|
||||
background transparent !important
|
||||
border none !important
|
||||
|
||||
> .title
|
||||
z-index 1
|
||||
margin 0
|
||||
padding 0 16px
|
||||
line-height 42px
|
||||
font-size 0.9em
|
||||
font-weight bold
|
||||
color #888
|
||||
box-shadow 0 1px rgba(0, 0, 0, 0.07)
|
||||
|
||||
> [data-fa]
|
||||
margin-right 4px
|
||||
|
||||
> button
|
||||
position absolute
|
||||
z-index 2
|
||||
top 0
|
||||
right 0
|
||||
padding 0
|
||||
width 42px
|
||||
font-size 0.9em
|
||||
line-height 42px
|
||||
color #ccc
|
||||
|
||||
&:hover
|
||||
color #aaa
|
||||
|
||||
&:active
|
||||
color #999
|
||||
|
||||
> .initializing
|
||||
margin 0
|
||||
padding 16px
|
||||
text-align center
|
||||
color #aaa
|
||||
|
||||
> [data-fa]
|
||||
margin-right 4px
|
||||
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.mixin('api');
|
||||
|
||||
this.design = this.opts.design || 0;
|
||||
this.view = this.opts.view || 0;
|
||||
|
||||
this.user = this.opts.user;
|
||||
this.initializing = true;
|
||||
|
||||
this.on('mount', () => {
|
||||
this.$root.$data.os.api('aggregation/users/activity', {
|
||||
user_id: this.user.id,
|
||||
limit: 20 * 7
|
||||
}).then(activity => {
|
||||
this.update({
|
||||
initializing: false,
|
||||
activity
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this.toggle = () => {
|
||||
this.view++;
|
||||
if (this.view == 2) this.view = 0;
|
||||
this.update();
|
||||
this.$emit('view-changed', this.view);
|
||||
};
|
||||
</script>
|
||||
</mk-activity-widget>
|
||||
|
||||
<mk-activity-widget-calender>
|
||||
<svg viewBox="0 0 21 7" preserveAspectRatio="none">
|
||||
<rect each={ data } class="day"
|
||||
width="1" height="1"
|
||||
riot-x={ x } riot-y={ date.weekday }
|
||||
rx="1" ry="1"
|
||||
fill="transparent">
|
||||
<title>{ date.year }/{ date.month }/{ date.day }<br/>Post: { posts }, Reply: { replies }, Repost: { reposts }</title>
|
||||
</rect>
|
||||
<rect each={ data }
|
||||
riot-width={ v } riot-height={ v }
|
||||
riot-x={ x + ((1 - v) / 2) } riot-y={ date.weekday + ((1 - v) / 2) }
|
||||
rx="1" ry="1"
|
||||
fill={ color }
|
||||
style="pointer-events: none;"/>
|
||||
<rect class="today"
|
||||
width="1" height="1"
|
||||
riot-x={ data[data.length - 1].x } riot-y={ data[data.length - 1].date.weekday }
|
||||
rx="1" ry="1"
|
||||
fill="none"
|
||||
stroke-width="0.1"
|
||||
stroke="#f73520"/>
|
||||
</svg>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
|
||||
> svg
|
||||
display block
|
||||
padding 10px
|
||||
width 100%
|
||||
|
||||
> rect
|
||||
transform-origin center
|
||||
|
||||
&.day
|
||||
&:hover
|
||||
fill rgba(0, 0, 0, 0.05)
|
||||
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.data = this.opts.data;
|
||||
this.data.forEach(d => d.total = d.posts + d.replies + d.reposts);
|
||||
const peak = Math.max.apply(null, this.data.map(d => d.total));
|
||||
|
||||
let x = 0;
|
||||
this.data.reverse().forEach(d => {
|
||||
d.x = x;
|
||||
d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
|
||||
|
||||
d.v = d.total / (peak / 2);
|
||||
if (d.v > 1) d.v = 1;
|
||||
const ch = d.date.weekday == 0 || d.date.weekday == 6 ? 275 : 170;
|
||||
const cs = d.v * 100;
|
||||
const cl = 15 + ((1 - d.v) * 80);
|
||||
d.color = `hsl(${ch}, ${cs}%, ${cl}%)`;
|
||||
|
||||
if (d.date.weekday == 6) x++;
|
||||
});
|
||||
</script>
|
||||
</mk-activity-widget-calender>
|
||||
|
||||
<mk-activity-widget-chart>
|
||||
<svg riot-viewBox="0 0 { viewBoxX } { viewBoxY }" preserveAspectRatio="none" onmousedown={ onMousedown }>
|
||||
<title>Black ... Total<br/>Blue ... Posts<br/>Red ... Replies<br/>Green ... Reposts</title>
|
||||
<polyline
|
||||
riot-points={ pointsPost }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#41ddde"/>
|
||||
<polyline
|
||||
riot-points={ pointsReply }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#f7796c"/>
|
||||
<polyline
|
||||
riot-points={ pointsRepost }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#a1de41"/>
|
||||
<polyline
|
||||
riot-points={ pointsTotal }
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#555"
|
||||
stroke-dasharray="2 2"/>
|
||||
</svg>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
|
||||
> svg
|
||||
display block
|
||||
padding 10px
|
||||
width 100%
|
||||
cursor all-scroll
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.viewBoxX = 140;
|
||||
this.viewBoxY = 60;
|
||||
this.zoom = 1;
|
||||
this.pos = 0;
|
||||
|
||||
this.data = this.opts.data.reverse();
|
||||
this.data.forEach(d => d.total = d.posts + d.replies + d.reposts);
|
||||
const peak = Math.max.apply(null, this.data.map(d => d.total));
|
||||
|
||||
this.on('mount', () => {
|
||||
this.render();
|
||||
});
|
||||
|
||||
this.render = () => {
|
||||
this.update({
|
||||
pointsPost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.posts / peak)) * this.viewBoxY}`).join(' '),
|
||||
pointsReply: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.replies / peak)) * this.viewBoxY}`).join(' '),
|
||||
pointsRepost: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.reposts / peak)) * this.viewBoxY}`).join(' '),
|
||||
pointsTotal: this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ')
|
||||
});
|
||||
};
|
||||
|
||||
this.onMousedown = e => {
|
||||
e.preventDefault();
|
||||
|
||||
const clickX = e.clientX;
|
||||
const clickY = e.clientY;
|
||||
const baseZoom = this.zoom;
|
||||
const basePos = this.pos;
|
||||
|
||||
// 動かした時
|
||||
dragListen(me => {
|
||||
let moveLeft = me.clientX - clickX;
|
||||
let moveTop = me.clientY - clickY;
|
||||
|
||||
this.zoom = baseZoom + (-moveTop / 20);
|
||||
this.pos = basePos + moveLeft;
|
||||
if (this.zoom < 1) this.zoom = 1;
|
||||
if (this.pos > 0) this.pos = 0;
|
||||
if (this.pos < -(((this.data.length - 1) * this.zoom) - this.viewBoxX)) this.pos = -(((this.data.length - 1) * this.zoom) - this.viewBoxX);
|
||||
|
||||
this.render();
|
||||
});
|
||||
};
|
||||
|
||||
function dragListen(fn) {
|
||||
window.addEventListener('mousemove', fn);
|
||||
window.addEventListener('mouseleave', dragClear.bind(null, fn));
|
||||
window.addEventListener('mouseup', dragClear.bind(null, fn));
|
||||
}
|
||||
|
||||
function dragClear(fn) {
|
||||
window.removeEventListener('mousemove', fn);
|
||||
window.removeEventListener('mouseleave', dragClear);
|
||||
window.removeEventListener('mouseup', dragClear);
|
||||
}
|
||||
</script>
|
||||
</mk-activity-widget-chart>
|
||||
|
66
src/web/app/desktop/views/components/activity.calendar.vue
Normal file
66
src/web/app/desktop/views/components/activity.calendar.vue
Normal file
|
@ -0,0 +1,66 @@
|
|||
<template>
|
||||
<svg viewBox="0 0 21 7" preserveAspectRatio="none">
|
||||
<rect v-for="record in data" class="day"
|
||||
width="1" height="1"
|
||||
:x="record.x" :y="record.date.weekday"
|
||||
rx="1" ry="1"
|
||||
fill="transparent">
|
||||
<title>{{ record.date.year }}/{{ record.date.month }}/{{ record.date.day }}</title>
|
||||
</rect>
|
||||
<rect v-for="record in data" class="day"
|
||||
:width="record.v" :height="record.v"
|
||||
:x="record.x + ((1 - record.v) / 2)" :y="record.date.weekday + ((1 - record.v) / 2)"
|
||||
rx="1" ry="1"
|
||||
:fill="record.color"
|
||||
style="pointer-events: none;"/>
|
||||
<rect class="today"
|
||||
width="1" height="1"
|
||||
:x="data[data.length - 1].x" :y="data[data.length - 1].date.weekday"
|
||||
rx="1" ry="1"
|
||||
fill="none"
|
||||
stroke-width="0.1"
|
||||
stroke="#f73520"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['data'],
|
||||
created() {
|
||||
this.data.forEach(d => d.total = d.posts + d.replies + d.reposts);
|
||||
const peak = Math.max.apply(null, this.data.map(d => d.total));
|
||||
|
||||
let x = 0;
|
||||
this.data.reverse().forEach(d => {
|
||||
d.x = x;
|
||||
d.date.weekday = (new Date(d.date.year, d.date.month - 1, d.date.day)).getDay();
|
||||
|
||||
d.v = d.total / (peak / 2);
|
||||
if (d.v > 1) d.v = 1;
|
||||
const ch = d.date.weekday == 0 || d.date.weekday == 6 ? 275 : 170;
|
||||
const cs = d.v * 100;
|
||||
const cl = 15 + ((1 - d.v) * 80);
|
||||
d.color = `hsl(${ch}, ${cs}%, ${cl}%)`;
|
||||
|
||||
if (d.date.weekday == 6) x++;
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
svg
|
||||
display block
|
||||
padding 10px
|
||||
width 100%
|
||||
|
||||
> rect
|
||||
transform-origin center
|
||||
|
||||
&.day
|
||||
&:hover
|
||||
fill rgba(0, 0, 0, 0.05)
|
||||
|
||||
</style>
|
101
src/web/app/desktop/views/components/activity.chart.vue
Normal file
101
src/web/app/desktop/views/components/activity.chart.vue
Normal file
|
@ -0,0 +1,101 @@
|
|||
<template>
|
||||
<svg :viewBox="`0 0 ${ viewBoxX } ${ viewBoxY }`" preserveAspectRatio="none" @mousedown.prevent="onMousedown">
|
||||
<title>Black ... Total<br/>Blue ... Posts<br/>Red ... Replies<br/>Green ... Reposts</title>
|
||||
<polyline
|
||||
:points="pointsPost"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#41ddde"/>
|
||||
<polyline
|
||||
:points="pointsReply"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#f7796c"/>
|
||||
<polyline
|
||||
:points="pointsRepost"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#a1de41"/>
|
||||
<polyline
|
||||
:points="pointsTotal"
|
||||
fill="none"
|
||||
stroke-width="1"
|
||||
stroke="#555"
|
||||
stroke-dasharray="2 2"/>
|
||||
</svg>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
|
||||
function dragListen(fn) {
|
||||
window.addEventListener('mousemove', fn);
|
||||
window.addEventListener('mouseleave', dragClear.bind(null, fn));
|
||||
window.addEventListener('mouseup', dragClear.bind(null, fn));
|
||||
}
|
||||
|
||||
function dragClear(fn) {
|
||||
window.removeEventListener('mousemove', fn);
|
||||
window.removeEventListener('mouseleave', dragClear);
|
||||
window.removeEventListener('mouseup', dragClear);
|
||||
}
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['data'],
|
||||
data() {
|
||||
return {
|
||||
viewBoxX: 140,
|
||||
viewBoxY: 60,
|
||||
zoom: 1,
|
||||
pos: 0,
|
||||
pointsPost: null,
|
||||
pointsReply: null,
|
||||
pointsRepost: null,
|
||||
pointsTotal: null
|
||||
};
|
||||
},
|
||||
created() {
|
||||
this.data.reverse();
|
||||
this.data.forEach(d => d.total = d.posts + d.replies + d.reposts);
|
||||
this.render();
|
||||
},
|
||||
methods: {
|
||||
render() {
|
||||
const peak = Math.max.apply(null, this.data.map(d => d.total));
|
||||
this.pointsPost = this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.posts / peak)) * this.viewBoxY}`).join(' ');
|
||||
this.pointsReply = this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.replies / peak)) * this.viewBoxY}`).join(' ');
|
||||
this.pointsRepost = this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.reposts / peak)) * this.viewBoxY}`).join(' ');
|
||||
this.pointsTotal = this.data.map((d, i) => `${(i * this.zoom) + this.pos},${(1 - (d.total / peak)) * this.viewBoxY}`).join(' ');
|
||||
},
|
||||
onMousedown(e) {
|
||||
const clickX = e.clientX;
|
||||
const clickY = e.clientY;
|
||||
const baseZoom = this.zoom;
|
||||
const basePos = this.pos;
|
||||
|
||||
// 動かした時
|
||||
dragListen(me => {
|
||||
let moveLeft = me.clientX - clickX;
|
||||
let moveTop = me.clientY - clickY;
|
||||
|
||||
this.zoom = baseZoom + (-moveTop / 20);
|
||||
this.pos = basePos + moveLeft;
|
||||
if (this.zoom < 1) this.zoom = 1;
|
||||
if (this.pos > 0) this.pos = 0;
|
||||
if (this.pos < -(((this.data.length - 1) * this.zoom) - this.viewBoxX)) this.pos = -(((this.data.length - 1) * this.zoom) - this.viewBoxX);
|
||||
|
||||
this.render();
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
svg
|
||||
display block
|
||||
padding 10px
|
||||
width 100%
|
||||
cursor all-scroll
|
||||
|
||||
</style>
|
116
src/web/app/desktop/views/components/activity.vue
Normal file
116
src/web/app/desktop/views/components/activity.vue
Normal file
|
@ -0,0 +1,116 @@
|
|||
<template>
|
||||
<div class="mk-activity">
|
||||
<template v-if="design == 0">
|
||||
<p class="title">%fa:chart-bar%%i18n:desktop.tags.mk-activity-widget.title%</p>
|
||||
<button @click="toggle" title="%i18n:desktop.tags.mk-activity-widget.toggle%">%fa:sort%</button>
|
||||
</template>
|
||||
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
|
||||
<template v-else>
|
||||
<mk-activity-widget-calender v-show="view == 0" :data="[].concat(activity)"/>
|
||||
<mk-activity-widget-chart v-show="view == 1" :data="[].concat(activity)"/>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import Calendar from './activity.calendar.vue';
|
||||
import Chart from './activity.chart.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
'mk-activity-widget-calender': Calendar,
|
||||
'mk-activity-widget-chart': Chart
|
||||
},
|
||||
props: {
|
||||
design: {
|
||||
default: 0
|
||||
},
|
||||
initView: {
|
||||
default: 0
|
||||
},
|
||||
user: {
|
||||
type: Object,
|
||||
required: true
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fetching: true,
|
||||
activity: null,
|
||||
view: this.initView
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
(this as any).api('aggregation/users/activity', {
|
||||
user_id: this.user.id,
|
||||
limit: 20 * 7
|
||||
}).then(activity => {
|
||||
this.activity = activity;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
toggle() {
|
||||
if (this.view == 1) {
|
||||
this.view = 0;
|
||||
this.$emit('viewChanged', this.view);
|
||||
} else {
|
||||
this.view++;
|
||||
this.$emit('viewChanged', this.view);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
||||
<style lang="stylus" scoped>
|
||||
.mk-activity
|
||||
background #fff
|
||||
border solid 1px rgba(0, 0, 0, 0.075)
|
||||
border-radius 6px
|
||||
|
||||
&[data-melt]
|
||||
background transparent !important
|
||||
border none !important
|
||||
|
||||
> .title
|
||||
z-index 1
|
||||
margin 0
|
||||
padding 0 16px
|
||||
line-height 42px
|
||||
font-size 0.9em
|
||||
font-weight bold
|
||||
color #888
|
||||
box-shadow 0 1px rgba(0, 0, 0, 0.07)
|
||||
|
||||
> [data-fa]
|
||||
margin-right 4px
|
||||
|
||||
> button
|
||||
position absolute
|
||||
z-index 2
|
||||
top 0
|
||||
right 0
|
||||
padding 0
|
||||
width 42px
|
||||
font-size 0.9em
|
||||
line-height 42px
|
||||
color #ccc
|
||||
|
||||
&:hover
|
||||
color #aaa
|
||||
|
||||
&:active
|
||||
color #999
|
||||
|
||||
> .fetching
|
||||
margin 0
|
||||
padding 16px
|
||||
text-align center
|
||||
color #aaa
|
||||
|
||||
> [data-fa]
|
||||
margin-right 4px
|
||||
|
||||
</style>
|
|
@ -47,7 +47,7 @@ export default Vue.extend({
|
|||
default: 0
|
||||
},
|
||||
start: {
|
||||
type: Object,
|
||||
type: Date,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
|
@ -94,7 +94,7 @@ export default Vue.extend({
|
|||
isOutOfRange(day) {
|
||||
const test = (new Date(this.year, this.month - 1, day)).getTime();
|
||||
return test > this.today.getTime() ||
|
||||
(this.start ? test < this.start.getTime() : false);
|
||||
(this.start ? test < (this.start as any).getTime() : false);
|
||||
},
|
||||
|
||||
isDonichi(day) {
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<mk-window width='400px' height='550px' @closed="$destroy">
|
||||
<mk-window width="400px" height="550px" @closed="$destroy">
|
||||
<span slot="header" :class="$style.header">
|
||||
<img :src="`${user.avatar_url}?thumbnail&size=64`" alt=""/>{{ user.name }}のフォロワー
|
||||
</span>
|
||||
<mk-user-followers :user="user"/>
|
||||
<mk-followers-list :user="user"/>
|
||||
</mk-window>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
<template>
|
||||
<mk-window width='400px' height='550px' @closed="$destroy">
|
||||
<mk-window width="400px" height="550px" @closed="$destroy">
|
||||
<span slot="header" :class="$style.header">
|
||||
<img :src="`${user.avatar_url}?thumbnail&size=64`" alt=""/>{{ user.name }}のフォロー
|
||||
</span>
|
||||
<mk-user-following :user="user"/>
|
||||
<mk-following-list :user="user"/>
|
||||
</mk-window>
|
||||
</template>
|
||||
|
||||
|
|
|
@ -43,8 +43,8 @@ export default Vue.extend({
|
|||
limit: this.limit,
|
||||
offset: this.limit * this.page
|
||||
}).then(users => {
|
||||
this.fetching = false;
|
||||
this.users = users;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
refresh() {
|
||||
|
|
|
@ -34,6 +34,7 @@ import driveNavFolder from './drive-nav-folder.vue';
|
|||
import postDetail from './post-detail.vue';
|
||||
import settings from './settings.vue';
|
||||
import calendar from './calendar.vue';
|
||||
import activity from './activity.vue';
|
||||
import wNav from './widgets/nav.vue';
|
||||
import wCalendar from './widgets/calendar.vue';
|
||||
import wPhotoStream from './widgets/photo-stream.vue';
|
||||
|
@ -78,6 +79,7 @@ Vue.component('mk-drive-nav-folder', driveNavFolder);
|
|||
Vue.component('mk-post-detail', postDetail);
|
||||
Vue.component('mk-settings', settings);
|
||||
Vue.component('mk-calendar', calendar);
|
||||
Vue.component('mk-activity', activity);
|
||||
Vue.component('mkw-nav', wNav);
|
||||
Vue.component('mkw-calendar', wCalendar);
|
||||
Vue.component('mkw-photo-stream', wPhotoStream);
|
||||
|
|
|
@ -23,8 +23,8 @@ export default Vue.extend({
|
|||
},
|
||||
mounted() {
|
||||
(this as any).api('mute/list').then(x => {
|
||||
this.fetching = false;
|
||||
this.users = x.users;
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
class="read-more"
|
||||
v-if="p.reply && p.reply.reply_id && context == null"
|
||||
title="会話をもっと読み込む"
|
||||
@click="loadContext"
|
||||
@click="fetchContext"
|
||||
:disabled="contextFetching"
|
||||
>
|
||||
<template v-if="!contextFetching">%fa:ellipsis-v%</template>
|
||||
|
|
|
@ -57,8 +57,8 @@ export default Vue.extend({
|
|||
(this as any).api('posts/timeline', {
|
||||
until_date: this.date ? this.date.getTime() : undefined
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
this.posts = posts;
|
||||
this.fetching = false;
|
||||
if (cb) cb();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -45,9 +45,9 @@ export default Vue.extend({
|
|||
_fetch(cb) {
|
||||
this.fetching = true;
|
||||
this.fetch(this.mode == 'iknow', this.limit, null, obj => {
|
||||
this.fetching = false;
|
||||
this.users = obj.users;
|
||||
this.next = obj.next;
|
||||
this.fetching = false;
|
||||
if (cb) cb();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -46,8 +46,8 @@ export default define({
|
|||
}
|
||||
});
|
||||
}
|
||||
this.fetching = false;
|
||||
this.broadcasts = broadcasts;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
methods: {
|
||||
|
|
|
@ -35,8 +35,8 @@ export default define({
|
|||
type: 'image/*',
|
||||
limit: 9
|
||||
}).then(images => {
|
||||
this.fetching = false;
|
||||
this.images = images;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
|
|
|
@ -93,8 +93,8 @@ export default define({
|
|||
type: 'image/*',
|
||||
limit: 100
|
||||
}).then(images => {
|
||||
this.fetching = false;
|
||||
this.images = images;
|
||||
this.fetching = false;
|
||||
(this.$refs.slideA as any).style.backgroundImage = '';
|
||||
(this.$refs.slideB as any).style.backgroundImage = '';
|
||||
this.change();
|
||||
|
|
|
@ -24,8 +24,8 @@ export default Vue.extend({
|
|||
(this as any).api('users/show', {
|
||||
username: this.username
|
||||
}).then(user => {
|
||||
this.fetching = false;
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
|
||||
document.title = 'メッセージ: ' + this.user.name;
|
||||
|
||||
|
|
|
@ -26,8 +26,8 @@ export default Vue.extend({
|
|||
(this as any).api('posts/show', {
|
||||
post_id: this.postId
|
||||
}).then(post => {
|
||||
this.fetching = false;
|
||||
this.post = post;
|
||||
this.fetching = false;
|
||||
|
||||
Progress.done();
|
||||
});
|
||||
|
|
|
@ -45,8 +45,8 @@ export default Vue.extend({
|
|||
window.addEventListener('scroll', this.onScroll);
|
||||
|
||||
(this as any).api('posts/search', parse(this.query)).then(posts => {
|
||||
this.fetching = false;
|
||||
this.posts = posts;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
|
|
|
@ -27,8 +27,8 @@ export default Vue.extend({
|
|||
iknow: true,
|
||||
limit: 16
|
||||
}).then(x => {
|
||||
this.fetching = false;
|
||||
this.users = x.users;
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -2,16 +2,18 @@
|
|||
<div class="mk-user-friends">
|
||||
<p class="title">%fa:users%%i18n:desktop.tags.mk-user.frequently-replied-users.title%</p>
|
||||
<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.frequently-replied-users.loading%<mk-ellipsis/></p>
|
||||
<div class="user" v-if="!fetching && users.length != 0" each={ _user in users }>
|
||||
<a class="avatar-anchor" href={ '/' + _user.username }>
|
||||
<img class="avatar" src={ _user.avatar_url + '?thumbnail&size=42' } alt="" v-user-preview={ _user.id }/>
|
||||
</a>
|
||||
<template v-if="!fetching && users.length != 0">
|
||||
<div class="user" v-for="friend in users">
|
||||
<router-link class="avatar-anchor" to="`/${friend.username}`">
|
||||
<img class="avatar" :src="`${friend.avatar_url}?thumbnail&size=42`" alt="" v-user-preview="friend.id"/>
|
||||
</router-link>
|
||||
<div class="body">
|
||||
<a class="name" href={ '/' + _user.username } v-user-preview={ _user.id }>{ _user.name }</a>
|
||||
<p class="username">@{ _user.username }</p>
|
||||
<router-link class="name" to="`/${friend.username}`" v-user-preview="friend.id">{{ friend.name }}</router-link>
|
||||
<p class="username">@{{ friend.username }}</p>
|
||||
</div>
|
||||
<mk-follow-button user={ _user }/>
|
||||
<mk-follow-button :user="friend"/>
|
||||
</div>
|
||||
</template>
|
||||
<p class="empty" v-if="!fetching && users.length == 0">%i18n:desktop.tags.mk-user.frequently-replied-users.no-users%</p>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -31,8 +33,8 @@ export default Vue.extend({
|
|||
user_id: this.user.id,
|
||||
limit: 4
|
||||
}).then(docs => {
|
||||
this.fetching = false;
|
||||
this.users = docs.map(doc => doc.user);
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -14,8 +14,8 @@
|
|||
</main>
|
||||
<div>
|
||||
<div ref="right">
|
||||
<mk-calendar-widget @warp="warp" :start="new Date(user.created_at)"/>
|
||||
<mk-activity-widget :user="user"/>
|
||||
<mk-calendar @chosen="warp" :start="new Date(user.created_at)"/>
|
||||
<mk-activity :user="user"/>
|
||||
<mk-user-friends :user="user"/>
|
||||
<div class="nav"><mk-nav/></div>
|
||||
</div>
|
||||
|
@ -25,7 +25,20 @@
|
|||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
import MkUserTimeline from './user-timeline.vue';
|
||||
import MkUserProfile from './user-profile.vue';
|
||||
import MkUserPhotos from './user-photos.vue';
|
||||
import MkUserFollowersYouKnow from './user-followers-you-know.vue';
|
||||
import MkUserFriends from './user-friends.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
components: {
|
||||
'mk-user-timeline': MkUserTimeline,
|
||||
'mk-user-profile': MkUserProfile,
|
||||
'mk-user-photos': MkUserPhotos,
|
||||
'mk-user-followers-you-know': MkUserFollowersYouKnow,
|
||||
'mk-user-friends': MkUserFriends
|
||||
},
|
||||
props: ['user'],
|
||||
methods: {
|
||||
warp(date) {
|
||||
|
|
|
@ -3,8 +3,7 @@
|
|||
<p class="title">%fa:camera%%i18n:desktop.tags.mk-user.photos.title%</p>
|
||||
<p class="initializing" v-if="fetching">%fa:spinner .pulse .fw%%i18n:desktop.tags.mk-user.photos.loading%<mk-ellipsis/></p>
|
||||
<div class="stream" v-if="!fetching && images.length > 0">
|
||||
<div v-for="image in images" :key="image.id"
|
||||
class="img"
|
||||
<div v-for="image in images" class="img"
|
||||
:style="`background-image: url(${image.url}?thumbnail&size=256)`"
|
||||
></div>
|
||||
</div>
|
||||
|
@ -28,12 +27,12 @@ export default Vue.extend({
|
|||
with_media: true,
|
||||
limit: 9
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
posts.forEach(post => {
|
||||
post.media.forEach(media => {
|
||||
if (this.images.length < 9) this.images.push(media);
|
||||
});
|
||||
});
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -23,7 +23,9 @@
|
|||
|
||||
<script lang="ts">
|
||||
import Vue from 'vue';
|
||||
const age = require('s-age');
|
||||
import age from 's-age';
|
||||
import MkFollowingWindow from '../../components/following-window.vue';
|
||||
import MkFollowersWindow from '../../components/followers-window.vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: ['user'],
|
||||
|
@ -34,8 +36,7 @@ export default Vue.extend({
|
|||
},
|
||||
methods: {
|
||||
showFollowing() {
|
||||
document.body.appendChild(new MkUserFollowingWindow({
|
||||
|
||||
document.body.appendChild(new MkFollowingWindow({
|
||||
propsData: {
|
||||
user: this.user
|
||||
}
|
||||
|
@ -43,8 +44,7 @@ export default Vue.extend({
|
|||
},
|
||||
|
||||
showFollowers() {
|
||||
document.body.appendChild(new MkUserFollowersWindow({
|
||||
|
||||
document.body.appendChild(new MkFollowersWindow({
|
||||
propsData: {
|
||||
user: this.user
|
||||
}
|
||||
|
@ -56,7 +56,7 @@ export default Vue.extend({
|
|||
user_id: this.user.id
|
||||
}).then(() => {
|
||||
this.user.is_muted = true;
|
||||
}, e => {
|
||||
}, () => {
|
||||
alert('error');
|
||||
});
|
||||
},
|
||||
|
@ -66,7 +66,7 @@ export default Vue.extend({
|
|||
user_id: this.user.id
|
||||
}).then(() => {
|
||||
this.user.is_muted = false;
|
||||
}, e => {
|
||||
}, () => {
|
||||
alert('error');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -65,8 +65,8 @@ export default Vue.extend({
|
|||
until_date: this.date ? this.date.getTime() : undefined,
|
||||
with_replies: this.mode == 'with-replies'
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
this.posts = posts;
|
||||
this.fetching = false;
|
||||
if (cb) cb();
|
||||
});
|
||||
},
|
|
@ -35,8 +35,8 @@ export default Vue.extend({
|
|||
(this as any).api('users/show', {
|
||||
username: this.$route.params.user
|
||||
}).then(user => {
|
||||
this.fetching = false;
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
Progress.done();
|
||||
document.title = user.name + ' | Misskey';
|
||||
});
|
||||
|
|
|
@ -351,13 +351,14 @@ export default Vue.extend({
|
|||
(this as any).api('drive/files/show', {
|
||||
file_id: file
|
||||
}).then(file => {
|
||||
this.fetching = false;
|
||||
this.file = file;
|
||||
this.folder = null;
|
||||
this.hierarchyFolders = [];
|
||||
|
||||
if (file.folder) this.dive(file.folder);
|
||||
|
||||
this.fetching = false;
|
||||
|
||||
this.$emit('open-file', this.file, silent);
|
||||
});
|
||||
},
|
||||
|
|
|
@ -36,8 +36,8 @@ export default Vue.extend({
|
|||
limit: this.limit,
|
||||
offset: this.limit * this.page
|
||||
}).then(users => {
|
||||
this.fetching = false;
|
||||
this.users = users;
|
||||
this.fetching = false;
|
||||
});
|
||||
},
|
||||
refresh() {
|
||||
|
|
|
@ -63,8 +63,8 @@ export default Vue.extend({
|
|||
(this as any).api('posts/timeline', {
|
||||
until_date: this.date ? (this.date as any).getTime() : undefined
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
this.posts = posts;
|
||||
this.fetching = false;
|
||||
if (cb) cb();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -31,8 +31,8 @@ export default Vue.extend({
|
|||
user_id: this.user.id,
|
||||
with_media: this.withMedia
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
this.posts = posts;
|
||||
this.fetching = false;
|
||||
this.$emit('loaded');
|
||||
});
|
||||
}
|
||||
|
|
|
@ -41,9 +41,9 @@ export default Vue.extend({
|
|||
_fetch(cb) {
|
||||
this.fetching = true;
|
||||
this.fetch(this.mode == 'iknow', this.limit, null, obj => {
|
||||
this.fetching = false;
|
||||
this.users = obj.users;
|
||||
this.next = obj.next;
|
||||
this.fetching = false;
|
||||
if (cb) cb();
|
||||
});
|
||||
},
|
||||
|
|
|
@ -26,8 +26,8 @@ export default Vue.extend({
|
|||
(this as any).api('users/show', {
|
||||
username: this.username
|
||||
}).then(user => {
|
||||
this.fetching = false;
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
|
||||
document.title = '%i18n:mobile.tags.mk-user-followers-page.followers-of%'.replace('{}', user.name) + ' | Misskey';
|
||||
document.documentElement.style.background = '#313a42';
|
||||
|
|
|
@ -26,8 +26,8 @@ export default Vue.extend({
|
|||
(this as any).api('users/show', {
|
||||
username: this.username
|
||||
}).then(user => {
|
||||
this.fetching = false;
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
|
||||
document.title = '%i18n:mobile.tags.mk-user-followers-page.followers-of%'.replace('{}', user.name) + ' | Misskey';
|
||||
document.documentElement.style.background = '#313a42';
|
||||
|
|
|
@ -32,8 +32,8 @@ export default Vue.extend({
|
|||
(this as any).api('posts/show', {
|
||||
post_id: this.postId
|
||||
}).then(post => {
|
||||
this.fetching = false;
|
||||
this.post = post;
|
||||
this.fetching = false;
|
||||
|
||||
Progress.done();
|
||||
});
|
||||
|
|
|
@ -88,8 +88,8 @@ export default Vue.extend({
|
|||
(this as any).api('users/show', {
|
||||
username: this.username
|
||||
}).then(user => {
|
||||
this.fetching = false;
|
||||
this.user = user;
|
||||
this.fetching = false;
|
||||
|
||||
Progress.done();
|
||||
document.title = user.name + ' | Misskey';
|
||||
|
|
|
@ -22,8 +22,8 @@ export default Vue.extend({
|
|||
(this as any).api('users/get_frequently_replied_users', {
|
||||
user_id: this.user.id
|
||||
}).then(res => {
|
||||
this.fetching = false;
|
||||
this.users = res.map(x => x.user);
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -28,7 +28,6 @@ export default Vue.extend({
|
|||
with_media: true,
|
||||
limit: 6
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
posts.forEach(post => {
|
||||
post.media.forEach(media => {
|
||||
if (this.images.length < 9) this.images.push({
|
||||
|
@ -37,6 +36,7 @@ export default Vue.extend({
|
|||
});
|
||||
});
|
||||
});
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
|
@ -22,8 +22,8 @@ export default Vue.extend({
|
|||
(this as any).api('users/posts', {
|
||||
user_id: this.user.id
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
this.posts = posts;
|
||||
this.fetching = false;
|
||||
});
|
||||
}
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue