summaryrefslogtreecommitdiff
path: root/src/web/app
diff options
context:
space:
mode:
Diffstat (limited to 'src/web/app')
-rw-r--r--src/web/app/common/define-widget.ts26
-rw-r--r--src/web/app/common/scripts/check-for-update.ts4
-rw-r--r--src/web/app/common/views/components/index.ts30
-rw-r--r--src/web/app/common/views/components/widgets/access-log.vue (renamed from src/web/app/desktop/views/components/widgets/access-log.vue)70
-rw-r--r--src/web/app/common/views/components/widgets/broadcast.vue (renamed from src/web/app/desktop/views/components/widgets/broadcast.vue)10
-rw-r--r--src/web/app/common/views/components/widgets/calendar.vue (renamed from src/web/app/desktop/views/components/widgets/calendar.vue)7
-rw-r--r--src/web/app/common/views/components/widgets/donation.vue (renamed from src/web/app/desktop/views/components/widgets/donation.vue)15
-rw-r--r--src/web/app/common/views/components/widgets/nav.vue (renamed from src/web/app/desktop/views/components/widgets/nav.vue)12
-rw-r--r--src/web/app/common/views/components/widgets/photo-stream.vue104
-rw-r--r--src/web/app/common/views/components/widgets/profile.vue (renamed from src/web/app/desktop/views/components/widgets/profile.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/rss.vue93
-rw-r--r--src/web/app/common/views/components/widgets/server.cpu-memory.vue (renamed from src/web/app/desktop/views/components/widgets/server.cpu-memory.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/server.cpu.vue (renamed from src/web/app/desktop/views/components/widgets/server.cpu.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/server.disk.vue (renamed from src/web/app/desktop/views/components/widgets/server.disk.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/server.info.vue (renamed from src/web/app/desktop/views/components/widgets/server.info.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/server.memory.vue (renamed from src/web/app/desktop/views/components/widgets/server.memory.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/server.pie.vue (renamed from src/web/app/desktop/views/components/widgets/server.pie.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/server.uptimes.vue (renamed from src/web/app/desktop/views/components/widgets/server.uptimes.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/server.vue93
-rw-r--r--src/web/app/common/views/components/widgets/slideshow.vue (renamed from src/web/app/desktop/views/components/widgets/slideshow.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/tips.vue (renamed from src/web/app/desktop/views/components/widgets/tips.vue)0
-rw-r--r--src/web/app/common/views/components/widgets/version.vue (renamed from src/web/app/desktop/views/components/widgets/version.vue)0
-rw-r--r--src/web/app/desktop/views/components/index.ts32
-rw-r--r--src/web/app/desktop/views/components/widget-container.vue72
-rw-r--r--src/web/app/desktop/views/components/widgets/photo-stream.vue122
-rw-r--r--src/web/app/desktop/views/components/widgets/rss.vue111
-rw-r--r--src/web/app/desktop/views/components/widgets/server.vue131
-rw-r--r--src/web/app/mobile/views/components/activity.vue (renamed from src/web/app/mobile/views/pages/user/home.activity.vue)4
-rw-r--r--src/web/app/mobile/views/components/home.vue29
-rw-r--r--src/web/app/mobile/views/components/index.ts14
-rw-r--r--src/web/app/mobile/views/components/ui.header.vue4
-rw-r--r--src/web/app/mobile/views/components/ui.vue6
-rw-r--r--src/web/app/mobile/views/components/widget-container.vue65
-rw-r--r--src/web/app/mobile/views/components/widgets/activity.vue23
-rw-r--r--src/web/app/mobile/views/pages/drive.vue4
-rw-r--r--src/web/app/mobile/views/pages/home.vue174
-rw-r--r--src/web/app/mobile/views/pages/notifications.vue4
-rw-r--r--src/web/app/mobile/views/pages/user.vue1
-rw-r--r--src/web/app/mobile/views/pages/user/home.vue6
39 files changed, 766 insertions, 500 deletions
diff --git a/src/web/app/common/define-widget.ts b/src/web/app/common/define-widget.ts
index fd13a3395b..60cd1969c0 100644
--- a/src/web/app/common/define-widget.ts
+++ b/src/web/app/common/define-widget.ts
@@ -8,6 +8,10 @@ export default function<T extends object>(data: {
props: {
widget: {
type: Object
+ },
+ isMobile: {
+ type: Boolean,
+ default: false
}
},
computed: {
@@ -21,6 +25,7 @@ export default function<T extends object>(data: {
};
},
created() {
+ if (this.widget.data == null) this.widget.data = {};
if (this.props) {
Object.keys(this.props).forEach(prop => {
if (this.widget.data.hasOwnProperty(prop)) {
@@ -30,12 +35,21 @@ export default function<T extends object>(data: {
}
this.$watch('props', newProps => {
- (this as any).api('i/update_home', {
- id: this.id,
- data: newProps
- }).then(() => {
- (this as any).os.i.client_settings.home.find(w => w.id == this.id).data = newProps;
- });
+ if (this.isMobile) {
+ (this as any).api('i/update_mobile_home', {
+ id: this.id,
+ data: newProps
+ }).then(() => {
+ (this as any).os.i.client_settings.mobile_home.find(w => w.id == this.id).data = newProps;
+ });
+ } else {
+ (this as any).api('i/update_home', {
+ id: this.id,
+ data: newProps
+ }).then(() => {
+ (this as any).os.i.client_settings.home.find(w => w.id == this.id).data = newProps;
+ });
+ }
}, {
deep: true
});
diff --git a/src/web/app/common/scripts/check-for-update.ts b/src/web/app/common/scripts/check-for-update.ts
index 0855676a42..fe539407da 100644
--- a/src/web/app/common/scripts/check-for-update.ts
+++ b/src/web/app/common/scripts/check-for-update.ts
@@ -9,7 +9,9 @@ export default async function(mios: MiOS) {
// Clear cache (serive worker)
try {
- navigator.serviceWorker.controller.postMessage('clear');
+ if (navigator.serviceWorker.controller) {
+ navigator.serviceWorker.controller.postMessage('clear');
+ }
navigator.serviceWorker.getRegistrations().then(registrations => {
registrations.forEach(registration => registration.unregister());
diff --git a/src/web/app/common/views/components/index.ts b/src/web/app/common/views/components/index.ts
index ab0f1767d4..e66a323266 100644
--- a/src/web/app/common/views/components/index.ts
+++ b/src/web/app/common/views/components/index.ts
@@ -21,6 +21,21 @@ import urlPreview from './url-preview.vue';
import twitterSetting from './twitter-setting.vue';
import fileTypeIcon from './file-type-icon.vue';
+//#region widgets
+import wAccessLog from './widgets/access-log.vue';
+import wVersion from './widgets/version.vue';
+import wRss from './widgets/rss.vue';
+import wProfile from './widgets/profile.vue';
+import wServer from './widgets/server.vue';
+import wBroadcast from './widgets/broadcast.vue';
+import wCalendar from './widgets/calendar.vue';
+import wPhotoStream from './widgets/photo-stream.vue';
+import wSlideshow from './widgets/slideshow.vue';
+import wTips from './widgets/tips.vue';
+import wDonation from './widgets/donation.vue';
+import wNav from './widgets/nav.vue';
+//#endregion
+
Vue.component('mk-signin', signin);
Vue.component('mk-signup', signup);
Vue.component('mk-forkit', forkit);
@@ -41,3 +56,18 @@ Vue.component('mk-messaging-room', messagingRoom);
Vue.component('mk-url-preview', urlPreview);
Vue.component('mk-twitter-setting', twitterSetting);
Vue.component('mk-file-type-icon', fileTypeIcon);
+
+//#region widgets
+Vue.component('mkw-nav', wNav);
+Vue.component('mkw-calendar', wCalendar);
+Vue.component('mkw-photo-stream', wPhotoStream);
+Vue.component('mkw-slideshow', wSlideshow);
+Vue.component('mkw-tips', wTips);
+Vue.component('mkw-donation', wDonation);
+Vue.component('mkw-broadcast', wBroadcast);
+Vue.component('mkw-profile', wProfile);
+Vue.component('mkw-server', wServer);
+Vue.component('mkw-rss', wRss);
+Vue.component('mkw-version', wVersion);
+Vue.component('mkw-access-log', wAccessLog);
+//#endregion
diff --git a/src/web/app/desktop/views/components/widgets/access-log.vue b/src/web/app/common/views/components/widgets/access-log.vue
index a04da1daaf..c810c2d157 100644
--- a/src/web/app/desktop/views/components/widgets/access-log.vue
+++ b/src/web/app/common/views/components/widgets/access-log.vue
@@ -1,15 +1,16 @@
<template>
<div class="mkw-access-log">
- <template v-if="props.design == 0">
- <p class="title">%fa:server%%i18n:desktop.tags.mk-access-log-home-widget.title%</p>
- </template>
- <div ref="log">
- <p v-for="req in requests">
- <span class="ip" :style="`color:${ req.fg }; background:${ req.bg }`">{{ req.ip }}</span>
- <b>{{ req.method }}</b>
- <span>{{ req.path }}</span>
- </p>
- </div>
+ <mk-widget-container :show-header="props.design == 0">
+ <template slot="header">%fa:server%%i18n:desktop.tags.mk-access-log-home-widget.title%</template>
+
+ <div :class="$style.logs" ref="log">
+ <p v-for="req in requests">
+ <span :class="$style.ip" :style="`color:${ req.fg }; background:${ req.bg }`">{{ req.ip }}</span>
+ <b>{{ req.method }}</b>
+ <span>{{ req.path }}</span>
+ </p>
+ </div>
+ </mk-widget-container>
</div>
</template>
@@ -65,44 +66,25 @@ export default define({
});
</script>
-<style lang="stylus" scoped>
-.mkw-access-log
- overflow hidden
- background #fff
- border solid 1px rgba(0, 0, 0, 0.075)
- border-radius 6px
+<style lang="stylus" module>
+.logs
+ max-height 250px
+ overflow auto
- > .title
- z-index 1
+ > p
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
+ padding 8px
+ font-size 0.8em
+ color #555
- > div
- max-height 250px
- overflow auto
+ &:nth-child(odd)
+ background rgba(0, 0, 0, 0.025)
- > p
- margin 0
- padding 8px
- font-size 0.8em
- color #555
-
- &:nth-child(odd)
- background rgba(0, 0, 0, 0.025)
-
- > .ip
- margin-right 4px
- padding 0 4px
+ > b
+ margin-right 4px
- > b
- margin-right 4px
+.ip
+ margin-right 4px
+ padding 0 4px
</style>
diff --git a/src/web/app/desktop/views/components/widgets/broadcast.vue b/src/web/app/common/views/components/widgets/broadcast.vue
index e4b7e25321..0bb59caf43 100644
--- a/src/web/app/desktop/views/components/widgets/broadcast.vue
+++ b/src/web/app/common/views/components/widgets/broadcast.vue
@@ -1,5 +1,9 @@
<template>
-<div class="mkw-broadcast" :data-found="broadcasts.length != 0" :data-melt="props.design == 1">
+<div class="mkw-broadcast"
+ :data-found="broadcasts.length != 0"
+ :data-melt="props.design == 1"
+ :data-mobile="isMobile"
+>
<div class="icon">
<svg height="32" version="1.1" viewBox="0 0 32 32" width="32">
<path class="tower" d="M16.04,11.24c1.79,0,3.239-1.45,3.239-3.24S17.83,4.76,16.04,4.76c-1.79,0-3.24,1.45-3.24,3.24 C12.78,9.78,14.24,11.24,16.04,11.24z M16.04,13.84c-0.82,0-1.66-0.2-2.4-0.6L7.34,29.98h2.98l1.72-2h8l1.681,2H24.7L18.42,13.24 C17.66,13.64,16.859,13.84,16.04,13.84z M16.02,14.8l2.02,7.2h-4L16.02,14.8z M12.04,25.98l2-2h4l2,2H12.04z"></path>
@@ -150,4 +154,8 @@ export default define({
display block
font-size 0.7em
+ &[data-mobile]
+ > p
+ color #fff
+
</style>
diff --git a/src/web/app/desktop/views/components/widgets/calendar.vue b/src/web/app/common/views/components/widgets/calendar.vue
index c16602db46..bfcbd7f68d 100644
--- a/src/web/app/desktop/views/components/widgets/calendar.vue
+++ b/src/web/app/common/views/components/widgets/calendar.vue
@@ -2,6 +2,7 @@
<div class="mkw-calendar"
:data-melt="props.design == 1"
:data-special="special"
+ :data-mobile="isMobile"
>
<div class="calendar" :data-is-holiday="isHoliday">
<p class="month-and-year">
@@ -66,6 +67,7 @@ export default define({
},
methods: {
func() {
+ if (this.isMobile) return;
if (this.props.design == 2) {
this.props.design = 0;
} else {
@@ -119,6 +121,11 @@ export default define({
background transparent
border none
+ &[data-mobile]
+ border none
+ border-radius 8px
+ box-shadow 0 0 0 1px rgba(0, 0, 0, 0.2)
+
&:after
content ""
display block
diff --git a/src/web/app/desktop/views/components/widgets/donation.vue b/src/web/app/common/views/components/widgets/donation.vue
index fbab0fca6c..08aab8ecd1 100644
--- a/src/web/app/desktop/views/components/widgets/donation.vue
+++ b/src/web/app/common/views/components/widgets/donation.vue
@@ -1,5 +1,5 @@
<template>
-<div class="mkw-donation">
+<div class="mkw-donation" :data-mobile="isMobile">
<article>
<h1>%fa:heart%%i18n:desktop.tags.mk-donation-home-widget.title%</h1>
<p>
@@ -42,4 +42,17 @@ export default define({
font-size 0.8em
color #999
+ &[data-mobile]
+ border none
+ background #ead8bb
+ border-radius 8px
+ box-shadow 0 0 0 1px rgba(0, 0, 0, 0.2)
+
+ > article
+ > h1
+ color #7b8871
+
+ > p
+ color #777d71
+
</style>
diff --git a/src/web/app/desktop/views/components/widgets/nav.vue b/src/web/app/common/views/components/widgets/nav.vue
index 5e04c266cf..ce88e587a8 100644
--- a/src/web/app/desktop/views/components/widgets/nav.vue
+++ b/src/web/app/common/views/components/widgets/nav.vue
@@ -1,6 +1,10 @@
<template>
<div class="mkw-nav">
- <mk-nav/>
+ <mk-widget-container>
+ <div :class="$style.body">
+ <mk-nav/>
+ </div>
+ </mk-widget-container>
</div>
</template>
@@ -11,14 +15,12 @@ export default define({
});
</script>
-<style lang="stylus" scoped>
-.mkw-nav
+<style lang="stylus" module>
+.body
padding 16px
font-size 12px
color #aaa
background #fff
- border solid 1px rgba(0, 0, 0, 0.075)
- border-radius 6px
a
color #999
diff --git a/src/web/app/common/views/components/widgets/photo-stream.vue b/src/web/app/common/views/components/widgets/photo-stream.vue
new file mode 100644
index 0000000000..dcaa6624dd
--- /dev/null
+++ b/src/web/app/common/views/components/widgets/photo-stream.vue
@@ -0,0 +1,104 @@
+<template>
+<div class="mkw-photo-stream" :class="$style.root" :data-melt="props.design == 2">
+ <mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
+ <template slot="header">%fa:camera%%i18n:desktop.tags.mk-photo-stream-home-widget.title%</template>
+
+ <p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
+ <div :class="$style.stream" v-if="!fetching && images.length > 0">
+ <div v-for="image in images" :key="image.id" :class="$style.img" :style="`background-image: url(${image.url}?thumbnail&size=256)`"></div>
+ </div>
+ <p :class="$style.empty" v-if="!fetching && images.length == 0">%i18n:desktop.tags.mk-photo-stream-home-widget.no-photos%</p>
+ </mk-widget-container>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../../../common/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 as any).os.stream.getConnection();
+ this.connectionId = (this as any).os.stream.use();
+
+ this.connection.on('drive_file_created', this.onDriveFileCreated);
+
+ (this as any).api('drive/stream', {
+ type: 'image/*',
+ limit: 9
+ }).then(images => {
+ this.images = images;
+ this.fetching = false;
+ });
+ },
+ beforeDestroy() {
+ this.connection.off('drive_file_created', this.onDriveFileCreated);
+ (this as any).os.stream.dispose(this.connectionId);
+ },
+ methods: {
+ onDriveFileCreated(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" module>
+.root[data-melt]
+ .stream
+ padding 0
+
+ .img
+ border solid 4px transparent
+ border-radius 8px
+
+.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>
diff --git a/src/web/app/desktop/views/components/widgets/profile.vue b/src/web/app/common/views/components/widgets/profile.vue
index 68cf469788..68cf469788 100644
--- a/src/web/app/desktop/views/components/widgets/profile.vue
+++ b/src/web/app/common/views/components/widgets/profile.vue
diff --git a/src/web/app/common/views/components/widgets/rss.vue b/src/web/app/common/views/components/widgets/rss.vue
new file mode 100644
index 0000000000..e80896bea6
--- /dev/null
+++ b/src/web/app/common/views/components/widgets/rss.vue
@@ -0,0 +1,93 @@
+<template>
+<div class="mkw-rss" :data-mobile="isMobile">
+ <mk-widget-container :show-header="!props.compact">
+ <template slot="header">%fa:rss-square%RSS</template>
+ <button slot="func" title="設定" @click="setting">%fa:cog%</button>
+
+ <p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
+ <div :class="$style.feed" v-else>
+ <a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>
+ </div>
+ </mk-widget-container>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../../../common/define-widget';
+export default define({
+ name: 'rss',
+ props: () => ({
+ compact: false
+ })
+}).extend({
+ data() {
+ return {
+ url: 'http://news.yahoo.co.jp/pickup/rss.xml',
+ items: [],
+ fetching: true,
+ clock: null
+ };
+ },
+ mounted() {
+ this.fetch();
+ this.clock = setInterval(this.fetch, 60000);
+ },
+ beforeDestroy() {
+ clearInterval(this.clock);
+ },
+ methods: {
+ func() {
+ this.props.compact = !this.props.compact;
+ },
+ fetch() {
+ fetch(`https://api.rss2json.com/v1/api.json?rss_url=${this.url}`, {
+ cache: 'no-cache'
+ }).then(res => {
+ res.json().then(feed => {
+ this.items = feed.items;
+ this.fetching = false;
+ });
+ });
+ },
+ setting() {
+ alert('not implemented yet');
+ }
+ }
+});
+</script>
+
+<style lang="stylus" module>
+.feed
+ padding 12px 16px
+ font-size 0.9em
+
+ > a
+ display block
+ padding 4px 0
+ color #666
+ border-bottom dashed 1px #eee
+
+ &:last-child
+ border-bottom none
+
+.fetching
+ margin 0
+ padding 16px
+ text-align center
+ color #aaa
+
+ > [data-fa]
+ margin-right 4px
+
+&[data-mobile]
+ .feed
+ padding 0
+ font-size 1em
+
+ > a
+ padding 8px 16px
+
+ &:nth-child(even)
+ background #e2e2e2
+
+</style>
diff --git a/src/web/app/desktop/views/components/widgets/server.cpu-memory.vue b/src/web/app/common/views/components/widgets/server.cpu-memory.vue
index d75a142568..d75a142568 100644
--- a/src/web/app/desktop/views/components/widgets/server.cpu-memory.vue
+++ b/src/web/app/common/views/components/widgets/server.cpu-memory.vue
diff --git a/src/web/app/desktop/views/components/widgets/server.cpu.vue b/src/web/app/common/views/components/widgets/server.cpu.vue
index 596c856da8..596c856da8 100644
--- a/src/web/app/desktop/views/components/widgets/server.cpu.vue
+++ b/src/web/app/common/views/components/widgets/server.cpu.vue
diff --git a/src/web/app/desktop/views/components/widgets/server.disk.vue b/src/web/app/common/views/components/widgets/server.disk.vue
index 2af1982a96..2af1982a96 100644
--- a/src/web/app/desktop/views/components/widgets/server.disk.vue
+++ b/src/web/app/common/views/components/widgets/server.disk.vue
diff --git a/src/web/app/desktop/views/components/widgets/server.info.vue b/src/web/app/common/views/components/widgets/server.info.vue
index bed6a1b743..bed6a1b743 100644
--- a/src/web/app/desktop/views/components/widgets/server.info.vue
+++ b/src/web/app/common/views/components/widgets/server.info.vue
diff --git a/src/web/app/desktop/views/components/widgets/server.memory.vue b/src/web/app/common/views/components/widgets/server.memory.vue
index 834a62671d..834a62671d 100644
--- a/src/web/app/desktop/views/components/widgets/server.memory.vue
+++ b/src/web/app/common/views/components/widgets/server.memory.vue
diff --git a/src/web/app/desktop/views/components/widgets/server.pie.vue b/src/web/app/common/views/components/widgets/server.pie.vue
index ce2cff1d00..ce2cff1d00 100644
--- a/src/web/app/desktop/views/components/widgets/server.pie.vue
+++ b/src/web/app/common/views/components/widgets/server.pie.vue
diff --git a/src/web/app/desktop/views/components/widgets/server.uptimes.vue b/src/web/app/common/views/components/widgets/server.uptimes.vue
index 06713d83ce..06713d83ce 100644
--- a/src/web/app/desktop/views/components/widgets/server.uptimes.vue
+++ b/src/web/app/common/views/components/widgets/server.uptimes.vue
diff --git a/src/web/app/common/views/components/widgets/server.vue b/src/web/app/common/views/components/widgets/server.vue
new file mode 100644
index 0000000000..4ebc5767d6
--- /dev/null
+++ b/src/web/app/common/views/components/widgets/server.vue
@@ -0,0 +1,93 @@
+<template>
+<div class="mkw-server">
+ <mk-widget-container :show-header="props.design == 0" :naked="props.design == 2">
+ <template slot="header">%fa:server%%i18n:desktop.tags.mk-server-home-widget.title%</template>
+ <button slot="func" @click="toggle" title="%i18n:desktop.tags.mk-server-home-widget.toggle%">%fa:sort%</button>
+
+ <p :class="$style.fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
+ <template v-if="!fetching">
+ <x-cpu-memory v-show="props.view == 0" :connection="connection"/>
+ <x-cpu v-show="props.view == 1" :connection="connection" :meta="meta"/>
+ <x-memory v-show="props.view == 2" :connection="connection"/>
+ <x-disk v-show="props.view == 3" :connection="connection"/>
+ <x-uptimes v-show="props.view == 4" :connection="connection"/>
+ <x-info v-show="props.view == 5" :connection="connection" :meta="meta"/>
+ </template>
+ </mk-widget-container>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../../../common/define-widget';
+import XCpuMemory from './server.cpu-memory.vue';
+import XCpu from './server.cpu.vue';
+import XMemory from './server.memory.vue';
+import XDisk from './server.disk.vue';
+import XUptimes from './server.uptimes.vue';
+import XInfo from './server.info.vue';
+
+export default define({
+ name: 'server',
+ props: () => ({
+ design: 0,
+ view: 0
+ })
+}).extend({
+ components: {
+ XCpuMemory,
+ XCpu,
+ XMemory,
+ XDisk,
+ XUptimes,
+ XInfo
+ },
+ data() {
+ return {
+ fetching: true,
+ meta: null,
+ connection: null,
+ connectionId: null
+ };
+ },
+ mounted() {
+ (this as any).os.getMeta().then(meta => {
+ this.meta = meta;
+ this.fetching = false;
+ });
+
+ this.connection = (this as any).os.streams.serverStream.getConnection();
+ this.connectionId = (this as any).os.streams.serverStream.use();
+ },
+ beforeDestroy() {
+ (this as any).os.streams.serverStream.dispose(this.connectionId);
+ },
+ methods: {
+ toggle() {
+ if (this.props.view == 5) {
+ this.props.view = 0;
+ } else {
+ this.props.view++;
+ }
+ },
+ func() {
+ if (this.props.design == 2) {
+ this.props.design = 0;
+ } else {
+ this.props.design++;
+ }
+ }
+ }
+});
+</script>
+
+<style lang="stylus" module>
+.fetching
+ margin 0
+ padding 16px
+ text-align center
+ color #aaa
+
+ > [data-fa]
+ margin-right 4px
+
+</style>
diff --git a/src/web/app/desktop/views/components/widgets/slideshow.vue b/src/web/app/common/views/components/widgets/slideshow.vue
index c2f4eb70d3..c2f4eb70d3 100644
--- a/src/web/app/desktop/views/components/widgets/slideshow.vue
+++ b/src/web/app/common/views/components/widgets/slideshow.vue
diff --git a/src/web/app/desktop/views/components/widgets/tips.vue b/src/web/app/common/views/components/widgets/tips.vue
index 2991fbc3b9..2991fbc3b9 100644
--- a/src/web/app/desktop/views/components/widgets/tips.vue
+++ b/src/web/app/common/views/components/widgets/tips.vue
diff --git a/src/web/app/desktop/views/components/widgets/version.vue b/src/web/app/common/views/components/widgets/version.vue
index ad2b27bc40..ad2b27bc40 100644
--- a/src/web/app/desktop/views/components/widgets/version.vue
+++ b/src/web/app/common/views/components/widgets/version.vue
diff --git a/src/web/app/desktop/views/components/index.ts b/src/web/app/desktop/views/components/index.ts
index da59d9219e..7584cb4983 100644
--- a/src/web/app/desktop/views/components/index.ts
+++ b/src/web/app/desktop/views/components/index.ts
@@ -27,27 +27,19 @@ import friendsMaker from './friends-maker.vue';
import followers from './followers.vue';
import following from './following.vue';
import usersList from './users-list.vue';
-import wNav from './widgets/nav.vue';
-import wCalendar from './widgets/calendar.vue';
-import wPhotoStream from './widgets/photo-stream.vue';
-import wSlideshow from './widgets/slideshow.vue';
-import wTips from './widgets/tips.vue';
-import wDonation from './widgets/donation.vue';
+import widgetContainer from './widget-container.vue';
+
+//#region widgets
import wNotifications from './widgets/notifications.vue';
-import wBroadcast from './widgets/broadcast.vue';
import wTimemachine from './widgets/timemachine.vue';
-import wProfile from './widgets/profile.vue';
-import wServer from './widgets/server.vue';
import wActivity from './widgets/activity.vue';
-import wRss from './widgets/rss.vue';
import wTrends from './widgets/trends.vue';
-import wVersion from './widgets/version.vue';
import wUsers from './widgets/users.vue';
import wPolls from './widgets/polls.vue';
import wPostForm from './widgets/post-form.vue';
import wMessaging from './widgets/messaging.vue';
import wChannel from './widgets/channel.vue';
-import wAccessLog from './widgets/access-log.vue';
+//#endregion
Vue.component('mk-ui', ui);
Vue.component('mk-ui-notification', uiNotification);
@@ -76,24 +68,16 @@ Vue.component('mk-friends-maker', friendsMaker);
Vue.component('mk-followers', followers);
Vue.component('mk-following', following);
Vue.component('mk-users-list', usersList);
-Vue.component('mkw-nav', wNav);
-Vue.component('mkw-calendar', wCalendar);
-Vue.component('mkw-photo-stream', wPhotoStream);
-Vue.component('mkw-slideshow', wSlideshow);
-Vue.component('mkw-tips', wTips);
-Vue.component('mkw-donation', wDonation);
+Vue.component('mk-widget-container', widgetContainer);
+
+//#region widgets
Vue.component('mkw-notifications', wNotifications);
-Vue.component('mkw-broadcast', wBroadcast);
Vue.component('mkw-timemachine', wTimemachine);
-Vue.component('mkw-profile', wProfile);
-Vue.component('mkw-server', wServer);
Vue.component('mkw-activity', wActivity);
-Vue.component('mkw-rss', wRss);
Vue.component('mkw-trends', wTrends);
-Vue.component('mkw-version', wVersion);
Vue.component('mkw-users', wUsers);
Vue.component('mkw-polls', wPolls);
Vue.component('mkw-post-form', wPostForm);
Vue.component('mkw-messaging', wMessaging);
Vue.component('mkw-channel', wChannel);
-Vue.component('mkw-access-log', wAccessLog);
+//#endregion
diff --git a/src/web/app/desktop/views/components/widget-container.vue b/src/web/app/desktop/views/components/widget-container.vue
new file mode 100644
index 0000000000..7b4e1f55f0
--- /dev/null
+++ b/src/web/app/desktop/views/components/widget-container.vue
@@ -0,0 +1,72 @@
+<template>
+<div class="mk-widget-container" :class="{ naked }">
+ <header v-if="showHeader">
+ <div class="title"><slot name="header"></slot></div>
+ <slot name="func"></slot>
+ </header>
+ <slot></slot>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+ props: {
+ showHeader: {
+ type: Boolean,
+ default: true
+ },
+ naked: {
+ type: Boolean,
+ default: false
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.mk-widget-container
+ background #fff
+ border solid 1px rgba(0, 0, 0, 0.075)
+ border-radius 6px
+ overflow hidden
+
+ &.naked
+ background transparent !important
+ border none !important
+
+ > header
+ > .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
+
+ &:empty
+ display none
+
+ > 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
+
+</style>
diff --git a/src/web/app/desktop/views/components/widgets/photo-stream.vue b/src/web/app/desktop/views/components/widgets/photo-stream.vue
deleted file mode 100644
index 04b71975b3..0000000000
--- a/src/web/app/desktop/views/components/widgets/photo-stream.vue
+++ /dev/null
@@ -1,122 +0,0 @@
-<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 '../../../../common/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 as any).os.stream.getConnection();
- this.connectionId = (this as any).os.stream.use();
-
- this.connection.on('drive_file_created', this.onDriveFileCreated);
-
- (this as any).api('drive/stream', {
- type: 'image/*',
- limit: 9
- }).then(images => {
- this.images = images;
- this.fetching = false;
- });
- },
- beforeDestroy() {
- this.connection.off('drive_file_created', this.onDriveFileCreated);
- (this as any).os.stream.dispose(this.connectionId);
- },
- methods: {
- onDriveFileCreated(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>
diff --git a/src/web/app/desktop/views/components/widgets/rss.vue b/src/web/app/desktop/views/components/widgets/rss.vue
deleted file mode 100644
index 3507129716..0000000000
--- a/src/web/app/desktop/views/components/widgets/rss.vue
+++ /dev/null
@@ -1,111 +0,0 @@
-<template>
-<div class="mkw-rss">
- <template v-if="!props.compact">
- <p class="title">%fa:rss-square%RSS</p>
- <button title="設定">%fa:cog%</button>
- </template>
- <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
- <div class="feed" v-else>
- <a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>
- </div>
-</div>
-</template>
-
-<script lang="ts">
-import define from '../../../../common/define-widget';
-export default define({
- name: 'rss',
- props: () => ({
- compact: false
- })
-}).extend({
- data() {
- return {
- url: 'http://news.yahoo.co.jp/pickup/rss.xml',
- items: [],
- fetching: true,
- clock: null
- };
- },
- mounted() {
- this.fetch();
- this.clock = setInterval(this.fetch, 60000);
- },
- beforeDestroy() {
- clearInterval(this.clock);
- },
- methods: {
- func() {
- this.props.compact = !this.props.compact;
- },
- fetch() {
- fetch(`https://api.rss2json.com/v1/api.json?rss_url=${this.url}`, {
- cache: 'no-cache'
- }).then(res => {
- res.json().then(feed => {
- this.items = feed.items;
- this.fetching = false;
- });
- });
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.mkw-rss
- background #fff
- border solid 1px rgba(0, 0, 0, 0.075)
- border-radius 6px
-
- > .title
- 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
- top 0
- right 0
- padding 0
- width 42px
- font-size 0.9em
- line-height 42px
- color #ccc
-
- &:hover
- color #aaa
-
- &:active
- color #999
-
- > .feed
- padding 12px 16px
- font-size 0.9em
-
- > a
- display block
- padding 4px 0
- color #666
- border-bottom dashed 1px #eee
-
- &:last-child
- border-bottom none
-
- > .fetching
- margin 0
- padding 16px
- text-align center
- color #aaa
-
- > [data-fa]
- margin-right 4px
-
-</style>
diff --git a/src/web/app/desktop/views/components/widgets/server.vue b/src/web/app/desktop/views/components/widgets/server.vue
deleted file mode 100644
index 1c0da84225..0000000000
--- a/src/web/app/desktop/views/components/widgets/server.vue
+++ /dev/null
@@ -1,131 +0,0 @@
-<template>
-<div class="mkw-server" :data-melt="props.design == 2">
- <template v-if="props.design == 0">
- <p class="title">%fa:server%%i18n:desktop.tags.mk-server-home-widget.title%</p>
- <button @click="toggle" title="%i18n:desktop.tags.mk-server-home-widget.toggle%">%fa:sort%</button>
- </template>
- <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
- <template v-if="!fetching">
- <x-cpu-memory v-show="props.view == 0" :connection="connection"/>
- <x-cpu v-show="props.view == 1" :connection="connection" :meta="meta"/>
- <x-memory v-show="props.view == 2" :connection="connection"/>
- <x-disk v-show="props.view == 3" :connection="connection"/>
- <x-uptimes v-show="props.view == 4" :connection="connection"/>
- <x-info v-show="props.view == 5" :connection="connection" :meta="meta"/>
- </template>
-</div>
-</template>
-
-<script lang="ts">
-import define from '../../../../common/define-widget';
-import XCpuMemory from './server.cpu-memory.vue';
-import XCpu from './server.cpu.vue';
-import XMemory from './server.memory.vue';
-import XDisk from './server.disk.vue';
-import XUptimes from './server.uptimes.vue';
-import XInfo from './server.info.vue';
-
-export default define({
- name: 'server',
- props: () => ({
- design: 0,
- view: 0
- })
-}).extend({
- components: {
- XCpuMemory,
- XCpu,
- XMemory,
- XDisk,
- XUptimes,
- XInfo
- },
- data() {
- return {
- fetching: true,
- meta: null,
- connection: null,
- connectionId: null
- };
- },
- mounted() {
- (this as any).os.getMeta().then(meta => {
- this.meta = meta;
- this.fetching = false;
- });
-
- this.connection = (this as any).os.streams.serverStream.getConnection();
- this.connectionId = (this as any).os.streams.serverStream.use();
- },
- beforeDestroy() {
- (this as any).os.streams.serverStream.dispose(this.connectionId);
- },
- methods: {
- toggle() {
- if (this.props.view == 5) {
- this.props.view = 0;
- } else {
- this.props.view++;
- }
- },
- func() {
- if (this.props.design == 2) {
- this.props.design = 0;
- } else {
- this.props.design++;
- }
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.mkw-server
- 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>
diff --git a/src/web/app/mobile/views/pages/user/home.activity.vue b/src/web/app/mobile/views/components/activity.vue
index 87970795b2..b50044b3de 100644
--- a/src/web/app/mobile/views/pages/user/home.activity.vue
+++ b/src/web/app/mobile/views/components/activity.vue
@@ -1,5 +1,5 @@
<template>
-<div class="root activity">
+<div class="mk-activity">
<svg v-if="data" ref="canvas" viewBox="0 0 30 1" preserveAspectRatio="none">
<g v-for="(d, i) in data">
<rect width="0.8" :height="d.postsH"
@@ -47,7 +47,7 @@ export default Vue.extend({
</script>
<style lang="stylus" scoped>
-.root.activity
+.mk-activity
max-width 600px
margin 0 auto
diff --git a/src/web/app/mobile/views/components/home.vue b/src/web/app/mobile/views/components/home.vue
deleted file mode 100644
index 3feab581d2..0000000000
--- a/src/web/app/mobile/views/components/home.vue
+++ /dev/null
@@ -1,29 +0,0 @@
-<template>
-<div class="mk-home">
- <mk-timeline @loaded="onTlLoaded"/>
-</div>
-</template>
-
-<script lang="ts">
-import Vue from 'vue';
-export default Vue.extend({
- methods: {
- onTlLoaded() {
- this.$emit('loaded');
- }
- }
-});
-</script>
-
-<style lang="stylus" scoped>
-.mk-home
-
- > .mk-timeline
- max-width 600px
- margin 0 auto
- padding 8px
-
- @media (min-width 500px)
- padding 16px
-
-</style>
diff --git a/src/web/app/mobile/views/components/index.ts b/src/web/app/mobile/views/components/index.ts
index 905baaf20d..d372f22332 100644
--- a/src/web/app/mobile/views/components/index.ts
+++ b/src/web/app/mobile/views/components/index.ts
@@ -1,7 +1,6 @@
import Vue from 'vue';
import ui from './ui.vue';
-import home from './home.vue';
import timeline from './timeline.vue';
import posts from './posts.vue';
import imagesImage from './images-image.vue';
@@ -19,9 +18,14 @@ import notificationPreview from './notification-preview.vue';
import usersList from './users-list.vue';
import userPreview from './user-preview.vue';
import userTimeline from './user-timeline.vue';
+import activity from './activity.vue';
+import widgetContainer from './widget-container.vue';
+
+//#region widgets
+import wActivity from './widgets/activity.vue';
+//#endregion
Vue.component('mk-ui', ui);
-Vue.component('mk-home', home);
Vue.component('mk-timeline', timeline);
Vue.component('mk-posts', posts);
Vue.component('mk-images-image', imagesImage);
@@ -39,3 +43,9 @@ Vue.component('mk-notification-preview', notificationPreview);
Vue.component('mk-users-list', usersList);
Vue.component('mk-user-preview', userPreview);
Vue.component('mk-user-timeline', userTimeline);
+Vue.component('mk-activity', activity);
+Vue.component('mk-widget-container', widgetContainer);
+
+//#region widgets
+Vue.component('mkw-activity', wActivity);
+//#endregion
diff --git a/src/web/app/mobile/views/components/ui.header.vue b/src/web/app/mobile/views/components/ui.header.vue
index 2df5ea162e..026e7eb1b4 100644
--- a/src/web/app/mobile/views/components/ui.header.vue
+++ b/src/web/app/mobile/views/components/ui.header.vue
@@ -9,9 +9,7 @@
<h1>
<slot>Misskey</slot>
</h1>
- <button v-if="func" @click="func">
- <slot name="funcIcon"></slot>
- </button>
+ <slot name="func"></slot>
</div>
</div>
</div>
diff --git a/src/web/app/mobile/views/components/ui.vue b/src/web/app/mobile/views/components/ui.vue
index 91d7ea29b6..325ce9d40e 100644
--- a/src/web/app/mobile/views/components/ui.vue
+++ b/src/web/app/mobile/views/components/ui.vue
@@ -1,7 +1,7 @@
<template>
<div class="mk-ui">
- <x-header :func="func">
- <template slot="funcIcon"><slot name="funcIcon"></slot></template>
+ <x-header>
+ <template slot="func"><slot name="func"></slot></template>
<slot name="header"></slot>
</x-header>
<x-nav :is-open="isDrawerOpening"/>
@@ -23,7 +23,7 @@ export default Vue.extend({
XHeader,
XNav
},
- props: ['title', 'func'],
+ props: ['title'],
data() {
return {
isDrawerOpening: false,
diff --git a/src/web/app/mobile/views/components/widget-container.vue b/src/web/app/mobile/views/components/widget-container.vue
new file mode 100644
index 0000000000..1775188a93
--- /dev/null
+++ b/src/web/app/mobile/views/components/widget-container.vue
@@ -0,0 +1,65 @@
+<template>
+<div class="mk-widget-container" :class="{ naked }">
+ <header v-if="showHeader">
+ <div class="title"><slot name="header"></slot></div>
+ <slot name="func"></slot>
+ </header>
+ <slot></slot>
+</div>
+</template>
+
+<script lang="ts">
+import Vue from 'vue';
+export default Vue.extend({
+ props: {
+ showHeader: {
+ type: Boolean,
+ default: true
+ },
+ naked: {
+ type: Boolean,
+ default: false
+ }
+ }
+});
+</script>
+
+<style lang="stylus" scoped>
+.mk-widget-container
+ background #eee
+ border-radius 8px
+ box-shadow 0 0 0 1px rgba(0, 0, 0, 0.2)
+ overflow hidden
+
+ &.naked
+ background transparent !important
+ border none !important
+
+ > header
+ > .title
+ margin 0
+ padding 8px 10px
+ font-size 15px
+ font-weight normal
+ color #465258
+ background #fff
+ border-radius 8px 8px 0 0
+
+ > [data-fa]
+ margin-right 6px
+
+ &:empty
+ display none
+
+ > button
+ position absolute
+ z-index 2
+ top 0
+ right 0
+ padding 0
+ width 42px
+ height 100%
+ font-size 15px
+ color #465258
+
+</style>
diff --git a/src/web/app/mobile/views/components/widgets/activity.vue b/src/web/app/mobile/views/components/widgets/activity.vue
new file mode 100644
index 0000000000..c3fe63f264
--- /dev/null
+++ b/src/web/app/mobile/views/components/widgets/activity.vue
@@ -0,0 +1,23 @@
+<template>
+<div class="mkw-activity">
+ <mk-widget-container>
+ <template slot="header">%fa:chart-bar%アクティビティ</template>
+ <div :class="$style.body">
+ <mk-activity :user="os.i"/>
+ </div>
+ </mk-widget-container>
+</div>
+</template>
+
+<script lang="ts">
+import define from '../../../../common/define-widget';
+
+export default define({
+ name: 'activity',
+});
+</script>
+
+<style lang="stylus" module>
+.body
+ padding 8px
+</style>
diff --git a/src/web/app/mobile/views/pages/drive.vue b/src/web/app/mobile/views/pages/drive.vue
index 47aeb52f49..ea61661cf6 100644
--- a/src/web/app/mobile/views/pages/drive.vue
+++ b/src/web/app/mobile/views/pages/drive.vue
@@ -1,11 +1,11 @@
<template>
-<mk-ui :func="fn">
+<mk-ui>
<span slot="header">
<template v-if="folder">%fa:R folder-open%{{ folder.name }}</template>
<template v-if="file"><mk-file-type-icon class="icon" :type="file.type"/>{{ file.name }}</template>
<template v-if="!folder && !file">%fa:cloud%%i18n:mobile.tags.mk-drive-page.drive%</template>
</span>
- <template slot="funcIcon">%fa:ellipsis-h%</template>
+ <template slot="func"><button @click="fn">%fa:ellipsis-h%</button></template>
<mk-drive
ref="browser"
:init-folder="initFolder"
diff --git a/src/web/app/mobile/views/pages/home.vue b/src/web/app/mobile/views/pages/home.vue
index c81cbcadb3..0466fbbbf8 100644
--- a/src/web/app/mobile/views/pages/home.vue
+++ b/src/web/app/mobile/views/pages/home.vue
@@ -1,24 +1,112 @@
<template>
-<mk-ui :func="fn">
- <span slot="header">%fa:home%%i18n:mobile.tags.mk-home.home%</span>
- <template slot="funcIcon">%fa:pencil-alt%</template>
- <mk-home @loaded="onHomeLoaded"/>
+<mk-ui>
+ <span slot="header" @click="showTl = !showTl">
+ <template v-if="showTl">%fa:home%タイムライン</template>
+ <template v-else>%fa:home%ウィジェット</template>
+ <span style="margin-left:8px">
+ <template v-if="showTl">%fa:angle-down%</template>
+ <template v-else>%fa:angle-up%</template>
+ </span>
+ </span>
+ <template slot="func">
+ <button @click="fn" v-if="showTl">%fa:pencil-alt%</button>
+ <button @click="customizing = !customizing" v-else>%fa:cog%</button>
+ </template>
+ <main>
+ <div class="tl">
+ <mk-timeline @loaded="onLoaded" v-show="showTl"/>
+ </div>
+ <div class="widgets" v-if="!showTl">
+ <template v-if="customizing">
+ <header>
+ <select v-model="widgetAdderSelected">
+ <option value="profile">プロフィール</option>
+ <option value="calendar">カレンダー</option>
+ <option value="activity">アクティビティ</option>
+ <option value="rss">RSSリーダー</option>
+ <option value="photo-stream">フォトストリーム</option>
+ <option value="version">バージョン</option>
+ <option value="access-log">アクセスログ</option>
+ <option value="server">サーバー情報</option>
+ <option value="donation">寄付のお願い</option>
+ <option value="nav">ナビゲーション</option>
+ <option value="tips">ヒント</option>
+ </select>
+ <button @click="addWidget">追加</button>
+ <p>移動するには「三」をドラッグします。削除するには「x」をタップします。</p>
+ </header>
+ <x-draggable
+ :list="widgets"
+ :options="{ handle: '.handle', animation: 150 }"
+ @sort="onWidgetSort"
+ >
+ <div v-for="widget in widgets" class="customize-container" :key="widget.id">
+ <header>
+ <span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
+ </header>
+ <div>
+ <component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-mobile="true"/>
+ </div>
+ </div>
+ </x-draggable>
+ </template>
+ <template v-else>
+ <component class="widget" v-for="widget in widgets" :is="`mkw-${widget.name}`" :key="widget.id" :widget="widget" :is-mobile="true" @chosen="warp"/>
+ </template>
+ </div>
+ </main>
</mk-ui>
</template>
<script lang="ts">
import Vue from 'vue';
+import * as XDraggable from 'vuedraggable';
+import * as uuid from 'uuid';
import Progress from '../../../common/scripts/loading';
import getPostSummary from '../../../../../common/get-post-summary';
export default Vue.extend({
+ components: {
+ XDraggable
+ },
data() {
return {
connection: null,
connectionId: null,
- unreadCount: 0
+ unreadCount: 0,
+ showTl: true,
+ widgets: [],
+ customizing: false,
+ widgetAdderSelected: null
};
},
+ created() {
+ if ((this as any).os.i.client_settings.mobile_home == null) {
+ Vue.set((this as any).os.i.client_settings, 'mobile_home', [{
+ name: 'calendar',
+ id: 'a'
+ }, {
+ name: 'activity',
+ id: 'b'
+ }, {
+ name: 'rss',
+ id: 'c'
+ }, {
+ name: 'photo-stream',
+ id: 'd'
+ }, {
+ name: 'donation',
+ id: 'e'
+ }, {
+ name: 'nav',
+ id: 'f'
+ }, {
+ name: 'version',
+ id: 'g'
+ }]);
+ }
+ this.widgets = (this as any).os.i.client_settings.mobile_home;
+ },
mounted() {
document.title = 'Misskey';
document.documentElement.style.background = '#313a42';
@@ -40,7 +128,7 @@ export default Vue.extend({
fn() {
(this as any).apis.post();
},
- onHomeLoaded() {
+ onLoaded() {
Progress.done();
},
onStreamPost(post) {
@@ -54,7 +142,81 @@ export default Vue.extend({
this.unreadCount = 0;
document.title = 'Misskey';
}
+ },
+ onWidgetSort() {
+ this.saveHome();
+ },
+ addWidget() {
+ const widget = {
+ name: this.widgetAdderSelected,
+ id: uuid(),
+ data: {}
+ };
+
+ this.widgets.unshift(widget);
+ this.saveHome();
+ },
+ removeWidget(widget) {
+ this.widgets = this.widgets.filter(w => w.id != widget.id);
+ this.saveHome();
+ },
+ saveHome() {
+ (this as any).api('i/update_mobile_home', {
+ home: this.widgets
+ });
+ },
+ warp() {
+
}
}
});
</script>
+
+<style lang="stylus" scoped>
+main
+
+ > .tl
+ > .mk-timeline
+ max-width 600px
+ margin 0 auto
+ padding 8px
+
+ @media (min-width 500px)
+ padding 16px
+
+ > .widgets
+ margin 0 auto
+ max-width 500px
+
+ > header
+ padding 8px
+ background #fff
+
+ .widget
+ margin 8px
+
+ .customize-container
+ margin 8px
+ background #fff
+
+ > header
+ line-height 32px
+ background #eee
+
+ > .handle
+ padding 0 8px
+
+ > .remove
+ position absolute
+ top 0
+ right 0
+ padding 0 8px
+ line-height 32px
+
+ > div
+ padding 8px
+
+ > *
+ pointer-events none
+
+</style>
diff --git a/src/web/app/mobile/views/pages/notifications.vue b/src/web/app/mobile/views/pages/notifications.vue
index b1243dbc74..3dcfb2f38c 100644
--- a/src/web/app/mobile/views/pages/notifications.vue
+++ b/src/web/app/mobile/views/pages/notifications.vue
@@ -1,7 +1,7 @@
<template>
-<mk-ui :func="fn">
+<mk-ui>
<span slot="header">%fa:R bell%%i18n:mobile.tags.mk-notifications-page.notifications%</span>
- <span slot="funcIcon">%fa:check%</span>
+ <template slot="func"><button @click="fn">%fa:check%</button></template>
<mk-notifications @fetched="onFetched"/>
</mk-ui>
</template>
diff --git a/src/web/app/mobile/views/pages/user.vue b/src/web/app/mobile/views/pages/user.vue
index 27f65e623d..378beeaf13 100644
--- a/src/web/app/mobile/views/pages/user.vue
+++ b/src/web/app/mobile/views/pages/user.vue
@@ -1,7 +1,6 @@
<template>
<mk-ui>
<span slot="header" v-if="!fetching">%fa:user% {{ user.name }}</span>
- <template slot="funcIcon">%fa:pencil-alt%</template>
<main v-if="!fetching">
<header>
<div class="banner" :style="user.banner_url ? `background-image: url(${user.banner_url}?thumbnail&size=1024)` : ''"></div>
diff --git a/src/web/app/mobile/views/pages/user/home.vue b/src/web/app/mobile/views/pages/user/home.vue
index 4c68317879..fdbfd1bf55 100644
--- a/src/web/app/mobile/views/pages/user/home.vue
+++ b/src/web/app/mobile/views/pages/user/home.vue
@@ -16,7 +16,7 @@
<section class="activity">
<h2>%fa:chart-bar%%i18n:mobile.tags.mk-user-overview.activity%</h2>
<div>
- <x-activity :user="user"/>
+ <mk-activity :user="user"/>
</div>
</section>
<section class="frequently-replied-users">
@@ -41,15 +41,13 @@ import XPosts from './home.posts.vue';
import XPhotos from './home.photos.vue';
import XFriends from './home.friends.vue';
import XFollowersYouKnow from './home.followers-you-know.vue';
-import XActivity from './home.activity.vue';
export default Vue.extend({
components: {
XPosts,
XPhotos,
XFriends,
- XFollowersYouKnow,
- XActivity
+ XFollowersYouKnow
},
props: ['user']
});