import Vuex from 'vuex'; import createPersistedState from 'vuex-persistedstate'; import * as nestedProperty from 'nested-property'; import MiOS from './mios'; const defaultSettings = { tutorial: 0, keepCw: false, showFullAcct: false, rememberNoteVisibility: false, defaultNoteVisibility: 'public', defaultNoteLocalOnly: false, uploadFolder: null, pastedFileName: 'yyyy-MM-dd HH-mm-ss [{{number}}]', memo: null, reactions: ['👍', '❤️', '😆', '🤔', '😮', '🎉', '💢', '😥', '😇', '🍮'], }; const defaultDeviceUserSettings = { visibility: 'public', localOnly: false, widgets: [], tl: { src: 'home' }, }; const defaultDeviceSettings = { lang: null, loadRawImages: false, alwaysShowNsfw: false, useOsNativeEmojis: false, autoReload: false, accounts: [], recentEmojis: [], themes: [], theme: 'light', animation: true, animatedMfm: true, imageNewTab: false, userData: {}, }; function copy(data: T): T { return JSON.parse(JSON.stringify(data)); } export default (os: MiOS) => new Vuex.Store({ plugins: [createPersistedState({ paths: ['i', 'device', 'deviceUser', 'settings', 'instance'] })], state: { i: null, }, getters: { isSignedIn: state => state.i != null, }, mutations: { updateI(state, x) { state.i = x; }, updateIKeyValue(state, x) { state.i[x.key] = x.value; }, }, actions: { async login(ctx, i) { ctx.commit('updateI', i); ctx.commit('settings/init', i.clientData); ctx.commit('deviceUser/init', ctx.state.device.userData[i.id] || {}); await ctx.dispatch('addAcount', { id: i.id, i: localStorage.getItem('i') }); }, addAcount(ctx, info) { if (!ctx.state.device.accounts.some(x => x.id === info.id)) { ctx.commit('device/set', { key: 'accounts', value: ctx.state.device.accounts.concat([{ id: info.id, token: info.i }]) }); } }, logout(ctx) { ctx.commit('device/setUserData', { userId: ctx.state.i.id, data: ctx.state.deviceUser }); ctx.commit('updateI', null); ctx.commit('settings/init', {}); ctx.commit('deviceUser/init', {}); localStorage.removeItem('i'); }, async switchAccount(ctx, i) { ctx.commit('device/setUserData', { userId: ctx.state.i.id, data: ctx.state.deviceUser }); localStorage.setItem('i', i.token); await ctx.dispatch('login', i); }, mergeMe(ctx, me) { for (const [key, value] of Object.entries(me)) { ctx.commit('updateIKeyValue', { key, value }); } if (me.clientData) { ctx.commit('settings/init', me.clientData); } }, }, 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: { namespaced: true, state: defaultDeviceSettings, mutations: { set(state, x: { key: string; value: any }) { state[x.key] = x.value; }, setUserData(state, x: { userId: string; data: any }) { state.userData[x.userId] = copy(x.data); }, } }, deviceUser: { namespaced: true, state: defaultDeviceUserSettings, mutations: { init(state, x) { for (const [key, value] of Object.entries(defaultDeviceUserSettings)) { if (x[key]) { state[key] = x[key]; } else { state[key] = value; } } }, set(state, x: { key: string; value: any }) { state[x.key] = x.value; }, setTl(state, x) { state.tl = { src: x.src, arg: x.arg }; }, setVisibility(state, visibility) { state.visibility = visibility; }, setLocalOnly(state, localOnly) { state.localOnly = localOnly; }, setWidgets(state, widgets) { state.widgets = widgets; }, addWidget(state, widget) { state.widgets.unshift(widget); }, removeWidget(state, widget) { state.widgets = state.widgets.filter(w => w.id != widget.id); }, updateWidget(state, x) { const w = state.widgets.find(w => w.id == x.id); if (w) { w.data = x.data; } }, } }, settings: { namespaced: true, state: defaultSettings, mutations: { set(state, x: { key: string; value: any }) { nestedProperty.set(state, x.key, x.value); }, init(state, x) { for (const [key, value] of Object.entries(defaultSettings)) { if (x[key]) { state[key] = x[key]; } else { state[key] = value; } } }, }, actions: { set(ctx, x) { ctx.commit('set', x); if (ctx.rootGetters.isSignedIn) { os.api('i/update-client-setting', { name: x.key, value: x.value }); } }, } } } });