akkoma-fe/src/boot/after_store.js

325 lines
11 KiB
JavaScript
Raw Normal View History

2018-10-26 13:16:23 +00:00
import Vue from 'vue'
import VueRouter from 'vue-router'
import routes from './routes'
2018-10-26 13:16:23 +00:00
import App from '../App.vue'
2019-04-01 19:41:34 +00:00
import { windowWidth } from '../services/window_utils/window_utils'
import { getOrCreateApp, getClientToken } from '../services/new_api/oauth.js'
import backendInteractorService from '../services/backend_interactor_service/backend_interactor_service.js'
import { CURRENT_VERSION } from '../services/theme_data/theme_data.service.js'
import { applyTheme } from '../services/style_setter/style_setter.js'
2018-10-26 13:16:23 +00:00
2019-03-13 10:57:30 +00:00
const getStatusnetConfig = async ({ store }) => {
try {
const res = await window.fetch('/api/statusnet/config.json')
2019-03-13 11:41:39 +00:00
if (res.ok) {
const data = await res.json()
const { name, closed: registrationClosed, textlimit, uploadlimit, server, vapidPublicKey, safeDMMentionsEnabled } = data.site
2018-10-26 13:16:23 +00:00
store.dispatch('setInstanceOption', { name: 'name', value: name })
store.dispatch('setInstanceOption', { name: 'registrationOpen', value: (registrationClosed === '0') })
store.dispatch('setInstanceOption', { name: 'textlimit', value: parseInt(textlimit) })
store.dispatch('setInstanceOption', { name: 'server', value: server })
store.dispatch('setInstanceOption', { name: 'safeDM', value: safeDMMentionsEnabled !== '0' })
2018-10-26 13:16:23 +00:00
2018-12-18 18:26:14 +00:00
// TODO: default values for this stuff, added if to not make it break on
// my dev config out of the box.
if (uploadlimit) {
store.dispatch('setInstanceOption', { name: 'uploadlimit', value: parseInt(uploadlimit.uploadlimit) })
store.dispatch('setInstanceOption', { name: 'avatarlimit', value: parseInt(uploadlimit.avatarlimit) })
store.dispatch('setInstanceOption', { name: 'backgroundlimit', value: parseInt(uploadlimit.backgroundlimit) })
store.dispatch('setInstanceOption', { name: 'bannerlimit', value: parseInt(uploadlimit.bannerlimit) })
}
2018-12-10 15:36:25 +00:00
if (vapidPublicKey) {
store.dispatch('setInstanceOption', { name: 'vapidPublicKey', value: vapidPublicKey })
}
2018-10-26 13:16:23 +00:00
2019-03-13 11:41:39 +00:00
return data.site.pleromafe
} else {
throw (res)
}
2019-03-13 10:57:30 +00:00
} catch (error) {
console.error('Could not load statusnet config, potentially fatal')
console.error(error)
}
}
2018-10-26 13:16:23 +00:00
2019-03-13 10:57:30 +00:00
const getStaticConfig = async () => {
try {
const res = await window.fetch('/static/config.json')
2019-03-13 11:41:39 +00:00
if (res.ok) {
return res.json()
} else {
throw (res)
}
2019-03-13 10:57:30 +00:00
} catch (error) {
console.warn('Failed to load static/config.json, continuing without it.')
console.warn(error)
return {}
}
}
2019-01-24 18:03:13 +00:00
2019-03-13 10:57:30 +00:00
const setSettings = async ({ apiConfig, staticConfig, store }) => {
const overrides = window.___pleromafe_dev_overrides || {}
const env = window.___pleromafe_mode.NODE_ENV
// This takes static config and overrides properties that are present in apiConfig
let config = {}
if (overrides.staticConfigPreference && env === 'development') {
console.warn('OVERRIDING API CONFIG WITH STATIC CONFIG')
config = Object.assign({}, apiConfig, staticConfig)
} else {
config = Object.assign({}, staticConfig, apiConfig)
}
const copyInstanceOption = (name) => {
store.dispatch('setInstanceOption', { name, value: config[name] })
}
copyInstanceOption('nsfwCensorImage')
copyInstanceOption('background')
copyInstanceOption('hidePostStats')
copyInstanceOption('hideUserStats')
copyInstanceOption('hideFilteredStatuses')
copyInstanceOption('logo')
2018-10-26 13:16:23 +00:00
2019-03-13 10:57:30 +00:00
store.dispatch('setInstanceOption', {
name: 'logoMask',
value: typeof config.logoMask === 'undefined'
? true
: config.logoMask
})
store.dispatch('setInstanceOption', {
name: 'logoMargin',
value: typeof config.logoMargin === 'undefined'
? 0
: config.logoMargin
})
store.commit('authFlow/setInitialStrategy', config.loginMethod)
2019-03-13 10:57:30 +00:00
copyInstanceOption('redirectRootNoLogin')
copyInstanceOption('redirectRootLogin')
copyInstanceOption('showInstanceSpecificPanel')
copyInstanceOption('minimalScopesMode')
copyInstanceOption('hideMutedPosts')
2019-03-13 10:57:30 +00:00
copyInstanceOption('collapseMessageWithSubject')
copyInstanceOption('scopeCopy')
copyInstanceOption('subjectLineBehavior')
copyInstanceOption('postContentType')
copyInstanceOption('alwaysShowSubjectInput')
copyInstanceOption('noAttachmentLinks')
copyInstanceOption('showFeaturesPanel')
copyInstanceOption('hideSitename')
2019-03-13 10:57:30 +00:00
return store.dispatch('setTheme', config['theme'])
}
2018-10-26 13:16:23 +00:00
const getTOS = async ({ store }) => {
try {
const res = await window.fetch('/static/terms-of-service.html')
if (res.ok) {
const html = await res.text()
2018-10-26 13:16:23 +00:00
store.dispatch('setInstanceOption', { name: 'tos', value: html })
} else {
throw (res)
}
} catch (e) {
console.warn("Can't load TOS")
console.warn(e)
}
}
const getInstancePanel = async ({ store }) => {
try {
const res = await window.fetch('/instance/panel.html')
if (res.ok) {
const html = await res.text()
store.dispatch('setInstanceOption', { name: 'instanceSpecificPanelContent', value: html })
} else {
throw (res)
}
} catch (e) {
console.warn("Can't load instance panel")
console.warn(e)
}
}
2018-10-26 13:16:23 +00:00
const getStickers = async ({ store }) => {
try {
const res = await window.fetch('/static/stickers.json')
if (res.ok) {
const values = await res.json()
const stickers = (await Promise.all(
Object.entries(values).map(async ([name, path]) => {
const resPack = await window.fetch(path + 'pack.json')
var meta = {}
if (resPack.ok) {
meta = await resPack.json()
}
return {
pack: name,
path,
meta
}
})
)).sort((a, b) => {
return a.meta.title.localeCompare(b.meta.title)
})
store.dispatch('setInstanceOption', { name: 'stickers', value: stickers })
} else {
throw (res)
}
} catch (e) {
console.warn("Can't load stickers")
console.warn(e)
}
}
const getAppSecret = async ({ store }) => {
const { state, commit } = store
const { oauth, instance } = state
return getOrCreateApp({ ...oauth, instance: instance.server, commit })
.then((app) => getClientToken({ ...app, instance: instance.server }))
.then((token) => {
commit('setAppToken', token.access_token)
commit('setBackendInteractor', backendInteractorService(store.getters.getToken()))
})
}
2019-11-09 05:21:07 +00:00
const resolveStaffAccounts = async ({ store, accounts }) => {
const backendInteractor = store.state.api.backendInteractor
2019-11-09 06:34:05 +00:00
let nicknames = accounts.map(uri => uri.split('/').pop())
.map(id => backendInteractor.fetchUser({ id }))
2019-11-09 05:21:07 +00:00
nicknames = await Promise.all(nicknames)
store.dispatch('setInstanceOption', { name: 'staffAccounts', value: nicknames })
}
const getNodeInfo = async ({ store }) => {
try {
const res = await window.fetch('/nodeinfo/2.0.json')
if (res.ok) {
const data = await res.json()
2018-10-26 13:16:23 +00:00
const metadata = data.metadata
const features = metadata.features
store.dispatch('setInstanceOption', { name: 'mediaProxyAvailable', value: features.includes('media_proxy') })
store.dispatch('setInstanceOption', { name: 'chatAvailable', value: features.includes('chat') })
store.dispatch('setInstanceOption', { name: 'gopherAvailable', value: features.includes('gopher') })
2019-06-18 20:28:31 +00:00
store.dispatch('setInstanceOption', { name: 'pollsAvailable', value: features.includes('polls') })
store.dispatch('setInstanceOption', { name: 'pollLimits', value: metadata.pollLimits })
2019-09-05 11:23:28 +00:00
store.dispatch('setInstanceOption', { name: 'mailerEnabled', value: metadata.mailerEnabled })
2018-10-26 13:16:23 +00:00
store.dispatch('setInstanceOption', { name: 'restrictedNicknames', value: metadata.restrictedNicknames })
store.dispatch('setInstanceOption', { name: 'postFormats', value: metadata.postFormats })
2018-10-26 13:16:23 +00:00
const suggestions = metadata.suggestions
store.dispatch('setInstanceOption', { name: 'suggestionsEnabled', value: suggestions.enabled })
store.dispatch('setInstanceOption', { name: 'suggestionsWeb', value: suggestions.web })
const software = data.software
store.dispatch('setInstanceOption', { name: 'backendVersion', value: software.version })
store.dispatch('setInstanceOption', { name: 'pleromaBackend', value: software.name === 'pleroma' })
const priv = metadata.private
store.dispatch('setInstanceOption', { name: 'private', value: priv })
const frontendVersion = window.___pleromafe_commit_hash
store.dispatch('setInstanceOption', { name: 'frontendVersion', value: frontendVersion })
2019-02-18 14:49:32 +00:00
store.dispatch('setInstanceOption', { name: 'tagPolicyAvailable', value: metadata.federation.mrf_policies.includes('TagPolicy') })
2019-11-09 05:21:07 +00:00
2019-11-09 06:09:32 +00:00
const federation = metadata.federation
store.dispatch('setInstanceOption', { name: 'federationPolicy', value: federation })
store.dispatch('setInstanceOption', {
name: 'federating',
value: typeof federation.enabled === 'undefined'
? true
: federation.enabled
})
2019-11-09 06:09:32 +00:00
2019-11-09 05:21:07 +00:00
const accounts = metadata.staffAccounts
await resolveStaffAccounts({ store, accounts })
} else {
throw (res)
}
} catch (e) {
console.warn('Could not load nodeinfo')
console.warn(e)
}
}
const setConfig = async ({ store }) => {
// apiConfig, staticConfig
const configInfos = await Promise.all([getStatusnetConfig({ store }), getStaticConfig()])
const apiConfig = configInfos[0]
const staticConfig = configInfos[1]
await setSettings({ store, apiConfig, staticConfig }).then(getAppSecret({ store }))
}
2019-04-01 19:32:13 +00:00
const checkOAuthToken = async ({ store }) => {
return new Promise(async (resolve, reject) => {
2019-06-13 07:05:22 +00:00
if (store.getters.getUserToken()) {
2019-04-01 19:32:13 +00:00
try {
2019-06-13 07:00:06 +00:00
await store.dispatch('loginUser', store.getters.getUserToken())
2019-04-01 19:32:13 +00:00
} catch (e) {
console.error(e)
2019-04-01 19:32:13 +00:00
}
}
resolve()
})
}
2019-03-13 10:57:30 +00:00
const afterStoreSetup = async ({ store, i18n }) => {
2019-04-01 19:41:34 +00:00
const width = windowWidth()
2019-03-23 20:21:57 +00:00
store.dispatch('setMobileLayout', width <= 800)
await setConfig({ store })
const { customTheme, customThemeSource } = store.state.config
const { theme } = store.state.instance
const customThemePresent = customThemeSource || customTheme
if (customThemePresent) {
if (customThemeSource && customThemeSource.version === CURRENT_VERSION) {
applyTheme(customThemeSource)
} else {
applyTheme(customTheme)
}
} else if (theme) {
// do nothing, it will load asynchronously
} else {
console.error('Failed to load any theme!')
}
2019-03-23 20:21:57 +00:00
// Now we can try getting the server settings and logging in
2019-04-01 19:32:13 +00:00
await Promise.all([
checkOAuthToken({ store }),
getTOS({ store }),
getInstancePanel({ store }),
getStickers({ store }),
2019-04-01 19:32:13 +00:00
getNodeInfo({ store })
])
2019-03-13 10:57:30 +00:00
const router = new VueRouter({
mode: 'history',
routes: routes(store),
scrollBehavior: (to, _from, savedPosition) => {
if (to.matched.some(m => m.meta.dontScroll)) {
return false
}
return savedPosition || { x: 0, y: 0 }
}
})
/* eslint-disable no-new */
return new Vue({
router,
store,
i18n,
el: '#app',
render: h => h(App)
})
2018-10-26 13:16:23 +00:00
}
export default afterStoreSetup