github.com/resonatecoop/id@v1.1.0-43/frontend/src/index.js (about) 1 const choo = require('choo') 2 const nanochoo = require('nanochoo') 3 const initialState = window.initialState 4 ? Object.assign({}, window.initialState) 5 : {} 6 const app = choo({ href: false }) // disable choo href routing 7 window.initialState = initialState // hack to bring back initial state (should be deleted again by nanochoo) 8 9 const { isBrowser } = require('browser-or-node') 10 const setTitle = require('./lib/title') 11 const { getAPIServiceClientWithAuth } = require('@resonate/api-service')({ 12 apiHost: process.env.APP_HOST, 13 base: process.env.API_BASE || '/api/v3' 14 }) 15 16 const SearchOuter = require('./components/header') 17 const UserMenu = require('./components/user-menu') 18 19 if (isBrowser) { 20 require('web-animations-js/web-animations.min') 21 22 window.localStorage.DISABLE_NANOTIMING = process.env.DISABLE_NANOTIMING === 'yes' 23 window.localStorage.logLevel = process.env.LOG_LEVEL 24 25 if (process.env.NODE_ENV !== 'production') { 26 app.use(require('choo-devtools')()) 27 } 28 29 if ('Notification' in window) { 30 app.use(require('choo-notification')()) 31 } 32 } 33 34 app.use(require('choo-meta')()) 35 36 // main app store 37 app.use((state, emitter) => { 38 state.profile = state.profile || { 39 displayName: '', 40 member: false 41 } 42 43 state.profile.avatar = state.profile.avatar || {} 44 45 state.clients = state.clients || [ 46 { 47 connectUrl: 'https://stream.resonate.coop/api/user/connect/resonate', 48 name: 'Player', 49 description: 'stream.resonate.coop' 50 }, 51 { 52 connectUrl: 'https://dash.resonate.coop/api/user/connect/resonate', 53 name: 'Dashboard', 54 description: 'dash.resonate.coop' 55 } 56 ] 57 58 emitter.on(state.events.DOMCONTENTLOADED, () => { 59 emitter.emit(`route:${state.route}`) 60 setMeta() 61 }) 62 63 emitter.on('route:account', () => { 64 getUserProfile() 65 }) 66 67 emitter.on('route:profile', () => { 68 getUserProfile() 69 }) 70 71 emitter.on(state.events.NAVIGATE, () => { 72 emitter.emit(`route:${state.route}`) 73 setMeta() 74 }) 75 76 async function getUserProfile () { 77 try { 78 // get v2 api profile for legacy values (old nickname, avatar) 79 const getClient = getAPIServiceClientWithAuth(state.token) 80 const client = await getClient('profile') 81 const result = await client.getUserProfile() 82 83 const { body: response } = result 84 const { data: userData } = response 85 86 state.profile.nickname = userData.nickname 87 state.profile.avatar = userData.avatar || {} 88 89 emitter.emit(state.events.RENDER) 90 } catch (err) { 91 console.log(err.message) 92 console.log(err) 93 } 94 } 95 96 function setMeta () { 97 const title = { 98 '*': 'Page not found', 99 '/': 'Apps', 100 login: 'Log In', 101 authorize: 'Authorize', 102 profile: 'Create your profile', 103 account: 'Update your account', 104 'password-reset': 'Password reset', 105 join: 'Join' 106 }[state.route] 107 108 if (!title) return 109 110 state.shortTitle = title 111 112 const fullTitle = setTitle(title) 113 114 emitter.emit('meta', { 115 title: fullTitle 116 }) 117 } 118 }) 119 120 app.use(require('./plugins/notifications')()) 121 122 require('./routes')(app) 123 124 /* 125 * Append search component to header (outside of main choo app) 126 */ 127 async function searchApp (initialState) { 128 window.initialState = initialState 129 130 const search = nanochoo() 131 132 search.use((state, emitter, app) => { 133 state.search = state.search || { 134 q: '' 135 } 136 137 state.user = { 138 token: state.token 139 } 140 state.params = {} // nanochoo does not have a router 141 142 emitter.on('search', (q) => { 143 const bang = q.startsWith('#') 144 const pathname = bang ? '/tag' : '/search' 145 const url = new URL(pathname, process.env.APP_HOST || 'http://localhost') 146 const params = bang ? { term: q.split('#')[1] } : { q } 147 url.search = new URLSearchParams(params) 148 return window.open(url.href, '_blank') 149 }) 150 }) 151 152 search.view((state, emit) => { 153 // component id needs to be header to work correctly 154 return state.cache(SearchOuter, 'header').render() 155 }) 156 157 search.mount('#search-host') 158 159 return Promise.resolve() 160 } 161 162 /* 163 * Append usermenu app 164 */ 165 async function userMenuApp (initialState) { 166 if (!document.getElementById('usermenu')) return 167 168 window.initialState = initialState 169 170 const usermenu = nanochoo() 171 172 usermenu.use((state, emitter, app) => { 173 state.params = {} // nanochoo does not have a router 174 }) 175 176 usermenu.view((state, emit) => { 177 return state.cache(UserMenu, 'usermenu').render({ 178 displayName: state.profile.displayName 179 }) 180 }) 181 182 usermenu.mount('#usermenu') 183 184 return Promise.resolve() 185 } 186 187 searchApp(initialState).then(() => { 188 console.log('Loaded search app') 189 }) 190 191 userMenuApp(initialState).then(() => { 192 console.log('Loaded user menu') 193 }) 194 195 module.exports = app.mount('#app')