wip
This commit is contained in:
		
							parent
							
								
									55273807d2
								
							
						
					
					
						commit
						69a8e4f4b2
					
				|  | @ -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> | ||||
| 
 | ||||
|  | @ -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> | ||||
|  | @ -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> | ||||
|  | @ -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> | ||||
| 		<div class="body"> | ||||
| 			<a class="name" href={ '/' + _user.username } v-user-preview={ _user.id }>{ _user.name }</a> | ||||
| 			<p class="username">@{ _user.username }</p> | ||||
| 	<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"> | ||||
| 				<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="friend"/> | ||||
| 		</div> | ||||
| 		<mk-follow-button user={ _user }/> | ||||
| 	</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; | ||||
| 		}); | ||||
| 	} | ||||
| }); | ||||
|  |  | |||
|  | @ -14,7 +14,7 @@ | |||
| 		<p>%fa:B twitter%<a :href="`https://twitter.com/${user.twitter.screen_name}`" target="_blank">@{{ user.twitter.screen_name }}</a></p> | ||||
| 	</div> | ||||
| 	<div class="status"> | ||||
| 	  <p class="posts-count">%fa:angle-right%<a>{{ user.posts_count }}</a><b>投稿</b></p> | ||||
| 		<p class="posts-count">%fa:angle-right%<a>{{ user.posts_count }}</a><b>投稿</b></p> | ||||
| 		<p class="following">%fa:angle-right%<a @click="showFollowing">{{ user.following_count }}</a>人を<b>フォロー</b></p> | ||||
| 		<p class="followers">%fa:angle-right%<a @click="showFollowers">{{ user.followers_count }}</a>人の<b>フォロワー</b></p> | ||||
| 	</div> | ||||
|  | @ -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 New Issue