This commit is contained in:
syuilo 2018-02-15 12:36:42 +09:00
parent b47fd29535
commit ca60469262
17 changed files with 716 additions and 647 deletions

View file

@ -2,7 +2,7 @@ import Vue from 'vue';
export default function<T extends object>(data: {
name: string;
props: T;
props?: T;
}) {
return Vue.extend({
props: {
@ -26,7 +26,7 @@ export default function<T extends object>(data: {
},
data() {
return {
props: data.props
props: data.props || {}
};
},
watch: {

View file

@ -0,0 +1,192 @@
<template>
<div class="mkw-calendar"
:data-melt="props.design == 1"
:data-special="special"
>
<div class="calendar" :data-is-holiday="isHoliday">
<p class="month-and-year">
<span class="year">{{ year }}</span>
<span class="month">{{ month }}</span>
</p>
<p class="day">{{ day }}</p>
<p class="week-day">{{ weekDay }}曜日</p>
</div>
<div class="info">
<div>
<p>今日:<b>{{ dayP.toFixed(1) }}%</b></p>
<div class="meter">
<div class="val" :style="{ width: `${dayP}%` }"></div>
</div>
</div>
<div>
<p>今月:<b>{{ monthP.toFixed(1) }}%</b></p>
<div class="meter">
<div class="val" :style="{ width: `${monthP}%` }"></div>
</div>
</div>
<div>
<p>今年:<b>{{ yearP.toFixed(1) }}%</b></p>
<div class="meter">
<div class="val" :style="{ width: `${yearP}%` }"></div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
import define from '../../../define-widget';
export default define({
name: 'calendar',
props: {
design: 0
}
}).extend({
data() {
return {
now: new Date(),
year: null,
month: null,
day: null,
weekDay: null,
yearP: null,
dayP: null,
monthP: null,
isHoliday: null,
special: null,
clock: null
};
},
created() {
this.tick();
this.clock = setInterval(this.tick, 1000);
},
beforeDestroy() {
clearInterval(this.clock);
},
methods: {
func() {
if (this.props.design == 2) {
this.props.design = 0;
} else {
this.props.design++;
}
},
tick() {
const now = new Date();
const nd = now.getDate();
const nm = now.getMonth();
const ny = now.getFullYear();
this.year = ny;
this.month = nm + 1;
this.day = nd;
this.weekDay = ['日', '月', '火', '水', '木', '金', '土'][now.getDay()];
const dayNumer = now.getTime() - new Date(ny, nm, nd).getTime();
const dayDenom = 1000/*ms*/ * 60/*s*/ * 60/*m*/ * 24/*h*/;
const monthNumer = now.getTime() - new Date(ny, nm, 1).getTime();
const monthDenom = new Date(ny, nm + 1, 1).getTime() - new Date(ny, nm, 1).getTime();
const yearNumer = now.getTime() - new Date(ny, 0, 1).getTime();
const yearDenom = new Date(ny + 1, 0, 1).getTime() - new Date(ny, 0, 1).getTime();
this.dayP = dayNumer / dayDenom * 100;
this.monthP = monthNumer / monthDenom * 100;
this.yearP = yearNumer / yearDenom * 100;
this.isHoliday = now.getDay() == 0 || now.getDay() == 6;
this.special =
nm == 0 && nd == 1 ? 'on-new-years-day' :
false;
}
}
});
</script>
<style lang="stylus" scoped>
.mkw-calendar
padding 16px 0
color #777
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
&[data-special='on-new-years-day']
border-color #ef95a0
&[data-melt]
background transparent
border none
&:after
content ""
display block
clear both
> .calendar
float left
width 60%
text-align center
&[data-is-holiday]
> .day
color #ef95a0
> p
margin 0
line-height 18px
font-size 14px
> span
margin 0 4px
> .day
margin 10px 0
line-height 32px
font-size 28px
> .info
display block
float left
width 40%
padding 0 16px 0 0
> div
margin-bottom 8px
&:last-child
margin-bottom 4px
> p
margin 0 0 2px 0
font-size 12px
line-height 18px
color #888
> b
margin-left 2px
> .meter
width 100%
overflow hidden
background #eee
border-radius 8px
> .val
height 4px
background $theme-color
&:nth-child(1)
> .meter > .val
background #f7796c
&:nth-child(2)
> .meter > .val
background #a1de41
&:nth-child(3)
> .meter > .val
background #41ddde
</style>

View file

@ -0,0 +1,45 @@
<template>
<div class="mkw-donation">
<article>
<h1>%fa:heart%%i18n:desktop.tags.mk-donation-home-widget.title%</h1>
<p>
{{ '%i18n:desktop.tags.mk-donation-home-widget.text%'.substr(0, '%i18n:desktop.tags.mk-donation-home-widget.text%'.indexOf('{')) }}
<a href="/syuilo" data-user-preview="@syuilo">@syuilo</a>
{{ '%i18n:desktop.tags.mk-donation-home-widget.text%'.substr('%i18n:desktop.tags.mk-donation-home-widget.text%'.indexOf('}') + 1) }}
</p>
</article>
</div>
</template>
<script lang="ts">
import define from '../../../define-widget';
export default define({
name: 'donation'
});
</script>
<style lang="stylus" scoped>
.mkw-donation
background #fff
border solid 1px #ead8bb
border-radius 6px
> article
padding 20px
> h1
margin 0 0 5px 0
font-size 1em
color #888
> [data-fa]
margin-right 0.25em
> p
display block
z-index 1
margin 0
font-size 0.8em
color #999
</style>

View file

@ -0,0 +1,59 @@
<template>
<div class="mkw-messaging">
<p class="title" v-if="props.design == 0">%fa:comments%%i18n:desktop.tags.mk-messaging-home-widget.title%</p>
<mk-messaging ref="index" compact @navigate="navigate"/>
</div>
</template>
<script lang="ts">
import define from '../../../define-widget';
export default define({
name: 'messaging',
props: {
design: 0
}
}).extend({
methods: {
navigate(user) {
if (this.platform == 'desktop') {
this.wapi_openMessagingRoomWindow(user);
} else {
// TODO: open room page in new tab
}
},
func() {
if (this.props.design == 1) {
this.props.design = 0;
} else {
this.props.design++;
}
}
}
});
</script>
<style lang="stylus" scoped>
.mkw-messaging
overflow hidden
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
> .title
z-index 2
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
> mk-messaging
max-height 250px
overflow auto
</style>

View file

@ -0,0 +1,29 @@
<template>
<div class="mkw-nav">
<mk-nav-links/>
</div>
</template>
<script lang="ts">
import define from '../../../define-widget';
export default define({
name: 'nav'
});
</script>
<style lang="stylus" scoped>
.mkw-nav
padding 16px
font-size 12px
color #aaa
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
a
color #999
i
color #ccc
</style>

View file

@ -0,0 +1,122 @@
<template>
<div class="mkw-photo-stream" :data-melt="props.design == 2">
<p class="title" v-if="props.design == 0">%fa:camera%%i18n:desktop.tags.mk-photo-stream-home-widget.title%</p>
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<div class="stream" v-if="!fetching && images.length > 0">
<div v-for="image in images" :key="image.id" class="img" :style="`background-image: url(${image.url}?thumbnail&size=256)`"></div>
</div>
<p class="empty" v-if="!fetching && images.length == 0">%i18n:desktop.tags.mk-photo-stream-home-widget.no-photos%</p>
</div>
</template>
<script lang="ts">
import define from '../../../define-widget';
export default define({
name: 'photo-stream',
props: {
design: 0
}
}).extend({
data() {
return {
images: [],
fetching: true,
connection: null,
connectionId: null
};
},
mounted() {
this.connection = this.$root.$data.os.stream.getConnection();
this.connectionId = this.$root.$data.os.stream.use();
this.connection.on('drive_file_created', this.onDriveFileCreated);
this.$root.$data.os.api('drive/stream', {
type: 'image/*',
limit: 9
}).then(images => {
this.fetching = false;
this.images = images;
});
},
beforeDestroy() {
this.connection.off('drive_file_created', this.onDriveFileCreated);
this.$root.$data.os.stream.dispose(this.connectionId);
},
methods: {
onStreamDriveFileCreated(file) {
if (/^image\/.+$/.test(file.type)) {
this.images.unshift(file);
if (this.images.length > 9) this.images.pop();
}
},
func() {
if (this.props.design == 2) {
this.props.design = 0;
} else {
this.props.design++;
}
}
}
});
</script>
<style lang="stylus" scoped>
.mkw-photo-stream
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
&[data-melt]
background transparent !important
border none !important
> .stream
padding 0
> .img
border solid 4px transparent
border-radius 8px
> .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
> .stream
display -webkit-flex
display -moz-flex
display -ms-flex
display flex
justify-content center
flex-wrap wrap
padding 8px
> .img
flex 1 1 33%
width 33%
height 80px
background-position center center
background-size cover
border solid 2px transparent
border-radius 4px
> .fetching
> .empty
margin 0
padding 16px
text-align center
color #aaa
> [data-fa]
margin-right 4px
</style>

View file

@ -1,7 +1,7 @@
<template>
<div class="mkw-profile"
data-compact={ data.design == 1 || data.design == 2 }
data-melt={ data.design == 2 }
:data-compact="props.design == 1 || props.design == 2"
:data-melt="props.design == 2"
>
<div class="banner"
style={ I.banner_url ? 'background-image: url(' + I.banner_url + '?thumbnail&size=256)' : '' }

View file

@ -0,0 +1,154 @@
<template>
<div class="mkw-slideshow">
<div @click="choose">
<p v-if="data.folder === undefined">クリックしてフォルダを指定してください</p>
<p v-if="data.folder !== undefined && images.length == 0 && !fetching">このフォルダには画像がありません</p>
<div ref="slideA" class="slide a"></div>
<div ref="slideB" class="slide b"></div>
</div>
<button @click="resize">%fa:expand%</button>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as anime from 'animejs';
import define from '../../../define-widget';
export default define({
name: 'slideshow',
props: {
folder: undefined,
size: 0
}
}).extend({
data() {
return {
images: [],
fetching: true,
clock: null
};
},
mounted() {
Vue.nextTick(() => {
this.applySize();
});
if (this.props.folder !== undefined) {
this.fetch();
}
this.clock = setInterval(this.change, 10000);
},
beforeDestroy() {
clearInterval(this.clock);
},
methods: {
applySize() {
let h;
if (this.props.size == 1) {
h = 250;
} else {
h = 170;
}
this.$el.style.height = `${h}px`;
},
resize() {
if (this.props.size == 1) {
this.props.size = 0;
} else {
this.props.size++;
}
this.applySize();
},
change() {
if (this.images.length == 0) return;
const index = Math.floor(Math.random() * this.images.length);
const img = `url(${ this.images[index].url }?thumbnail&size=1024)`;
(this.$refs.slideB as any).style.backgroundImage = img;
anime({
targets: this.$refs.slideB,
opacity: 1,
duration: 1000,
easing: 'linear',
complete: () => {
(this.$refs.slideA as any).style.backgroundImage = img;
anime({
targets: this.$refs.slideB,
opacity: 0,
duration: 0
});
}
});
},
fetch() {
this.fetching = true;
this.$root.$data.os.api('drive/files', {
folder_id: this.props.folder,
type: 'image/*',
limit: 100
}).then(images => {
this.fetching = false;
this.images = images;
(this.$refs.slideA as any).style.backgroundImage = '';
(this.$refs.slideB as any).style.backgroundImage = '';
this.change();
});
},
choose() {
this.wapi_selectDriveFolder().then(folder => {
this.props.folder = folder ? folder.id : null;
this.fetch();
});
}
}
});
</script>
<style lang="stylus" scoped>
.mkw-slideshow
overflow hidden
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
&:hover > button
display block
> button
position absolute
left 0
bottom 0
display none
padding 4px
font-size 24px
color #fff
text-shadow 0 0 8px #000
> div
width 100%
height 100%
cursor pointer
> *
pointer-events none
> .slide
position absolute
top 0
left 0
width 100%
height 100%
background-size cover
background-position center
&.b
opacity 0
</style>

View file

@ -0,0 +1,109 @@
<template>
<div class="mkw-tips">
<p ref="tip">%fa:R lightbulb%<span v-html="tip"></span></p>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import * as anime from 'animejs';
import define from '../../../define-widget';
const tips = [
'<kbd>t</kbd>でタイムラインにフォーカスできます',
'<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます',
'投稿フォームにはファイルをドラッグ&ドロップできます',
'投稿フォームにクリップボードにある画像データをペーストできます',
'ドライブにファイルをドラッグ&ドロップしてアップロードできます',
'ドライブでファイルをドラッグしてフォルダ移動できます',
'ドライブでフォルダをドラッグしてフォルダ移動できます',
'ホームは設定からカスタマイズできます',
'MisskeyはMIT Licenseです',
'タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます',
'投稿の ... をクリックして、投稿をユーザーページにピン留めできます',
'ドライブの容量は(デフォルトで)1GBです',
'投稿に添付したファイルは全てドライブに保存されます',
'ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます',
'タイムライン上部にもウィジェットを設置できます',
'投稿をダブルクリックすると詳細が見れます',
'「**」でテキストを囲むと**強調表示**されます',
'チャンネルウィジェットを利用すると、よく利用するチャンネルを素早く確認できます',
'いくつかのウィンドウはブラウザの外に切り離すことができます',
'カレンダーウィジェットのパーセンテージは、経過の割合を示しています',
'APIを利用してbotの開発なども行えます',
'MisskeyはLINEを通じてでも利用できます',
'まゆかわいいよまゆ',
'Misskeyは2014年にサービスを開始しました',
'対応ブラウザではMisskeyを開いていなくても通知を受け取れます'
]
export default define({
name: 'tips'
}).extend({
data() {
return {
tip: null,
clock: null
};
},
mounted() {
Vue.nextTick(() => {
this.set();
});
this.clock = setInterval(this.change, 20000);
},
beforeDestroy() {
clearInterval(this.clock);
},
methods: {
set() {
this.tip = tips[Math.floor(Math.random() * tips.length)];
},
change() {
anime({
targets: this.$refs.tip,
opacity: 0,
duration: 500,
easing: 'linear',
complete: this.set
});
setTimeout(() => {
anime({
targets: this.$refs.tip,
opacity: 1,
duration: 500,
easing: 'linear'
});
}, 500);
}
}
});
</script>
<style lang="stylus" scoped>
.mkw-tips
overflow visible !important
> p
display block
margin 0
padding 0 12px
text-align center
font-size 0.7em
color #999
> [data-fa]
margin-right 4px
kbd
display inline
padding 0 6px
margin 0 2px
font-size 1em
font-family inherit
border solid 1px #999
border-radius 2px
</style>

View file

@ -1,167 +0,0 @@
<mk-calendar-home-widget data-melt={ data.design == 1 } data-special={ special }>
<div class="calendar" data-is-holiday={ isHoliday }>
<p class="month-and-year"><span class="year">{ year }年</span><span class="month">{ month }月</span></p>
<p class="day">{ day }日</p>
<p class="week-day">{ weekDay }曜日</p>
</div>
<div class="info">
<div>
<p>今日:<b>{ dayP.toFixed(1) }%</b></p>
<div class="meter">
<div class="val" style={ 'width:' + dayP + '%' }></div>
</div>
</div>
<div>
<p>今月:<b>{ monthP.toFixed(1) }%</b></p>
<div class="meter">
<div class="val" style={ 'width:' + monthP + '%' }></div>
</div>
</div>
<div>
<p>今年:<b>{ yearP.toFixed(1) }%</b></p>
<div class="meter">
<div class="val" style={ 'width:' + yearP + '%' }></div>
</div>
</div>
</div>
<style lang="stylus" scoped>
:scope
display block
padding 16px 0
color #777
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
&[data-special='on-new-years-day']
border-color #ef95a0
&[data-melt]
background transparent
border none
&:after
content ""
display block
clear both
> .calendar
float left
width 60%
text-align center
&[data-is-holiday]
> .day
color #ef95a0
> p
margin 0
line-height 18px
font-size 14px
> span
margin 0 4px
> .day
margin 10px 0
line-height 32px
font-size 28px
> .info
display block
float left
width 40%
padding 0 16px 0 0
> div
margin-bottom 8px
&:last-child
margin-bottom 4px
> p
margin 0 0 2px 0
font-size 12px
line-height 18px
color #888
> b
margin-left 2px
> .meter
width 100%
overflow hidden
background #eee
border-radius 8px
> .val
height 4px
background $theme-color
&:nth-child(1)
> .meter > .val
background #f7796c
&:nth-child(2)
> .meter > .val
background #a1de41
&:nth-child(3)
> .meter > .val
background #41ddde
</style>
<script lang="typescript">
this.data = {
design: 0
};
this.mixin('widget');
this.draw = () => {
const now = new Date();
const nd = now.getDate();
const nm = now.getMonth();
const ny = now.getFullYear();
this.year = ny;
this.month = nm + 1;
this.day = nd;
this.weekDay = ['日', '月', '火', '水', '木', '金', '土'][now.getDay()];
this.dayNumer = now - new Date(ny, nm, nd);
this.dayDenom = 1000/*ms*/ * 60/*s*/ * 60/*m*/ * 24/*h*/;
this.monthNumer = now - new Date(ny, nm, 1);
this.monthDenom = new Date(ny, nm + 1, 1) - new Date(ny, nm, 1);
this.yearNumer = now - new Date(ny, 0, 1);
this.yearDenom = new Date(ny + 1, 0, 1) - new Date(ny, 0, 1);
this.dayP = this.dayNumer / this.dayDenom * 100;
this.monthP = this.monthNumer / this.monthDenom * 100;
this.yearP = this.yearNumer / this.yearDenom * 100;
this.isHoliday = now.getDay() == 0 || now.getDay() == 6;
this.special =
nm == 0 && nd == 1 ? 'on-new-years-day' :
false;
this.update();
};
this.draw();
this.on('mount', () => {
this.clock = setInterval(this.draw, 1000);
});
this.on('unmount', () => {
clearInterval(this.clock);
});
this.func = () => {
if (++this.data.design == 2) this.data.design = 0;
this.save();
};
</script>
</mk-calendar-home-widget>

View file

@ -1,36 +0,0 @@
<mk-donation-home-widget>
<article>
<h1>%fa:heart%%i18n:desktop.tags.mk-donation-home-widget.title%</h1>
<p>{'%i18n:desktop.tags.mk-donation-home-widget.text%'.substr(0, '%i18n:desktop.tags.mk-donation-home-widget.text%'.indexOf('{'))}<a href="/syuilo" data-user-preview="@syuilo">@syuilo</a>{'%i18n:desktop.tags.mk-donation-home-widget.text%'.substr('%i18n:desktop.tags.mk-donation-home-widget.text%'.indexOf('}') + 1)}</p>
</article>
<style lang="stylus" scoped>
:scope
display block
background #fff
border solid 1px #ead8bb
border-radius 6px
> article
padding 20px
> h1
margin 0 0 5px 0
font-size 1em
color #888
> [data-fa]
margin-right 0.25em
> p
display block
z-index 1
margin 0
font-size 0.8em
color #999
</style>
<script lang="typescript">
this.mixin('widget');
this.mixin('user-preview');
</script>
</mk-donation-home-widget>

View file

@ -1,52 +0,0 @@
<mk-messaging-home-widget>
<template v-if="data.design == 0">
<p class="title">%fa:comments%%i18n:desktop.tags.mk-messaging-home-widget.title%</p>
</template>
<mk-messaging ref="index" compact={ true }/>
<style lang="stylus" scoped>
:scope
display block
overflow hidden
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
> .title
z-index 2
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
> mk-messaging
max-height 250px
overflow auto
</style>
<script lang="typescript">
this.data = {
design: 0
};
this.mixin('widget');
this.on('mount', () => {
this.$refs.index.on('navigate-user', user => {
riot.mount(document.body.appendChild(document.createElement('mk-messaging-room-window')), {
user: user
});
});
});
this.func = () => {
if (++this.data.design == 2) this.data.design = 0;
this.save();
};
</script>
</mk-messaging-home-widget>

View file

@ -1,23 +0,0 @@
<mk-nav-home-widget>
<mk-nav-links/>
<style lang="stylus" scoped>
:scope
display block
padding 16px
font-size 12px
color #aaa
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
a
color #999
i
color #ccc
</style>
<script lang="typescript">
this.mixin('widget');
</script>
</mk-nav-home-widget>

View file

@ -1,118 +0,0 @@
<mk-photo-stream-home-widget data-melt={ data.design == 2 }>
<template v-if="data.design == 0">
<p class="title">%fa:camera%%i18n:desktop.tags.mk-photo-stream-home-widget.title%</p>
</template>
<p class="initializing" v-if="initializing">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<div class="stream" v-if="!initializing && images.length > 0">
<template each={ image in images }>
<div class="img" style={ 'background-image: url(' + image.url + '?thumbnail&size=256)' }></div>
</template>
</div>
<p class="empty" v-if="!initializing && images.length == 0">%i18n:desktop.tags.mk-photo-stream-home-widget.no-photos%</p>
<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
> .stream
padding 0
> .img
border solid 4px transparent
border-radius 8px
> .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
> .stream
display -webkit-flex
display -moz-flex
display -ms-flex
display flex
justify-content center
flex-wrap wrap
padding 8px
> .img
flex 1 1 33%
width 33%
height 80px
background-position center center
background-size cover
border solid 2px transparent
border-radius 4px
> .initializing
> .empty
margin 0
padding 16px
text-align center
color #aaa
> [data-fa]
margin-right 4px
</style>
<script lang="typescript">
this.data = {
design: 0
};
this.mixin('widget');
this.mixin('stream');
this.connection = this.stream.getConnection();
this.connectionId = this.stream.use();
this.images = [];
this.initializing = true;
this.on('mount', () => {
this.connection.on('drive_file_created', this.onStreamDriveFileCreated);
this.api('drive/stream', {
type: 'image/*',
limit: 9
}).then(images => {
this.update({
initializing: false,
images: images
});
});
});
this.on('unmount', () => {
this.connection.off('drive_file_created', this.onStreamDriveFileCreated);
this.stream.dispose(this.connectionId);
});
this.onStreamDriveFileCreated = file => {
if (/^image\/.+$/.test(file.type)) {
this.images.unshift(file);
if (this.images.length > 9) this.images.pop();
this.update();
}
};
this.func = () => {
if (++this.data.design == 3) this.data.design = 0;
this.save();
};
</script>
</mk-photo-stream-home-widget>

View file

@ -1,151 +0,0 @@
<mk-slideshow-home-widget>
<div @click="choose">
<p v-if="data.folder === undefined">クリックしてフォルダを指定してください</p>
<p v-if="data.folder !== undefined && images.length == 0 && !fetching">このフォルダには画像がありません</p>
<div ref="slideA" class="slide a"></div>
<div ref="slideB" class="slide b"></div>
</div>
<button @click="resize">%fa:expand%</button>
<style lang="stylus" scoped>
:scope
display block
overflow hidden
background #fff
border solid 1px rgba(0, 0, 0, 0.075)
border-radius 6px
&:hover > button
display block
> button
position absolute
left 0
bottom 0
display none
padding 4px
font-size 24px
color #fff
text-shadow 0 0 8px #000
> div
width 100%
height 100%
cursor pointer
> *
pointer-events none
> .slide
position absolute
top 0
left 0
width 100%
height 100%
background-size cover
background-position center
&.b
opacity 0
</style>
<script lang="typescript">
import * as anime from 'animejs';
this.data = {
folder: undefined,
size: 0
};
this.mixin('widget');
this.images = [];
this.fetching = true;
this.on('mount', () => {
this.applySize();
if (this.data.folder !== undefined) {
this.fetch();
}
this.clock = setInterval(this.change, 10000);
});
this.on('unmount', () => {
clearInterval(this.clock);
});
this.applySize = () => {
let h;
if (this.data.size == 1) {
h = 250;
} else {
h = 170;
}
this.root.style.height = `${h}px`;
};
this.resize = () => {
this.data.size++;
if (this.data.size == 2) this.data.size = 0;
this.applySize();
this.save();
};
this.change = () => {
if (this.images.length == 0) return;
const index = Math.floor(Math.random() * this.images.length);
const img = `url(${ this.images[index].url }?thumbnail&size=1024)`;
this.$refs.slideB.style.backgroundImage = img;
anime({
targets: this.$refs.slideB,
opacity: 1,
duration: 1000,
easing: 'linear',
complete: () => {
this.$refs.slideA.style.backgroundImage = img;
anime({
targets: this.$refs.slideB,
opacity: 0,
duration: 0
});
}
});
};
this.fetch = () => {
this.update({
fetching: true
});
this.api('drive/files', {
folder_id: this.data.folder,
type: 'image/*',
limit: 100
}).then(images => {
this.update({
fetching: false,
images: images
});
this.$refs.slideA.style.backgroundImage = '';
this.$refs.slideB.style.backgroundImage = '';
this.change();
});
};
this.choose = () => {
const i = riot.mount(document.body.appendChild(document.createElement('mk-select-folder-from-drive-window')))[0];
i.one('selected', folder => {
this.data.folder = folder ? folder.id : null;
this.fetch();
this.save();
});
};
</script>
</mk-slideshow-home-widget>

View file

@ -1,94 +0,0 @@
<mk-tips-home-widget>
<p ref="tip">%fa:R lightbulb%<span ref="text"></span></p>
<style lang="stylus" scoped>
:scope
display block
overflow visible !important
> p
display block
margin 0
padding 0 12px
text-align center
font-size 0.7em
color #999
> [data-fa]
margin-right 4px
kbd
display inline
padding 0 6px
margin 0 2px
font-size 1em
font-family inherit
border solid 1px #999
border-radius 2px
</style>
<script lang="typescript">
import * as anime from 'animejs';
this.mixin('widget');
this.tips = [
'<kbd>t</kbd>でタイムラインにフォーカスできます',
'<kbd>p</kbd>または<kbd>n</kbd>で投稿フォームを開きます',
'投稿フォームにはファイルをドラッグ&ドロップできます',
'投稿フォームにクリップボードにある画像データをペーストできます',
'ドライブにファイルをドラッグ&ドロップしてアップロードできます',
'ドライブでファイルをドラッグしてフォルダ移動できます',
'ドライブでフォルダをドラッグしてフォルダ移動できます',
'ホームは設定からカスタマイズできます',
'MisskeyはMIT Licenseです',
'タイムマシンウィジェットを利用すると、簡単に過去のタイムラインに遡れます',
'投稿の ... をクリックして、投稿をユーザーページにピン留めできます',
'ドライブの容量は(デフォルトで)1GBです',
'投稿に添付したファイルは全てドライブに保存されます',
'ホームのカスタマイズ中、ウィジェットを右クリックしてデザインを変更できます',
'タイムライン上部にもウィジェットを設置できます',
'投稿をダブルクリックすると詳細が見れます',
'「**」でテキストを囲むと**強調表示**されます',
'チャンネルウィジェットを利用すると、よく利用するチャンネルを素早く確認できます',
'いくつかのウィンドウはブラウザの外に切り離すことができます',
'カレンダーウィジェットのパーセンテージは、経過の割合を示しています',
'APIを利用してbotの開発なども行えます',
'MisskeyはLINEを通じてでも利用できます',
'まゆかわいいよまゆ',
'Misskeyは2014年にサービスを開始しました',
'対応ブラウザではMisskeyを開いていなくても通知を受け取れます'
]
this.on('mount', () => {
this.set();
this.clock = setInterval(this.change, 20000);
});
this.on('unmount', () => {
clearInterval(this.clock);
});
this.set = () => {
this.$refs.text.innerHTML = this.tips[Math.floor(Math.random() * this.tips.length)];
};
this.change = () => {
anime({
targets: this.$refs.tip,
opacity: 0,
duration: 500,
easing: 'linear',
complete: this.set
});
setTimeout(() => {
anime({
targets: this.$refs.tip,
opacity: 1,
duration: 500,
easing: 'linear'
});
}, 500);
};
</script>
</mk-tips-home-widget>

View file

@ -11,11 +11,11 @@ const isProduction = env === 'production';
export default (version, lang) => {
const plugins = [
consts(lang),
new StringReplacePlugin(),
hoist()
new StringReplacePlugin()
];
if (isProduction) {
plugins.push(hoist());
plugins.push(minify());
}