なんかもうめっちゃ変えた

Resolve #5846
This commit is contained in:
syuilo 2020-02-10 23:17:42 +09:00
parent 9cd267fee5
commit 2511114c28
20 changed files with 173 additions and 221 deletions

View file

@ -376,6 +376,7 @@ next: "次"
retype: "再入力" retype: "再入力"
noteOf: "{user}のノート" noteOf: "{user}のノート"
inviteToGroup: "グループに招待" inviteToGroup: "グループに招待"
maxNoteTextLength: "ノートの文字数制限"
_tutorial: _tutorial:
title: "Misskeyの使い方" title: "Misskeyの使い方"

View file

@ -143,7 +143,7 @@ export default Vue.extend({
this.setPosition(); this.setPosition();
//#region Construct Emoji DB //#region Construct Emoji DB
const customEmojis = (this.$root.getMetaSync() || { emojis: [] }).emojis || []; const customEmojis = this.$store.state.instance.meta.emojis;
const emojiDefinitions: EmojiDef[] = []; const emojiDefinitions: EmojiDef[] = [];
for (const x of customEmojis) { for (const x of customEmojis) {

View file

@ -140,7 +140,7 @@ export default Vue.extend({
}, },
created() { created() {
let local = (this.$root.getMetaSync() || { emojis: [] }).emojis || []; let local = this.$store.state.instance.meta.emojis;
local = groupByX(local, (x: any) => x.category || ''); local = groupByX(local, (x: any) => x.category || '');
this.customEmojis = local; this.customEmojis = local;
}, },

View file

@ -55,13 +55,21 @@ export default Vue.extend({
useOsDefaultEmojis(): boolean { useOsDefaultEmojis(): boolean {
return this.$store.state.device.useOsDefaultEmojis && !this.isReaction; return this.$store.state.device.useOsDefaultEmojis && !this.isReaction;
},
ce() {
let ce = [];
if (this.customEmojis) ce = ce.concat(this.customEmojis);
if (this.$store.state.instance.meta && this.$store.state.instance.meta.emojis) ce = ce.concat(this.$store.state.instance.meta.emojis);
return ce;
} }
}, },
watch: { watch: {
customEmojis() { ce: {
handler() {
if (this.name) { if (this.name) {
const customEmoji = this.customEmojis.find(x => x.name == this.name); const customEmoji = this.ce.find(x => x.name == this.name);
if (customEmoji) { if (customEmoji) {
this.customEmoji = customEmoji; this.customEmoji = customEmoji;
this.url = this.$store.state.device.disableShowingAnimatedImages this.url = this.$store.state.device.disableShowingAnimatedImages
@ -70,23 +78,12 @@ export default Vue.extend({
} }
} }
}, },
immediate: true
},
}, },
created() { created() {
if (this.name) { if (!this.name) {
const customEmoji = this.customEmojis.find(x => x.name == this.name);
if (customEmoji) {
this.customEmoji = customEmoji;
this.url = this.$store.state.device.disableShowingAnimatedImages
? getStaticImageUrl(customEmoji.url)
: customEmoji.url;
} else {
//const emoji = lib[this.name];
//if (emoji) {
// this.char = emoji.char;
//}
}
} else {
this.char = this.emoji; this.char = this.emoji;
} }

View file

@ -234,7 +234,6 @@ export default Vue.component('misskey-flavored-markdown', {
} }
case 'emoji': { case 'emoji': {
const customEmojis = (this.$root.getMetaSync() || { emojis: [] }).emojis || [];
return [createElement('mk-emoji', { return [createElement('mk-emoji', {
key: Math.random(), key: Math.random(),
attrs: { attrs: {
@ -242,7 +241,7 @@ export default Vue.component('misskey-flavored-markdown', {
name: token.node.props.name name: token.node.props.name
}, },
props: { props: {
customEmojis: this.customEmojis || customEmojis, customEmojis: this.customEmojis,
normal: this.plain normal: this.plain
} }
})]; })];

View file

@ -8,7 +8,7 @@
<header> <header>
<button class="cancel _button" @click="cancel"><fa :icon="faTimes"/></button> <button class="cancel _button" @click="cancel"><fa :icon="faTimes"/></button>
<div> <div>
<span class="text-count" :class="{ over: trimmedLength(text) > 500 }">{{ 500 - trimmedLength(text) }}</span> <span class="text-count" :class="{ over: trimmedLength(text) > max }">{{ max - trimmedLength(text) }}</span>
<button class="_button visibility" @click="setVisibility" ref="visibilityButton"> <button class="_button visibility" @click="setVisibility" ref="visibilityButton">
<span v-if="visibility === 'public'"><fa :icon="faGlobe"/></span> <span v-if="visibility === 'public'"><fa :icon="faGlobe"/></span>
<span v-if="visibility === 'home'"><fa :icon="faHome"/></span> <span v-if="visibility === 'home'"><fa :icon="faHome"/></span>
@ -172,8 +172,12 @@ export default Vue.extend({
canPost(): boolean { canPost(): boolean {
return !this.posting && return !this.posting &&
(1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) && (1 <= this.text.length || 1 <= this.files.length || this.poll || this.renote) &&
(length(this.text.trim()) <= 500) && (length(this.text.trim()) <= this.max) &&
(!this.poll || this.pollChoices.length >= 2); (!this.poll || this.pollChoices.length >= 2);
},
max(): number {
return this.$store.state.instance.meta ? this.$store.state.instance.meta.maxNoteTextLength : 1000;
} }
}, },

View file

@ -1,5 +1,5 @@
<template> <template>
<mk-emoji :emoji="reaction.startsWith(':') ? null : reaction" :name="reaction.startsWith(':') ? reaction.substr(1, reaction.length - 2) : null" :is-reaction="true" :custom-emojis="customEmojis" :normal="true" :no-style="noStyle"/> <mk-emoji :emoji="reaction.startsWith(':') ? null : reaction" :name="reaction.startsWith(':') ? reaction.substr(1, reaction.length - 2) : null" :is-reaction="true" :normal="true" :no-style="noStyle"/>
</template> </template>
<script lang="ts"> <script lang="ts">
@ -18,15 +18,5 @@ export default Vue.extend({
default: false default: false
}, },
}, },
data() {
return {
customEmojis: []
};
},
created() {
this.$root.getMeta().then(meta => {
if (meta && meta.emojis) this.customEmojis = meta.emojis;
});
},
}); });
</script> </script>

View file

@ -82,7 +82,6 @@ export default Vue.extend({
token: '', token: '',
apiUrl, apiUrl,
host: toUnicode(host), host: toUnicode(host),
meta: null,
totpLogin: false, totpLogin: false,
credential: null, credential: null,
challengeData: null, challengeData: null,
@ -91,11 +90,13 @@ export default Vue.extend({
}; };
}, },
created() { computed: {
this.$root.getMeta().then(meta => { meta() {
this.meta = meta; return this.$store.state.instance.meta;
}); },
},
created() {
if (this.autoSet) { if (this.autoSet) {
this.$once('login', res => { this.$once('login', res => {
localStorage.setItem('i', res.i); localStorage.setItem('i', res.i);

View file

@ -79,7 +79,6 @@ export default Vue.extend({
usernameState: null, usernameState: null,
passwordStrength: '', passwordStrength: '',
passwordRetypeState: null, passwordRetypeState: null,
meta: {},
submitting: false, submitting: false,
ToSAgreement: false, ToSAgreement: false,
faLock, faExclamationTriangle, faSpinner, faCheck faLock, faExclamationTriangle, faSpinner, faCheck
@ -87,6 +86,10 @@ export default Vue.extend({
}, },
computed: { computed: {
meta() {
return this.$store.state.instance.meta;
},
shouldShowProfileUrl(): boolean { shouldShowProfileUrl(): boolean {
return (this.username != '' && return (this.username != '' &&
this.usernameState != 'invalid-format' && this.usernameState != 'invalid-format' &&
@ -95,12 +98,6 @@ export default Vue.extend({
} }
}, },
created() {
this.$root.getMeta().then(meta => {
this.meta = meta;
});
},
mounted() { mounted() {
const head = document.getElementsByTagName('head')[0]; const head = document.getElementsByTagName('head')[0];
const script = document.createElement('script'); const script = document.createElement('script');

View file

@ -157,8 +157,6 @@ os.init(async () => {
}, },
methods: { methods: {
api: os.api, api: os.api,
getMeta: os.getMeta,
getMetaSync: os.getMetaSync,
signout: os.signout, signout: os.signout,
new(vm, props) { new(vm, props) {
const x = new vm({ const x = new vm({

View file

@ -17,16 +17,6 @@ let pending = 0;
* Misskey Operating System * Misskey Operating System
*/ */
export default class MiOS extends EventEmitter { export default class MiOS extends EventEmitter {
/**
* Misskeyの /meta
*/
private meta: {
data: { [x: string]: any };
chachedAt: Date;
};
private isMetaFetching = false;
public app: Vue; public app: Vue;
public store: ReturnType<typeof initStore>; public store: ReturnType<typeof initStore>;
@ -88,7 +78,7 @@ export default class MiOS extends EventEmitter {
// When failure // When failure
.catch(() => { .catch(() => {
// Render the error screen // Render the error screen
document.body.innerHTML = '<div id="err">Error</div>'; document.body.innerHTML = '<div id="err">Oops!</div>';
Progress.done(); Progress.done();
}); });
@ -107,9 +97,9 @@ export default class MiOS extends EventEmitter {
// Finish init // Finish init
callback(); callback();
this.store.dispatch('instance/fetch').then(() => {
// Init service worker // Init service worker
this.getMeta().then(data => { if (this.store.state.instance.meta.swPublickey) this.registerSw(this.store.state.instance.meta.swPublickey);
if (data.swPublickey) this.registerSw(data.swPublickey);
}); });
}; };
@ -350,49 +340,6 @@ export default class MiOS extends EventEmitter {
return promise; return promise;
} }
/**
* Misskeyのメタ情報を取得します
*/
@autobind
public getMetaSync() {
return this.meta ? this.meta.data : null;
}
/**
* Misskeyのメタ情報を取得します
* @param force
*/
@autobind
public getMeta(force = false) {
return new Promise<{ [x: string]: any }>(async (res, rej) => {
if (this.isMetaFetching) {
this.once('_meta_fetched_', () => {
res(this.meta.data);
});
return;
}
const expire = 1000 * 60; // 1min
// forceが有効, meta情報を保持していない or 期限切れ
if (force || this.meta == null || Date.now() - this.meta.chachedAt.getTime() > expire) {
this.isMetaFetching = true;
const meta = await this.api('meta', {
detail: false
});
this.meta = {
data: meta,
chachedAt: new Date()
};
this.isMetaFetching = false;
this.emit('_meta_fetched_');
res(meta);
} else {
res(this.meta.data);
}
});
}
} }
/** /**

View file

@ -84,18 +84,19 @@ export default Vue.extend({
data() { data() {
return { return {
version, version,
meta: null,
stats: null, stats: null,
serverInfo: null, serverInfo: null,
faInfoCircle faInfoCircle
} }
}, },
created() { computed: {
this.$root.getMeta().then(meta => { meta() {
this.meta = meta; return this.$store.state.instance.meta;
}); },
},
created() {
this.$root.api('stats').then(res => { this.$root.api('stats').then(res => {
this.stats = res; this.stats = res;
}); });

View file

@ -115,13 +115,15 @@ export default Vue.extend({
tagsLocal: [], tagsLocal: [],
tagsRemote: [], tagsRemote: [],
stats: null, stats: null,
meta: null,
num: Vue.filter('number'), num: Vue.filter('number'),
faBookmark, faChartLine, faCommentAlt, faPlus, faHashtag, faRocket faBookmark, faChartLine, faCommentAlt, faPlus, faHashtag, faRocket
}; };
}, },
computed: { computed: {
meta() {
return this.$store.state.instance.meta;
},
tagUsers(): any { tagUsers(): any {
return { return {
endpoint: 'hashtags/users', endpoint: 'hashtags/users',
@ -159,9 +161,6 @@ export default Vue.extend({
this.$root.api('stats').then(stats => { this.$root.api('stats').then(stats => {
this.stats = stats; this.stats = stats;
}); });
this.$root.getMeta().then(meta => {
this.meta = meta;
});
}, },
}); });
</script> </script>

View file

@ -83,15 +83,6 @@ export default Vue.extend({
}, },
created() { created() {
this.$root.getMeta().then((meta: Record<string, any>) => {
if (!(
this.enableGlobalTimeline = !meta.disableGlobalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin
) && this.src === 'global') this.src = 'local';
if (!(
this.enableLocalTimeline = !meta.disableLocalTimeline || this.$store.state.i.isModerator || this.$store.state.i.isAdmin
) && ['local', 'social'].includes(this.src)) this.src = 'home';
});
this.src = this.$store.state.deviceUser.tl.src; this.src = this.$store.state.deviceUser.tl.src;
if (this.src === 'list') { if (this.src === 'list') {
this.list = this.$store.state.deviceUser.tl.arg; this.list = this.$store.state.deviceUser.tl.arg;

View file

@ -1,10 +1,10 @@
<template> <template>
<div class="rsqzvsbo"> <div class="rsqzvsbo">
<div class="_panel about"> <div class="_panel about" v-if="meta">
<div class="banner" :style="{ backgroundImage: `url(${ banner })` }"></div> <div class="banner" :style="{ backgroundImage: `url(${ meta.bannerUrl })` }"></div>
<div class="body"> <div class="body">
<h1 class="name" v-html="name || host"></h1> <h1 class="name" v-html="meta.name || host"></h1>
<div class="desc" v-html="description || $t('introMisskey')"></div> <div class="desc" v-html="meta.description || $t('introMisskey')"></div>
<mk-button @click="signup()" style="display: inline-block; margin-right: 16px;" primary>{{ $t('signup') }}</mk-button> <mk-button @click="signup()" style="display: inline-block; margin-right: 16px;" primary>{{ $t('signup') }}</mk-button>
<mk-button @click="signin()" style="display: inline-block;">{{ $t('login') }}</mk-button> <mk-button @click="signin()" style="display: inline-block;">{{ $t('login') }}</mk-button>
</div> </div>
@ -39,23 +39,16 @@ export default Vue.extend({
noPaging: true, noPaging: true,
}, },
host: toUnicode(host), host: toUnicode(host),
meta: null,
name: null,
description: null,
banner: null,
announcements: [],
}; };
}, },
created() { computed: {
this.$root.getMeta().then(meta => { meta() {
this.meta = meta; return this.$store.state.instance.meta;
this.name = meta.name; },
this.description = meta.description; },
this.announcements = meta.announcements;
this.banner = meta.bannerUrl;
});
created() {
this.$root.api('stats').then(stats => { this.$root.api('stats').then(stats => {
this.stats = stats; this.stats = stats;
}); });

View file

@ -20,15 +20,14 @@ export default Vue.extend({
data() { data() {
return { return {
meta: null,
instanceName: getInstanceName(), instanceName: getInstanceName(),
} }
}, },
created() { computed: {
this.$root.getMeta().then(meta => { meta() {
this.meta = meta; return this.$store.state.instance.meta;
}); },
} },
}); });
</script> </script>

View file

@ -98,7 +98,7 @@
<div class="operations"> <div class="operations">
<span class="label">{{ $t('operations') }}</span> <span class="label">{{ $t('operations') }}</span>
<mk-switch v-model="isSuspended" class="switch">{{ $t('stopActivityDelivery') }}</mk-switch> <mk-switch v-model="isSuspended" class="switch">{{ $t('stopActivityDelivery') }}</mk-switch>
<mk-switch v-model="isBlocked" class="switch">{{ $t('blockThisInstance') }}</mk-switch> <mk-switch :value="isBlocked" class="switch" @change="changeBlock">{{ $t('blockThisInstance') }}</mk-switch>
</div> </div>
<details class="metadata"> <details class="metadata">
<summary class="label">{{ $t('metadata') }}</summary> <summary class="label">{{ $t('metadata') }}</summary>
@ -147,9 +147,7 @@ export default Vue.extend({
data() { data() {
return { return {
meta: null, isSuspended: this.instance.isSuspended,
isSuspended: false,
isBlocked: false,
now: null, now: null,
chart: null, chart: null,
chartInstance: null, chartInstance: null,
@ -184,6 +182,14 @@ export default Vue.extend({
null; null;
return stats; return stats;
},
meta() {
return this.$store.state.instance.meta;
},
isBlocked() {
return this.meta && this.meta.blockedHosts.includes(this.instance.host);
} }
}, },
@ -195,12 +201,6 @@ export default Vue.extend({
}); });
}, },
isBlocked() {
this.$root.api('admin/update-meta', {
blockedHosts: this.isBlocked ? this.meta.blockedHosts.concat([this.instance.host]) : this.meta.blockedHosts.filter(x => x !== this.instance.host)
});
},
chartSrc() { chartSrc() {
this.renderChart(); this.renderChart();
}, },
@ -211,12 +211,6 @@ export default Vue.extend({
}, },
async created() { async created() {
this.$root.getMeta().then(meta => {
this.meta = meta;
this.isSuspended = this.instance.isSuspended;
this.isBlocked = this.meta.blockedHosts.includes(this.instance.host);
});
this.now = new Date(); this.now = new Date();
const [perHour, perDay] = await Promise.all([ const [perHour, perDay] = await Promise.all([
@ -235,6 +229,12 @@ export default Vue.extend({
}, },
methods: { methods: {
changeBlock(e) {
this.$root.api('admin/update-meta', {
blockedHosts: this.isBlocked ? this.meta.blockedHosts.concat([this.instance.host]) : this.meta.blockedHosts.filter(x => x !== this.instance.host)
});
},
setSrc(src) { setSrc(src) {
this.chartSrc = src; this.chartSrc = src;
}, },

View file

@ -20,6 +20,9 @@
</section> </section>
<section class="_card info"> <section class="_card info">
<div class="_content">
<mk-input v-model="maxNoteTextLength" type="number" :save="() => save()" style="margin:0;"><template #icon><fa :icon="faPencilAlt"/></template>{{ $t('maxNoteTextLength') }}</mk-input>
</div>
<div class="_content"> <div class="_content">
<mk-switch v-model="enableLocalTimeline" @change="save()">{{ $t('enableLocalTimeline') }}</mk-switch> <mk-switch v-model="enableLocalTimeline" @change="save()">{{ $t('enableLocalTimeline') }}</mk-switch>
<mk-switch v-model="enableGlobalTimeline" @change="save()">{{ $t('enableGlobalTimeline') }}</mk-switch> <mk-switch v-model="enableGlobalTimeline" @change="save()">{{ $t('enableGlobalTimeline') }}</mk-switch>
@ -171,7 +174,7 @@
<script lang="ts"> <script lang="ts">
import Vue from 'vue'; import Vue from 'vue';
import { faShareAlt, faGhost, faCog, faPlus, faCloud, faInfoCircle, faBan, faSave, faServer, faLink, faThumbtack, faUser, faShieldAlt, faKey, faBolt } from '@fortawesome/free-solid-svg-icons'; import { faPencilAlt, faShareAlt, faGhost, faCog, faPlus, faCloud, faInfoCircle, faBan, faSave, faServer, faLink, faThumbtack, faUser, faShieldAlt, faKey, faBolt } from '@fortawesome/free-solid-svg-icons';
import { faTrashAlt, faEnvelope } from '@fortawesome/free-regular-svg-icons'; import { faTrashAlt, faEnvelope } from '@fortawesome/free-regular-svg-icons';
import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons'; import { faTwitter, faDiscord, faGithub } from '@fortawesome/free-brands-svg-icons';
import MkButton from '../../components/ui/button.vue'; import MkButton from '../../components/ui/button.vue';
@ -205,7 +208,6 @@ export default Vue.extend({
return { return {
version, version,
url, url,
meta: null,
stats: null, stats: null,
serverInfo: null, serverInfo: null,
proxyAccount: null, proxyAccount: null,
@ -223,6 +225,7 @@ export default Vue.extend({
tosUrl: null, tosUrl: null,
bannerUrl: null, bannerUrl: null,
iconUrl: null, iconUrl: null,
maxNoteTextLength: 0,
enableRegistration: false, enableRegistration: false,
enableLocalTimeline: false, enableLocalTimeline: false,
enableGlobalTimeline: false, enableGlobalTimeline: false,
@ -241,13 +244,17 @@ export default Vue.extend({
enableDiscordIntegration: false, enableDiscordIntegration: false,
discordClientId: null, discordClientId: null,
discordClientSecret: null, discordClientSecret: null,
faTwitter, faDiscord, faGithub, faShareAlt, faTrashAlt, faGhost, faCog, faPlus, faCloud, faInfoCircle, faBan, faSave, faServer, faLink, faEnvelope, faThumbtack, faUser, faShieldAlt, faKey, faBolt faPencilAlt, faTwitter, faDiscord, faGithub, faShareAlt, faTrashAlt, faGhost, faCog, faPlus, faCloud, faInfoCircle, faBan, faSave, faServer, faLink, faEnvelope, faThumbtack, faUser, faShieldAlt, faKey, faBolt
} }
}, },
computed: {
meta() {
return this.$store.state.instance.meta;
},
},
created() { created() {
this.$root.getMeta().then(meta => {
this.meta = meta;
this.name = this.meta.name; this.name = this.meta.name;
this.description = this.meta.description; this.description = this.meta.description;
this.tosUrl = this.meta.tosUrl; this.tosUrl = this.meta.tosUrl;
@ -255,6 +262,7 @@ export default Vue.extend({
this.iconUrl = this.meta.iconUrl; this.iconUrl = this.meta.iconUrl;
this.maintainerName = this.meta.maintainerName; this.maintainerName = this.meta.maintainerName;
this.maintainerEmail = this.meta.maintainerEmail; this.maintainerEmail = this.meta.maintainerEmail;
this.maxNoteTextLength = this.meta.maxNoteTextLength;
this.enableRegistration = !this.meta.disableRegistration; this.enableRegistration = !this.meta.disableRegistration;
this.enableLocalTimeline = !this.meta.disableLocalTimeline; this.enableLocalTimeline = !this.meta.disableLocalTimeline;
this.enableGlobalTimeline = !this.meta.disableGlobalTimeline; this.enableGlobalTimeline = !this.meta.disableGlobalTimeline;
@ -286,7 +294,6 @@ export default Vue.extend({
this.proxyAccount = proxyAccount; this.proxyAccount = proxyAccount;
}); });
} }
});
this.$root.api('admin/server-info').then(res => { this.$root.api('admin/server-info').then(res => {
this.serverInfo = res; this.serverInfo = res;
@ -347,6 +354,7 @@ export default Vue.extend({
iconUrl: this.iconUrl, iconUrl: this.iconUrl,
maintainerName: this.maintainerName, maintainerName: this.maintainerName,
maintainerEmail: this.maintainerEmail, maintainerEmail: this.maintainerEmail,
maxNoteTextLength: this.maxNoteTextLength,
disableRegistration: !this.enableRegistration, disableRegistration: !this.enableRegistration,
disableLocalTimeline: !this.enableLocalTimeline, disableLocalTimeline: !this.enableLocalTimeline,
disableGlobalTimeline: !this.enableGlobalTimeline, disableGlobalTimeline: !this.enableGlobalTimeline,
@ -373,6 +381,7 @@ export default Vue.extend({
discordClientId: this.discordClientId, discordClientId: this.discordClientId,
discordClientSecret: this.discordClientSecret, discordClientSecret: this.discordClientSecret,
}).then(() => { }).then(() => {
this.$store.dispatch('instance/fetch');
if (withDialog) { if (withDialog) {
this.$root.dialog({ this.$root.dialog({
type: 'success', type: 'success',

View file

@ -56,15 +56,17 @@ export default Vue.extend({
computed: { computed: {
integrations() { integrations() {
return this.$store.state.i.integrations; return this.$store.state.i.integrations;
} },
meta() {
return this.$store.state.instance.meta;
},
}, },
created() { created() {
this.$root.getMeta().then(meta => { this.enableTwitterIntegration = this.meta.enableTwitterIntegration;
this.enableTwitterIntegration = meta.enableTwitterIntegration; this.enableDiscordIntegration = this.meta.enableDiscordIntegration;
this.enableDiscordIntegration = meta.enableDiscordIntegration; this.enableGithubIntegration = this.meta.enableGithubIntegration;
this.enableGithubIntegration = meta.enableGithubIntegration;
});
}, },
mounted() { mounted() {

View file

@ -41,13 +41,13 @@ const defaultDeviceSettings = {
userData: {}, userData: {},
}; };
function copy(data) { function copy<T>(data: T): T {
return JSON.parse(JSON.stringify(data)); return JSON.parse(JSON.stringify(data));
} }
export default (os: MiOS) => new Vuex.Store({ export default (os: MiOS) => new Vuex.Store({
plugins: [createPersistedState({ plugins: [createPersistedState({
paths: ['i', 'device', 'deviceUser', 'settings'] paths: ['i', 'device', 'deviceUser', 'settings', 'instance']
})], })],
state: { state: {
@ -111,6 +111,30 @@ export default (os: MiOS) => new Vuex.Store({
}, },
modules: { modules: {
instance: {
namespaced: true,
state: {
meta: null
},
mutations: {
set(state, meta) {
state.meta = meta;
},
},
actions: {
async fetch(ctx) {
const meta = await os.api('meta', {
detail: false
});
ctx.commit('set', meta);
}
}
},
device: { device: {
namespaced: true, namespaced: true,