mirror of
https://git.joinsharkey.org/Sharkey/Sharkey.git
synced 2024-12-23 19:33:09 +02:00
wip
This commit is contained in:
parent
b47fd29535
commit
ca60469262
17 changed files with 716 additions and 647 deletions
|
@ -2,7 +2,7 @@ import Vue from 'vue';
|
||||||
|
|
||||||
export default function<T extends object>(data: {
|
export default function<T extends object>(data: {
|
||||||
name: string;
|
name: string;
|
||||||
props: T;
|
props?: T;
|
||||||
}) {
|
}) {
|
||||||
return Vue.extend({
|
return Vue.extend({
|
||||||
props: {
|
props: {
|
||||||
|
@ -26,7 +26,7 @@ export default function<T extends object>(data: {
|
||||||
},
|
},
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
props: data.props
|
props: data.props || {}
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
watch: {
|
watch: {
|
||||||
|
|
192
src/web/app/common/views/components/widgets/calendar.vue
Normal file
192
src/web/app/common/views/components/widgets/calendar.vue
Normal 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>
|
45
src/web/app/common/views/components/widgets/donation.vue
Normal file
45
src/web/app/common/views/components/widgets/donation.vue
Normal 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>
|
59
src/web/app/common/views/components/widgets/messaging.vue
Normal file
59
src/web/app/common/views/components/widgets/messaging.vue
Normal 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>
|
29
src/web/app/common/views/components/widgets/nav.vue
Normal file
29
src/web/app/common/views/components/widgets/nav.vue
Normal 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>
|
122
src/web/app/common/views/components/widgets/photo-stream.vue
Normal file
122
src/web/app/common/views/components/widgets/photo-stream.vue
Normal 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>
|
|
@ -1,7 +1,7 @@
|
||||||
<template>
|
<template>
|
||||||
<div class="mkw-profile"
|
<div class="mkw-profile"
|
||||||
data-compact={ data.design == 1 || data.design == 2 }
|
:data-compact="props.design == 1 || props.design == 2"
|
||||||
data-melt={ data.design == 2 }
|
:data-melt="props.design == 2"
|
||||||
>
|
>
|
||||||
<div class="banner"
|
<div class="banner"
|
||||||
style={ I.banner_url ? 'background-image: url(' + I.banner_url + '?thumbnail&size=256)' : '' }
|
style={ I.banner_url ? 'background-image: url(' + I.banner_url + '?thumbnail&size=256)' : '' }
|
||||||
|
|
154
src/web/app/common/views/components/widgets/slideshow.vue
Normal file
154
src/web/app/common/views/components/widgets/slideshow.vue
Normal 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>
|
109
src/web/app/common/views/components/widgets/tips.vue
Normal file
109
src/web/app/common/views/components/widgets/tips.vue
Normal 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>
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -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>
|
|
|
@ -11,11 +11,11 @@ const isProduction = env === 'production';
|
||||||
export default (version, lang) => {
|
export default (version, lang) => {
|
||||||
const plugins = [
|
const plugins = [
|
||||||
consts(lang),
|
consts(lang),
|
||||||
new StringReplacePlugin(),
|
new StringReplacePlugin()
|
||||||
hoist()
|
|
||||||
];
|
];
|
||||||
|
|
||||||
if (isProduction) {
|
if (isProduction) {
|
||||||
|
plugins.push(hoist());
|
||||||
plugins.push(minify());
|
plugins.push(minify());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue