1
1
mirror of https://github.com/kokonect-link/cherrypick synced 2024-12-14 06:38:28 +09:00

Deckにウィジェットを置けるように

This commit is contained in:
syuilo 2018-06-06 19:22:45 +09:00
parent ed8fa59639
commit b0f989dbac
20 changed files with 417 additions and 179 deletions

View File

@ -9,9 +9,9 @@ export default function<T extends object>(data: {
widget: { widget: {
type: Object type: Object
}, },
isMobile: { platform: {
type: Boolean, type: String,
default: false required: true
}, },
isCustomizeMode: { isCustomizeMode: {
type: Boolean, type: Boolean,
@ -66,17 +66,10 @@ export default function<T extends object>(data: {
this.bakeProps(); this.bakeProps();
if (this.isMobile) { (this as any).api('i/update_widget', {
(this as any).api('i/update_mobile_home', { id: this.id,
id: this.id, data: this.props
data: this.props });
});
} else {
(this as any).api('i/update_home', {
id: this.id,
data: this.props
});
}
} }
} }
}); });

View File

@ -58,25 +58,18 @@ export class HomeStream extends Stream {
}); });
this.on('home_updated', x => { this.on('home_updated', x => {
if (x.home) { os.store.commit('settings/setHome', x);
os.store.commit('settings/setHome', x.home);
} else {
os.store.commit('settings/setHomeWidget', {
id: x.id,
data: x.data
});
}
}); });
this.on('mobile_home_updated', x => { this.on('mobile_home_updated', x => {
if (x.home) { os.store.commit('settings/setMobileHome', x);
os.store.commit('settings/setMobileHome', x.home); });
} else {
os.store.commit('settings/setMobileHomeWidget', { this.on('widgetUpdated', x => {
id: x.id, os.store.commit('settings/setWidget', {
data: x.data id: x.id,
}); data: x.data
} });
}); });
// トークンが再生成されたとき // トークンが再生成されたとき

View File

@ -2,7 +2,10 @@
<div class="mk-menu"> <div class="mk-menu">
<div class="backdrop" ref="backdrop" @click="close"></div> <div class="backdrop" ref="backdrop" @click="close"></div>
<div class="popover" :class="{ compact }" ref="popover"> <div class="popover" :class="{ compact }" ref="popover">
<button v-for="item in items" @click="clicked(item.onClick)" v-html="item.content"></button> <template v-for="item in items">
<div v-if="item == null"></div>
<button v-else @click="clicked(item.onClick)" v-html="item.content"></button>
</template>
</div> </div>
</div> </div>
</template> </template>
@ -150,4 +153,9 @@ $border-color = rgba(27, 31, 35, 0.15)
color $theme-color-foreground color $theme-color-foreground
background darken($theme-color, 10%) background darken($theme-color, 10%)
> div
margin 8px 0
height 1px
background #eee
</style> </style>

View File

@ -2,7 +2,7 @@
<div class="mkw-broadcast" <div class="mkw-broadcast"
:data-found="broadcasts.length != 0" :data-found="broadcasts.length != 0"
:data-melt="props.design == 1" :data-melt="props.design == 1"
:data-mobile="isMobile" :data-mobile="platform == 'mobile'"
> >
<div class="icon"> <div class="icon">
<svg height="32" version="1.1" viewBox="0 0 32 32" width="32"> <svg height="32" version="1.1" viewBox="0 0 32 32" width="32">

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="mkw-calendar" :data-special="special" :data-mobile="isMobile"> <div class="mkw-calendar" :data-special="special" :data-mobile="platform == 'mobile'">
<mk-widget-container :naked="props.design == 1" :show-header="false"> <mk-widget-container :naked="props.design == 1" :show-header="false">
<div class="mkw-calendar--body"> <div class="mkw-calendar--body">
<div class="calendar" :data-is-holiday="isHoliday"> <div class="calendar" :data-is-holiday="isHoliday">
@ -67,7 +67,7 @@ export default define({
}, },
methods: { methods: {
func() { func() {
if (this.isMobile) return; if (this.platform == 'mobile') return;
if (this.props.design == 2) { if (this.props.design == 2) {
this.props.design = 0; this.props.design = 0;
} else { } else {

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="mkw-donation" :data-mobile="isMobile"> <div class="mkw-donation" :data-mobile="platform == 'mobile'">
<article> <article>
<h1>%fa:heart%%i18n:@title%</h1> <h1>%fa:heart%%i18n:@title%</h1>
<p> <p>

View File

@ -4,7 +4,7 @@
<template slot="header">%fa:rss-square%RSS</template> <template slot="header">%fa:rss-square%RSS</template>
<button slot="func" title="設定" @click="setting">%fa:cog%</button> <button slot="func" title="設定" @click="setting">%fa:cog%</button>
<div class="mkw-rss--body" :data-mobile="isMobile"> <div class="mkw-rss--body" :data-mobile="platform == 'mobile'">
<p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p> <p class="fetching" v-if="fetching">%fa:spinner .pulse .fw%%i18n:common.loading%<mk-ellipsis/></p>
<div class="feed" v-else> <div class="feed" v-else>
<a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a> <a v-for="item in items" :href="item.link" target="_blank">{{ item.title }}</a>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="mkw-slideshow" :data-mobile="isMobile"> <div class="mkw-slideshow" :data-mobile="platform == 'mobile'">
<div @click="choose"> <div @click="choose">
<p v-if="props.folder === undefined"> <p v-if="props.folder === undefined">
<template v-if="isCustomizeMode">フォルダを指定するにはカスタマイズモードを終了してください</template> <template v-if="isCustomizeMode">フォルダを指定するにはカスタマイズモードを終了してください</template>

View File

@ -47,7 +47,7 @@
:key="place" :key="place"
> >
<div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)"> <div v-for="widget in widgets[place]" class="customize-container" :key="widget.id" @contextmenu.stop.prevent="onWidgetContextmenu(widget.id)">
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true"/> <component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="desktop"/>
</div> </div>
</x-draggable> </x-draggable>
<div class="main"> <div class="main">
@ -60,7 +60,7 @@
</template> </template>
<template v-else> <template v-else>
<div v-for="place in ['left', 'right']" :class="place"> <div v-for="place in ['left', 'right']" :class="place">
<component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp"/> <component v-for="widget in widgets[place]" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" @chosen="warp" platform="desktop"/>
</div> </div>
<div class="main"> <div class="main">
<mk-post-form class="form" v-if="$store.state.settings.showPostFormOnTopOfTl"/> <mk-post-form class="form" v-if="$store.state.settings.showPostFormOnTopOfTl"/>

View File

@ -36,7 +36,7 @@ export default Vue.extend({
<style lang="stylus" scoped> <style lang="stylus" scoped>
root(isDark) root(isDark)
background isDark ? #282C37 : #fff background isDark ? #282C37 : #fff
border solid 1px rgba(#000, 0.075) border solid 1px rgba(#000, isDark ? 0.2 : 0.075)
border-radius 6px border-radius 6px
overflow hidden overflow hidden

View File

@ -1,8 +1,8 @@
<template> <template>
<div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs"> <div class="dnpfarvgbnfmyzbdquhhzyxcmstpdqzs" :class="{ naked, narrow }">
<header :class="{ indicate }"> <header :class="{ indicate }">
<slot name="header"></slot> <slot name="header"></slot>
<button ref="menu" @click="menu">%fa:caret-down%</button> <button ref="menu" @click="showMenu">%fa:caret-down%</button>
</header> </header>
<div ref="body"> <div ref="body">
<slot></slot> <slot></slot>
@ -19,6 +19,20 @@ export default Vue.extend({
id: { id: {
type: String, type: String,
required: false required: false
},
menu: {
type: Array,
required: false
},
naked: {
type: Boolean,
required: false,
default: false
},
narrow: {
type: Boolean,
required: false,
default: false
} }
}, },
@ -59,26 +73,33 @@ export default Vue.extend({
} }
}, },
menu() { showMenu() {
const items = [{
content: '%fa:arrow-left% %i18n:@swap-left%',
onClick: () => {
this.$store.dispatch('settings/swapLeftDeckColumn', this.id);
}
}, {
content: '%fa:arrow-right% %i18n:@swap-right%',
onClick: () => {
this.$store.dispatch('settings/swapRightDeckColumn', this.id);
}
}, {
content: '%fa:trash-alt R% %i18n:@remove%',
onClick: () => {
this.$store.dispatch('settings/removeDeckColumn', this.id);
}
}];
if (this.menu) {
items.unshift(null);
this.menu.reverse().forEach(i => items.unshift(i));
}
this.os.new(Menu, { this.os.new(Menu, {
source: this.$refs.menu, source: this.$refs.menu,
compact: false, compact: false,
items: [{ items
content: '%fa:arrow-left% %i18n:@swap-left%',
onClick: () => {
this.$store.dispatch('settings/swapLeftDeckColumn', this.id);
}
}, {
content: '%fa:arrow-right% %i18n:@swap-right%',
onClick: () => {
this.$store.dispatch('settings/swapRightDeckColumn', this.id);
}
}, {
content: '%fa:trash-alt R% %i18n:@remove%',
onClick: () => {
this.$store.dispatch('settings/removeDeckColumn', this.id);
}
}]
}); });
} }
} }
@ -100,6 +121,21 @@ root(isDark)
box-shadow 0 2px 16px rgba(#000, 0.1) box-shadow 0 2px 16px rgba(#000, 0.1)
overflow hidden overflow hidden
&.narrow
min-width 285px
max-width 285px
&.naked
background rgba(#000, isDark ? 0.25 : 0.1)
> header
background transparent
box-shadow none
if !isDark
> button
color #bbb
> header > header
z-index 1 z-index 1
line-height $header-height line-height $header-height

View File

@ -1,7 +1,7 @@
<template> <template>
<div> <div>
<x-column :id="id"> <x-column :id="id">
<span slot="header">%fa:bell R% %i18n:@notifications%</span> <span slot="header">%fa:bell R%%i18n:@notifications%</span>
<x-notifications/> <x-notifications/>
</x-column> </x-column>

View File

@ -2,6 +2,7 @@
<mk-ui :class="$style.root"> <mk-ui :class="$style.root">
<div class="qlvquzbjribqcaozciifydkngcwtyzje" :data-darkmode="$store.state.device.darkmode"> <div class="qlvquzbjribqcaozciifydkngcwtyzje" :data-darkmode="$store.state.device.darkmode">
<template v-for="column in columns"> <template v-for="column in columns">
<x-widgets-column v-if="column.type == 'widgets'" :key="column.id" :column="column"/>
<x-notifications-column v-if="column.type == 'notifications'" :key="column.id" :id="column.id"/> <x-notifications-column v-if="column.type == 'notifications'" :key="column.id" :id="column.id"/>
<x-tl-column v-if="column.type == 'home'" :key="column.id" :column="column"/> <x-tl-column v-if="column.type == 'home'" :key="column.id" :column="column"/>
<x-tl-column v-if="column.type == 'local'" :key="column.id" :column="column"/> <x-tl-column v-if="column.type == 'local'" :key="column.id" :column="column"/>
@ -17,6 +18,7 @@
import Vue from 'vue'; import Vue from 'vue';
import XTlColumn from './deck.tl-column.vue'; import XTlColumn from './deck.tl-column.vue';
import XNotificationsColumn from './deck.notifications-column.vue'; import XNotificationsColumn from './deck.notifications-column.vue';
import XWidgetsColumn from './deck.widgets-column.vue';
import Menu from '../../../../common/views/components/menu.vue'; import Menu from '../../../../common/views/components/menu.vue';
import MkUserListsWindow from '../../components/user-lists-window.vue'; import MkUserListsWindow from '../../components/user-lists-window.vue';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
@ -24,7 +26,8 @@ import * as uuid from 'uuid';
export default Vue.extend({ export default Vue.extend({
components: { components: {
XTlColumn, XTlColumn,
XNotificationsColumn XNotificationsColumn,
XWidgetsColumn
}, },
computed: { computed: {
columns() { columns() {
@ -110,6 +113,15 @@ export default Vue.extend({
type: 'notifications' type: 'notifications'
}); });
} }
}, {
content: '%i18n:@widgets%',
onClick: () => {
this.$store.dispatch('settings/addDeckColumn', {
id: uuid(),
type: 'widgets',
widgets: []
});
}
}] }]
}); });
} }

View File

@ -0,0 +1,152 @@
<template>
<div class="wtdtxvecapixsepjtcupubtsmometobz">
<x-column :id="column.id" :menu="menu" :naked="true" :narrow="true">
<span slot="header">%fa:calculator%%i18n:@widgets%</span>
<div class="gqpwvtwtprsbmnssnbicggtwqhmylhnq">
<template v-if="edit">
<header>
<select v-model="widgetAdderSelected">
<option value="profile">%i18n:common.widgets.profile%</option>
<option value="analog-clock">%i18n:common.widgets.analog-clock%</option>
<option value="calendar">%i18n:common.widgets.calendar%</option>
<option value="timemachine">%i18n:common.widgets.timemachine%</option>
<option value="activity">%i18n:common.widgets.activity%</option>
<option value="rss">%i18n:common.widgets.rss%</option>
<option value="trends">%i18n:common.widgets.trends%</option>
<option value="photo-stream">%i18n:common.widgets.photo-stream%</option>
<option value="slideshow">%i18n:common.widgets.slideshow%</option>
<option value="version">%i18n:common.widgets.version%</option>
<option value="broadcast">%i18n:common.widgets.broadcast%</option>
<option value="notifications">%i18n:common.widgets.notifications%</option>
<option value="users">%i18n:common.widgets.users%</option>
<option value="polls">%i18n:common.widgets.polls%</option>
<option value="post-form">%i18n:common.widgets.post-form%</option>
<option value="messaging">%i18n:common.widgets.messaging%</option>
<option value="memo">%i18n:common.widgets.memo%</option>
<option value="server">%i18n:common.widgets.server%</option>
<option value="donation">%i18n:common.widgets.donation%</option>
<option value="nav">%i18n:common.widgets.nav%</option>
<option value="tips">%i18n:common.widgets.tips%</option>
</select>
<button @click="addWidget">追加</button>
</header>
<x-draggable
:list="column.widgets"
:options="{ handle: '.handle', animation: 150 }"
@sort="onWidgetSort"
>
<div v-for="widget in column.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 @click="widgetFunc(widget.id)">
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="deck"/>
</div>
</div>
</x-draggable>
</template>
<template v-else>
<component class="widget" v-for="widget in column.widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="deck"/>
</template>
</div>
</x-column>
</div>
</template>
<script lang="ts">
import Vue from 'vue';
import XColumn from './deck.column.vue';
import * as XDraggable from 'vuedraggable';
import * as uuid from 'uuid';
export default Vue.extend({
components: {
XColumn,
XDraggable
},
props: {
column: {
type: Object,
required: true
}
},
data() {
return {
edit: false,
menu: null,
widgetAdderSelected: null
}
},
created() {
this.menu = [{
content: '%fa:cog% %i18n:@edit%',
onClick: () => {
this.edit = !this.edit;
}
}];
},
methods: {
widgetFunc(id) {
const w = this.$refs[id][0];
if (w.func) w.func();
},
onWidgetSort() {
this.saveWidgets();
},
addWidget() {
this.$store.dispatch('settings/addDeckWidget', {
id: this.column.id,
widget: {
name: this.widgetAdderSelected,
id: uuid(),
data: {}
}
});
},
removeWidget(widget) {
this.$store.dispatch('settings/removeDeckWidget', {
id: this.column.id,
widget
});
},
saveWidgets() {
this.$store.dispatch('settings/saveDeck');
}
}
});
</script>
<style lang="stylus" scoped>
@import '~const.styl'
root(isDark)
.gqpwvtwtprsbmnssnbicggtwqhmylhnq
.widget, .customize-container
margin 8px
&:first-of-type
margin-top 0
.customize-container
background #fff
> header
color isDark ? #fff : #000
.wtdtxvecapixsepjtcupubtsmometobz[data-darkmode]
root(true)
.wtdtxvecapixsepjtcupubtsmometobz:not([data-darkmode])
root(false)
</style>

View File

@ -35,13 +35,13 @@
<span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button> <span class="handle">%fa:bars%</span>{{ widget.name }}<button class="remove" @click="removeWidget(widget)">%fa:times%</button>
</header> </header>
<div @click="widgetFunc(widget.id)"> <div @click="widgetFunc(widget.id)">
<component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" :is-mobile="true"/> <component :is="`mkw-${widget.name}`" :widget="widget" :ref="widget.id" :is-customize-mode="true" platform="mobile"/>
</div> </div>
</div> </div>
</x-draggable> </x-draggable>
</template> </template>
<template v-else> <template v-else>
<component class="widget" v-for="widget in widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" :is-mobile="true"/> <component class="widget" v-for="widget in widgets" :is="`mkw-${widget.name}`" :key="widget.id" :ref="widget.id" :widget="widget" platform="mobile"/>
</template> </template>
</main> </main>
</mk-ui> </mk-ui>

View File

@ -124,13 +124,6 @@ export default (os: MiOS) => new Vuex.Store({
state.home = data; state.home = data;
}, },
setHomeWidget(state, x) {
const w = state.home.find(w => w.id == x.id);
if (w) {
w.data = x.data;
}
},
addHomeWidget(state, widget) { addHomeWidget(state, widget) {
state.home.unshift(widget); state.home.unshift(widget);
}, },
@ -139,11 +132,36 @@ export default (os: MiOS) => new Vuex.Store({
state.mobileHome = data; state.mobileHome = data;
}, },
setMobileHomeWidget(state, x) { setWidget(state, x) {
const w = state.mobileHome.find(w => w.id == x.id); let w;
if (w) {
w.data = x.data; //#region Decktop home
if (state.home) {
w = state.home.find(w => w.id == x.id);
if (w) {
w.data = x.data;
}
} }
//#endregion
//#region Mobile home
if (state.mobileHome) {
w = state.mobileHome.find(w => w.id == x.id);
if (w) {
w.data = x.data;
}
}
//#endregion
//#region Deck
if (state.deck && state.deck.columns) {
state.deck.columns.filter(c => c.type == 'widgets').forEach(c => {
c.widgets.forEach(w => {
if (w.id == x.id) w.data = x.data;
});
});
}
//#endregion
}, },
addMobileHomeWidget(state, widget) { addMobileHomeWidget(state, widget) {
@ -190,6 +208,20 @@ export default (os: MiOS) => new Vuex.Store({
return true; return true;
} }
}); });
},
addDeckWidget(state, x) {
if (state.deck.columns == null) return;
const column = state.deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.widgets.unshift(x.widget);
},
removeDeckWidget(state, x) {
if (state.deck.columns == null) return;
const column = state.deck.columns.find(c => c.id == x.id);
if (column == null) return;
column.widgets = column.widgets.filter(w => w.id != x.widget.id);
} }
}, },
@ -212,40 +244,41 @@ export default (os: MiOS) => new Vuex.Store({
} }
}, },
addDeckColumn(ctx, column) { saveDeck(ctx) {
ctx.commit('addDeckColumn', column);
os.api('i/update_client_setting', { os.api('i/update_client_setting', {
name: 'deck', name: 'deck',
value: ctx.state.deck value: ctx.state.deck
}); });
}, },
addDeckColumn(ctx, column) {
ctx.commit('addDeckColumn', column);
ctx.dispatch('saveDeck');
},
removeDeckColumn(ctx, id) { removeDeckColumn(ctx, id) {
ctx.commit('removeDeckColumn', id); ctx.commit('removeDeckColumn', id);
ctx.dispatch('saveDeck');
os.api('i/update_client_setting', {
name: 'deck',
value: ctx.state.deck
});
}, },
swapLeftDeckColumn(ctx, id) { swapLeftDeckColumn(ctx, id) {
ctx.commit('swapLeftDeckColumn', id); ctx.commit('swapLeftDeckColumn', id);
ctx.dispatch('saveDeck');
os.api('i/update_client_setting', {
name: 'deck',
value: ctx.state.deck
});
}, },
swapRightDeckColumn(ctx, id) { swapRightDeckColumn(ctx, id) {
ctx.commit('swapRightDeckColumn', id); ctx.commit('swapRightDeckColumn', id);
ctx.dispatch('saveDeck');
},
os.api('i/update_client_setting', { addDeckWidget(ctx, x) {
name: 'deck', ctx.commit('addDeckWidget', x);
value: ctx.state.deck ctx.dispatch('saveDeck');
}); },
removeDeckWidget(ctx, x) {
ctx.commit('removeDeckWidget', x);
ctx.dispatch('saveDeck');
}, },
addHomeWidget(ctx, widget) { addHomeWidget(ctx, widget) {

View File

@ -189,6 +189,11 @@ const endpoints: Endpoint[] = [
withCredential: true, withCredential: true,
secure: true secure: true
}, },
{
name: 'i/update_widget',
withCredential: true,
secure: true
},
{ {
name: 'i/change_password', name: 'i/change_password',
withCredential: true, withCredential: true,

View File

@ -1,6 +1,3 @@
/**
* Module dependencies
*/
import $ from 'cafy'; import $ from 'cafy';
import User from '../../../../models/user'; import User from '../../../../models/user';
import event from '../../../../publishers/stream'; import event from '../../../../publishers/stream';
@ -13,50 +10,16 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
.have('id', $.str) .have('id', $.str)
.have('place', $.str) .have('place', $.str)
.have('data', $.obj)) .have('data', $.obj))
.optional()
.get(params.home); .get(params.home);
if (homeErr) return rej('invalid home param'); if (homeErr) return rej('invalid home param');
// Get 'id' parameter await User.update(user._id, {
const [id, idErr] = $.str.optional().get(params.id); $set: {
if (idErr) return rej('invalid id param'); 'clientSettings.home': home
}
});
// Get 'data' parameter res();
const [data, dataErr] = $.obj.optional().get(params.data);
if (dataErr) return rej('invalid data param');
if (home) { event(user._id, 'home_updated', home);
await User.update(user._id, {
$set: {
'clientSettings.home': home
}
});
res();
event(user._id, 'home_updated', {
home
});
} else {
if (id == null && data == null) return rej('you need to set id and data params if home param unset');
const _home = user.clientSettings.home;
const widget = _home.find(w => w.id == id);
if (widget == null) return rej('widget not found');
widget.data = data;
await User.update(user._id, {
$set: {
'clientSettings.home': _home
}
});
res();
event(user._id, 'home_updated', {
id, data
});
}
}); });

View File

@ -1,6 +1,3 @@
/**
* Module dependencies
*/
import $ from 'cafy'; import $ from 'cafy';
import User from '../../../../models/user'; import User from '../../../../models/user';
import event from '../../../../publishers/stream'; import event from '../../../../publishers/stream';
@ -12,49 +9,16 @@ module.exports = async (params, user) => new Promise(async (res, rej) => {
.have('name', $.str) .have('name', $.str)
.have('id', $.str) .have('id', $.str)
.have('data', $.obj)) .have('data', $.obj))
.optional().get(params.home); .get(params.home);
if (homeErr) return rej('invalid home param'); if (homeErr) return rej('invalid home param');
// Get 'id' parameter await User.update(user._id, {
const [id, idErr] = $.str.optional().get(params.id); $set: {
if (idErr) return rej('invalid id param'); 'clientSettings.mobileHome': home
}
});
// Get 'data' parameter res();
const [data, dataErr] = $.obj.optional().get(params.data);
if (dataErr) return rej('invalid data param');
if (home) { event(user._id, 'mobile_home_updated', home);
await User.update(user._id, {
$set: {
'clientSettings.mobileHome': home
}
});
res();
event(user._id, 'mobile_home_updated', {
home
});
} else {
if (id == null && data == null) return rej('you need to set id and data params if home param unset');
const _home = user.clientSettings.mobileHome || [];
const widget = _home.find(w => w.id == id);
if (widget == null) return rej('widget not found');
widget.data = data;
await User.update(user._id, {
$set: {
'clientSettings.mobileHome': _home
}
});
res();
event(user._id, 'mobile_home_updated', {
id, data
});
}
}); });

View File

@ -0,0 +1,79 @@
import $ from 'cafy';
import User from '../../../../models/user';
import event from '../../../../publishers/stream';
module.exports = async (params, user) => new Promise(async (res, rej) => {
// Get 'id' parameter
const [id, idErr] = $.str.get(params.id);
if (idErr) return rej('invalid id param');
// Get 'data' parameter
const [data, dataErr] = $.obj.get(params.data);
if (dataErr) return rej('invalid data param');
if (id == null && data == null) return rej('you need to set id and data params if home param unset');
let widget;
//#region Desktop home
if (widget == null && user.clientSettings.home) {
const desktopHome = user.clientSettings.home;
widget = desktopHome.find(w => w.id == id);
if (widget) {
widget.data = data;
await User.update(user._id, {
$set: {
'clientSettings.home': desktopHome
}
});
}
}
//#endregion
//#region Mobile home
if (widget == null && user.clientSettings.mobileHome) {
const mobileHome = user.clientSettings.mobileHome;
widget = mobileHome.find(w => w.id == id);
if (widget) {
widget.data = data;
await User.update(user._id, {
$set: {
'clientSettings.mobileHome': mobileHome
}
});
}
}
//#endregion
//#region Deck
if (widget == null && user.clientSettings.deck && user.clientSettings.deck.columns) {
const deck = user.clientSettings.deck;
deck.columns.filter(c => c.type == 'widgets').forEach(c => {
c.widgets.forEach(w => {
if (w.id == id) widget = w;
});
});
if (widget) {
widget.data = data;
await User.update(user._id, {
$set: {
'clientSettings.deck': deck
}
});
}
}
//#endregion
if (widget) {
event(user._id, 'widgetUpdated', {
id, data
});
res();
} else {
rej('widget not found');
}
});