mirror of
https://github.com/paricafe/misskey.git
synced 2024-11-28 08:26:44 -06:00
wip
This commit is contained in:
parent
4705c935ab
commit
0c9a7cf643
8 changed files with 161 additions and 162 deletions
17
.eslintrc
Normal file
17
.eslintrc
Normal file
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"parserOptions": {
|
||||
"parser": "typescript-eslint-parser"
|
||||
},
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:vue/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"vue/require-v-for-key": false,
|
||||
"vue/max-attributes-per-line": false,
|
||||
"vue/html-indent": false,
|
||||
"vue/html-self-closing": false,
|
||||
"vue/no-unused-vars": false,
|
||||
"no-console": 0
|
||||
}
|
||||
}
|
|
@ -99,6 +99,8 @@
|
|||
"diskusage": "0.2.4",
|
||||
"elasticsearch": "14.1.0",
|
||||
"escape-regexp": "0.0.1",
|
||||
"eslint": "^4.18.0",
|
||||
"eslint-plugin-vue": "^4.2.2",
|
||||
"eventemitter3": "3.0.0",
|
||||
"exif-js": "2.3.0",
|
||||
"express": "4.16.2",
|
||||
|
@ -174,6 +176,7 @@
|
|||
"ts-node": "4.1.0",
|
||||
"tslint": "5.9.1",
|
||||
"typescript": "2.7.1",
|
||||
"typescript-eslint-parser": "^13.0.0",
|
||||
"uglify-es": "3.3.9",
|
||||
"uglifyjs-webpack-plugin": "1.1.8",
|
||||
"uuid": "3.2.1",
|
||||
|
|
|
@ -1,23 +0,0 @@
|
|||
<mk-timemachine-home-widget>
|
||||
<mk-calendar-widget design={ data.design } warp={ warp }/>
|
||||
<style lang="stylus" scoped>
|
||||
:scope
|
||||
display block
|
||||
</style>
|
||||
<script lang="typescript">
|
||||
this.data = {
|
||||
design: 0
|
||||
};
|
||||
|
||||
this.mixin('widget');
|
||||
|
||||
this.warp = date => {
|
||||
this.opts.tl.warp(date);
|
||||
};
|
||||
|
||||
this.func = () => {
|
||||
if (++this.data.design == 6) this.data.design = 0;
|
||||
this.save();
|
||||
};
|
||||
</script>
|
||||
</mk-timemachine-home-widget>
|
|
@ -7,16 +7,15 @@
|
|||
</template>
|
||||
|
||||
<div class="calendar">
|
||||
<template v-if="design == 0 || design == 2 || design == 4">
|
||||
<div class="weekday"
|
||||
v-if="design == 0 || design == 2 || design == 4"
|
||||
v-for="(day, i) in Array(7).fill(0)"
|
||||
:key="i"
|
||||
:data-today="year == today.getFullYear() && month == today.getMonth() + 1 && today.getDay() == i"
|
||||
:data-is-donichi="i == 0 || i == 6"
|
||||
>{{ weekdayText[i] }}</div>
|
||||
<div each={ day, i in Array(paddingDays).fill(0) }></div>
|
||||
<div class="day" v-for="(day, i) in Array(days).fill(0)"
|
||||
:key="i"
|
||||
</template>
|
||||
<div v-for="n in paddingDays"></div>
|
||||
<div class="day" v-for="(day, i) in days"
|
||||
:data-today="isToday(i + 1)"
|
||||
:data-selected="isSelected(i + 1)"
|
||||
:data-is-out-of-range="isOutOfRange(i + 1)"
|
||||
|
|
|
@ -37,43 +37,21 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="main">
|
||||
<div class="left">
|
||||
<div ref="left" data-place="left">
|
||||
<template v-for="widget in leftWidgets">
|
||||
<div v-for="place in ['left', 'main', 'right']" :class="place" :ref="place" :data-place="place">
|
||||
<template v-if="place != 'main'">
|
||||
<template v-for="widget in widgets[place]">
|
||||
<div class="customize-container" v-if="customize" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
|
||||
<component :is="'mkw-' + widget.name" :widget="widget" :ref="widget.id"/>
|
||||
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id"/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<component :is="'mkw-' + widget.name" :key="widget.id" :widget="widget" :ref="widget.id"/>
|
||||
<component :is="`mkw-${widget.name}`" :key="widget.id" :widget="widget" :ref="widget.id" @chosen="warp"/>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
<main ref="main">
|
||||
<div class="maintop" ref="maintop" data-place="main" v-if="customize">
|
||||
<template v-for="widget in centerWidgets">
|
||||
<div class="customize-container" v-if="customize" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
|
||||
<component :is="'mkw-' + widget.name" :widget="widget" :ref="widget.id"/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<component :is="'mkw-' + widget.name" :key="widget.id" :widget="widget" :ref="widget.id"/>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
<mk-timeline ref="tl" @loaded="onTlLoaded" v-if="mode == 'timeline'"/>
|
||||
<mk-mentions ref="tl" @loaded="onTlLoaded" v-if="mode == 'mentions'"/>
|
||||
</main>
|
||||
<div class="right">
|
||||
<div ref="right" data-place="right">
|
||||
<template v-for="widget in rightWidgets">
|
||||
<div class="customize-container" v-if="customize" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
|
||||
<component :is="'mkw-' + widget.name" :widget="widget" :ref="widget.id"/>
|
||||
</div>
|
||||
<template v-else>
|
||||
<component :is="'mkw-' + widget.name" :key="widget.id" :widget="widget" :ref="widget.id"/>
|
||||
</template>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
<template v-else>
|
||||
<mk-timeline ref="tl" @loaded="onTlLoaded" v-if="place == 'main' && mode == 'timeline'"/>
|
||||
<mk-mentions @loaded="onTlLoaded" v-if="place == 'main' && mode == 'mentions'"/>
|
||||
</template>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -99,6 +77,85 @@ export default Vue.extend({
|
|||
widgetAdderSelected: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
leftWidgets(): any {
|
||||
return (this as any).os.i.client_settings.home.filter(w => w.place == 'left');
|
||||
},
|
||||
rightWidgets(): any {
|
||||
return (this as any).os.i.client_settings.home.filter(w => w.place == 'right');
|
||||
},
|
||||
widgets(): any {
|
||||
return {
|
||||
left: this.leftWidgets,
|
||||
right: this.rightWidgets,
|
||||
};
|
||||
},
|
||||
leftEl(): Element {
|
||||
return (this.$refs.left as Element[])[0];
|
||||
},
|
||||
rightEl(): Element {
|
||||
return (this.$refs.right as Element[])[0];
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.bakedHomeData = this.bakeHomeData();
|
||||
},
|
||||
mounted() {
|
||||
(this as any).os.i.on('refreshed', this.onMeRefreshed);
|
||||
|
||||
this.home = (this as any).os.i.client_settings.home;
|
||||
|
||||
this.$nextTick(() => {
|
||||
if (!this.customize) {
|
||||
if (this.leftEl.children.length == 0) {
|
||||
this.leftEl.parentNode.removeChild(this.leftEl);
|
||||
}
|
||||
if (this.rightEl.children.length == 0) {
|
||||
this.rightEl.parentNode.removeChild(this.rightEl);
|
||||
}
|
||||
}
|
||||
|
||||
if (this.customize) {
|
||||
(this as any).apis.dialog({
|
||||
title: '%fa:info-circle%カスタマイズのヒント',
|
||||
text: '<p>ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。</p>' +
|
||||
'<p>一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。</p>' +
|
||||
'<p>ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。</p>' +
|
||||
'<p>カスタマイズを終了するには、右上の「完了」をクリックします。</p>',
|
||||
actions: [{
|
||||
text: 'Got it!'
|
||||
}]
|
||||
});
|
||||
|
||||
const sortableOption = {
|
||||
group: 'kyoppie',
|
||||
animation: 150,
|
||||
onMove: evt => {
|
||||
const id = evt.dragged.getAttribute('data-widget-id');
|
||||
this.home.find(tag => tag.id == id).widget.place = evt.to.getAttribute('data-place');
|
||||
},
|
||||
onSort: () => {
|
||||
this.saveHome();
|
||||
}
|
||||
};
|
||||
|
||||
new Sortable(this.leftEl, sortableOption);
|
||||
new Sortable(this.rightEl, sortableOption);
|
||||
new Sortable(this.$refs.trash, Object.assign({}, sortableOption, {
|
||||
onAdd: evt => {
|
||||
const el = evt.item;
|
||||
const id = el.getAttribute('data-widget-id');
|
||||
el.parentNode.removeChild(el);
|
||||
(this as any).os.i.client_settings.home = (this as any).os.i.client_settings.home.filter(w => w.id != id);
|
||||
this.saveHome();
|
||||
}
|
||||
}));
|
||||
}
|
||||
});
|
||||
},
|
||||
beforeDestroy() {
|
||||
(this as any).os.i.off('refreshed', this.onMeRefreshed);
|
||||
},
|
||||
methods: {
|
||||
bakeHomeData() {
|
||||
return JSON.stringify((this as any).os.i.client_settings.home);
|
||||
|
@ -130,102 +187,27 @@ export default Vue.extend({
|
|||
saveHome() {
|
||||
const data = [];
|
||||
|
||||
Array.from((this.$refs.left as Element).children).forEach(el => {
|
||||
Array.from(this.leftEl.children).forEach(el => {
|
||||
const id = el.getAttribute('data-widget-id');
|
||||
const widget = (this as any).os.i.client_settings.home.find(w => w.id == id);
|
||||
widget.place = 'left';
|
||||
data.push(widget);
|
||||
});
|
||||
|
||||
Array.from((this.$refs.right as Element).children).forEach(el => {
|
||||
Array.from(this.rightEl.children).forEach(el => {
|
||||
const id = el.getAttribute('data-widget-id');
|
||||
const widget = (this as any).os.i.client_settings.home.find(w => w.id == id);
|
||||
widget.place = 'right';
|
||||
data.push(widget);
|
||||
});
|
||||
|
||||
Array.from((this.$refs.maintop as Element).children).forEach(el => {
|
||||
const id = el.getAttribute('data-widget-id');
|
||||
const widget = (this as any).os.i.client_settings.home.find(w => w.id == id);
|
||||
widget.place = 'main';
|
||||
data.push(widget);
|
||||
});
|
||||
|
||||
(this as any).api('i/update_home', {
|
||||
home: data
|
||||
});
|
||||
}
|
||||
},
|
||||
computed: {
|
||||
leftWidgets(): any {
|
||||
return (this as any).os.i.client_settings.home.filter(w => w.place == 'left');
|
||||
},
|
||||
centerWidgets(): any {
|
||||
return (this as any).os.i.client_settings.home.filter(w => w.place == 'center');
|
||||
},
|
||||
rightWidgets(): any {
|
||||
return (this as any).os.i.client_settings.home.filter(w => w.place == 'right');
|
||||
warp(date) {
|
||||
(this.$refs.tl as any)[0].warp(date);
|
||||
}
|
||||
},
|
||||
created() {
|
||||
this.bakedHomeData = this.bakeHomeData();
|
||||
},
|
||||
mounted() {
|
||||
(this as any).os.i.on('refreshed', this.onMeRefreshed);
|
||||
|
||||
this.home = (this as any).os.i.client_settings.home;
|
||||
|
||||
if (!this.customize) {
|
||||
if ((this.$refs.left as Element).children.length == 0) {
|
||||
(this.$refs.left as Element).parentNode.removeChild((this.$refs.left as Element));
|
||||
}
|
||||
if ((this.$refs.right as Element).children.length == 0) {
|
||||
(this.$refs.right as Element).parentNode.removeChild((this.$refs.right as Element));
|
||||
}
|
||||
}
|
||||
|
||||
if (this.customize) {
|
||||
/*dialog('%fa:info-circle%カスタマイズのヒント',
|
||||
'<p>ホームのカスタマイズでは、ウィジェットを追加/削除したり、ドラッグ&ドロップして並べ替えたりすることができます。</p>' +
|
||||
'<p>一部のウィジェットは、<strong><strong>右</strong>クリック</strong>することで表示を変更することができます。</p>' +
|
||||
'<p>ウィジェットを削除するには、ヘッダーの<strong>「ゴミ箱」</strong>と書かれたエリアにウィジェットをドラッグ&ドロップします。</p>' +
|
||||
'<p>カスタマイズを終了するには、右上の「完了」をクリックします。</p>',
|
||||
[{
|
||||
text: 'Got it!'
|
||||
}]);*/
|
||||
|
||||
const sortableOption = {
|
||||
group: 'kyoppie',
|
||||
animation: 150,
|
||||
onMove: evt => {
|
||||
const id = evt.dragged.getAttribute('data-widget-id');
|
||||
this.home.find(tag => tag.id == id).update({ place: evt.to.getAttribute('data-place') });
|
||||
},
|
||||
onSort: () => {
|
||||
this.saveHome();
|
||||
}
|
||||
};
|
||||
|
||||
new Sortable(this.$refs.left, sortableOption);
|
||||
new Sortable(this.$refs.right, sortableOption);
|
||||
new Sortable(this.$refs.maintop, sortableOption);
|
||||
new Sortable(this.$refs.trash, Object.assign({}, sortableOption, {
|
||||
onAdd: evt => {
|
||||
const el = evt.item;
|
||||
const id = el.getAttribute('data-widget-id');
|
||||
el.parentNode.removeChild(el);
|
||||
(this as any).os.i.client_settings.home = (this as any).os.i.client_settings.home.filter(w => w.id != id);
|
||||
this.saveHome();
|
||||
}
|
||||
}));
|
||||
}
|
||||
},
|
||||
beforeDestroy() {
|
||||
(this as any).os.i.off('refreshed', this.onMeRefreshed);
|
||||
|
||||
this.home.forEach(widget => {
|
||||
widget.unmount();
|
||||
});
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@ -324,26 +306,16 @@ export default Vue.extend({
|
|||
> *
|
||||
pointer-events none
|
||||
|
||||
> main
|
||||
> .main
|
||||
padding 16px
|
||||
width calc(100% - 275px * 2)
|
||||
|
||||
> *:not(.maintop):not(:last-child)
|
||||
> .maintop > *:not(:last-child)
|
||||
margin-bottom 16px
|
||||
|
||||
> .maintop
|
||||
min-height 64px
|
||||
margin-bottom 16px
|
||||
|
||||
> *:not(main)
|
||||
width 275px
|
||||
padding 16px 0 16px 0
|
||||
|
||||
> *
|
||||
padding 16px 0 16px 0
|
||||
|
||||
> *:not(:last-child)
|
||||
margin-bottom 16px
|
||||
> *:not(:last-child)
|
||||
margin-bottom 16px
|
||||
|
||||
> .left
|
||||
padding-left 16px
|
||||
|
@ -355,7 +327,7 @@ export default Vue.extend({
|
|||
> *:not(main)
|
||||
display none
|
||||
|
||||
> main
|
||||
> .main
|
||||
float none
|
||||
width 100%
|
||||
max-width 700px
|
||||
|
|
|
@ -33,6 +33,7 @@ import driveFolder from './drive-folder.vue';
|
|||
import driveNavFolder from './drive-nav-folder.vue';
|
||||
import postDetail from './post-detail.vue';
|
||||
import settings from './settings.vue';
|
||||
import calendar from './calendar.vue';
|
||||
import wNav from './widgets/nav.vue';
|
||||
import wCalendar from './widgets/calendar.vue';
|
||||
import wPhotoStream from './widgets/photo-stream.vue';
|
||||
|
@ -41,6 +42,7 @@ import wTips from './widgets/tips.vue';
|
|||
import wDonation from './widgets/donation.vue';
|
||||
import wNotifications from './widgets/notifications.vue';
|
||||
import wBroadcast from './widgets/broadcast.vue';
|
||||
import wTimemachine from './widgets/timemachine.vue';
|
||||
|
||||
Vue.component('mk-ui', ui);
|
||||
Vue.component('mk-ui-header', uiHeader);
|
||||
|
@ -75,6 +77,7 @@ Vue.component('mk-drive-folder', driveFolder);
|
|||
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('mkw-nav', wNav);
|
||||
Vue.component('mkw-calendar', wCalendar);
|
||||
Vue.component('mkw-photo-stream', wPhotoStream);
|
||||
|
@ -83,3 +86,4 @@ Vue.component('mkw-tips', wTips);
|
|||
Vue.component('mkw-donation', wDonation);
|
||||
Vue.component('mkw-notifications', wNotifications);
|
||||
Vue.component('mkw-broadcast', wBroadcast);
|
||||
Vue.component('mkw-timemachine', wTimemachine);
|
||||
|
|
|
@ -13,19 +13,14 @@
|
|||
import Vue from 'vue';
|
||||
|
||||
export default Vue.extend({
|
||||
props: {
|
||||
date: {
|
||||
type: Date,
|
||||
required: false
|
||||
}
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
fetching: true,
|
||||
moreFetching: false,
|
||||
posts: [],
|
||||
connection: null,
|
||||
connectionId: null
|
||||
connectionId: null,
|
||||
date: null
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
@ -60,7 +55,7 @@ export default Vue.extend({
|
|||
this.fetching = true;
|
||||
|
||||
(this as any).api('posts/timeline', {
|
||||
until_date: this.date ? (this.date as any).getTime() : undefined
|
||||
until_date: this.date ? this.date.getTime() : undefined
|
||||
}).then(posts => {
|
||||
this.fetching = false;
|
||||
this.posts = posts;
|
||||
|
@ -93,6 +88,10 @@ export default Vue.extend({
|
|||
(this.$refs.timeline as any).focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
warp(date) {
|
||||
this.date = date;
|
||||
this.fetch();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
|
28
src/web/app/desktop/views/components/widgets/timemachine.vue
Normal file
28
src/web/app/desktop/views/components/widgets/timemachine.vue
Normal file
|
@ -0,0 +1,28 @@
|
|||
<template>
|
||||
<div class="mkw-timemachine">
|
||||
<mk-calendar :design="props.design" @chosen="chosen"/>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script lang="ts">
|
||||
import define from '../../../../common/define-widget';
|
||||
export default define({
|
||||
name: 'timemachine',
|
||||
props: {
|
||||
design: 0
|
||||
}
|
||||
}).extend({
|
||||
methods: {
|
||||
chosen(date) {
|
||||
this.$emit('chosen', date);
|
||||
},
|
||||
func() {
|
||||
if (this.props.design == 5) {
|
||||
this.props.design = 0;
|
||||
} else {
|
||||
this.props.design++;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
</script>
|
Loading…
Reference in a new issue