refactor [instanceName].html

This commit is contained in:
Nolan Lawson 2018-01-27 14:45:51 -08:00
parent 94e06ca7f8
commit a779afafce
6 changed files with 153 additions and 77 deletions

37
package-lock.json generated
View file

@ -43,6 +43,22 @@
} }
} }
}, },
"aggregate-error": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-1.0.0.tgz",
"integrity": "sha1-iINE2tAiCnLjr1CQYRf0h3GSX6w=",
"requires": {
"clean-stack": "1.3.0",
"indent-string": "3.2.0"
},
"dependencies": {
"indent-string": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/indent-string/-/indent-string-3.2.0.tgz",
"integrity": "sha1-Sl/W0nzDMvN+VBmlBNu4NxBckok="
}
}
},
"ajv": { "ajv": {
"version": "5.5.2", "version": "5.5.2",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz",
@ -760,6 +776,11 @@
} }
} }
}, },
"clean-stack": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-1.3.0.tgz",
"integrity": "sha1-noIVAa6XmYbEax1m0tQy2y/UrjE="
},
"cliui": { "cliui": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz",
@ -4933,6 +4954,14 @@
"os-tmpdir": "1.0.2" "os-tmpdir": "1.0.2"
} }
}, },
"p-any": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/p-any/-/p-any-1.1.0.tgz",
"integrity": "sha512-Ef0tVa4CZ5pTAmKn+Cg3w8ABBXh+hHO1aV8281dKOoUHfX+3tjG2EaFcC+aZyagg9b4EYGsHEjz21DnEE8Og2g==",
"requires": {
"p-some": "2.0.1"
}
},
"p-finally": { "p-finally": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
@ -4954,6 +4983,14 @@
"p-limit": "1.2.0" "p-limit": "1.2.0"
} }
}, },
"p-some": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/p-some/-/p-some-2.0.1.tgz",
"integrity": "sha1-Zdh8ixVO289SIdFnd4ttLhUPbwY=",
"requires": {
"aggregate-error": "1.0.0"
}
},
"p-try": { "p-try": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",

View file

@ -38,6 +38,7 @@
"node-fetch": "^1.7.3", "node-fetch": "^1.7.3",
"node-sass": "^4.7.2", "node-sass": "^4.7.2",
"npm-run-all": "^4.1.2", "npm-run-all": "^4.1.2",
"p-any": "^1.1.0",
"performance-now": "^2.1.0", "performance-now": "^2.1.0",
"pify": "^3.0.0", "pify": "^3.0.0",
"quick-lru": "^1.1.0", "quick-lru": "^1.1.0",

View file

@ -39,6 +39,18 @@ if (process.browser && process.env.NODE_ENV !== 'production') {
} }
} }
function setInCache(cache, instanceName, key, value) {
return cache.set(`${instanceName}/${key}`, value)
}
function getInCache(cache, instanceName, key) {
return cache.get(`${instanceName}/${key}`)
}
function hasInCache(cache, instanceName, key) {
return cache.has(`${instanceName}/${key}`)
}
// //
// timelines/statuses // timelines/statuses
// //
@ -68,10 +80,10 @@ export async function getTimeline(instanceName, timeline, maxId = null, limit =
export async function insertStatuses(instanceName, timeline, statuses) { export async function insertStatuses(instanceName, timeline, statuses) {
for (let status of statuses) { for (let status of statuses) {
statusesCache.set(status.id, status) setInCache(statusesCache, instanceName, status.id, status)
accountsCache.set(status.account.id, status.account) setInCache(accountsCache, instanceName, status.account.id, status.account)
if (status.reblog) { if (status.reblog) {
accountsCache.set(status.reblog.account.id, status.reblog.account) setInCache(accountsCache, instanceName, status.reblog.account.id, status.reblog.account)
} }
} }
const db = await getDatabase(instanceName, timeline) const db = await getDatabase(instanceName, timeline)
@ -93,11 +105,11 @@ export async function insertStatuses(instanceName, timeline, statuses) {
} }
export async function getStatus(instanceName, statusId) { export async function getStatus(instanceName, statusId) {
if (statusesCache.has(statusId)) { if (hasInCache(statusesCache, instanceName, statusId)) {
if (process.browser && process.env.NODE_ENV !== 'production') { if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.statuses.hits++ window.cacheStats.statuses.hits++
} }
return statusesCache.get(statusId) return getInCache(statusesCache, instanceName, statusId)
} }
const db = await getDatabase(instanceName) const db = await getDatabase(instanceName)
let result = await dbPromise(db, STATUSES_STORE, 'readonly', (store, callback) => { let result = await dbPromise(db, STATUSES_STORE, 'readonly', (store, callback) => {
@ -105,7 +117,7 @@ export async function getStatus(instanceName, statusId) {
callback(e.target.result && e.target.result) callback(e.target.result && e.target.result)
} }
}) })
statusesCache.set(statusId, result) setInCache(statusesCache, instanceName, statusId, result)
if (process.browser && process.env.NODE_ENV !== 'production') { if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.statuses.misses++ window.cacheStats.statuses.misses++
} }
@ -117,11 +129,11 @@ export async function getStatus(instanceName, statusId) {
// //
async function getMetaProperty(instanceName, key) { async function getMetaProperty(instanceName, key) {
if (metaCache.has(key)) { if (hasInCache(metaCache, instanceName, key)) {
if (process.browser && process.env.NODE_ENV !== 'production') { if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.meta.hits++ window.cacheStats.meta.hits++
} }
return metaCache.get(key) return getInCache(metaCache, instanceName, key)
} }
const db = await getDatabase(instanceName) const db = await getDatabase(instanceName)
let result = await dbPromise(db, META_STORE, 'readonly', (store, callback) => { let result = await dbPromise(db, META_STORE, 'readonly', (store, callback) => {
@ -129,7 +141,7 @@ async function getMetaProperty(instanceName, key) {
callback(e.target.result && e.target.result.value) callback(e.target.result && e.target.result.value)
} }
}) })
metaCache.set(key, result) setInCache(metaCache, instanceName, key, result)
if (process.browser && process.env.NODE_ENV !== 'production') { if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.meta.misses++ window.cacheStats.meta.misses++
} }
@ -137,7 +149,7 @@ async function getMetaProperty(instanceName, key) {
} }
async function setMetaProperty(instanceName, key, value) { async function setMetaProperty(instanceName, key, value) {
metaCache.set(key, value) setInCache(metaCache, instanceName, key, value)
const db = await getDatabase(instanceName) const db = await getDatabase(instanceName)
return await dbPromise(db, META_STORE, 'readwrite', (store) => { return await dbPromise(db, META_STORE, 'readwrite', (store) => {
store.put({ store.put({
@ -168,11 +180,11 @@ export async function setInstanceInfo(instanceName, value) {
// //
export async function getAccount(instanceName, accountId) { export async function getAccount(instanceName, accountId) {
if (accountsCache.has(accountId)) { if (hasInCache(accountsCache, instanceName, accountId)) {
if (process.browser && process.env.NODE_ENV !== 'production') { if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.accounts.hits++ window.cacheStats.accounts.hits++
} }
return accountsCache.get(accountId) return getInCache(accountsCache, instanceName, accountId)
} }
const db = await getDatabase(instanceName) const db = await getDatabase(instanceName)
let result = await dbPromise(db, ACCOUNTS_STORE, 'readonly', (store, callback) => { let result = await dbPromise(db, ACCOUNTS_STORE, 'readonly', (store, callback) => {

View file

@ -97,12 +97,13 @@
import { store } from '../../_utils/store' import { store } from '../../_utils/store'
import Layout from '../../_components/Layout.html' import Layout from '../../_components/Layout.html'
import SettingsLayout from '../_components/SettingsLayout.html' import SettingsLayout from '../_components/SettingsLayout.html'
import { getVerifyCredentials } from '../../_utils/mastodon/user' import {
import { database } from '../../_utils/database/database' changeTheme,
switchToInstance,
logOutOfInstance,
updateVerifyCredentialsForInstance
} from './_actions/[instanceName]'
import { themes } from '../../_static/themes' import { themes } from '../../_static/themes'
import { switchToTheme } from '../../_utils/themeEngine'
import { goto } from 'sapper/runtime.js'
import { toast } from '../../_utils/toast'
export default { export default {
components: { components: {
@ -111,73 +112,32 @@
}, },
store: () => store, store: () => store,
data: () => ({ data: () => ({
themes: themes themes: themes,
}), }),
oncreate: async function () { async oncreate() {
let instanceName = this.get('params').instanceName let instanceName = this.get('instanceName')
let loggedInInstances = this.store.get('loggedInInstances') await updateVerifyCredentialsForInstance(instanceName)
let instanceThemes = this.store.get('instanceThemes') },
let instanceData = loggedInInstances[instanceName] computed: {
let verifyCredentials = await database.getInstanceVerifyCredentials(instanceName) instanceName: (params) => params.instanceName,
if (verifyCredentials) { // update in background selectedTheme: ($instanceThemes, instanceName) => $instanceThemes[instanceName],
getVerifyCredentials(instanceName, instanceData.access_token).then(verifyCredentials => { verifyCredentials: ($verifyCredentials, instanceName) => $verifyCredentials && $verifyCredentials[instanceName]
database.setInstanceVerifyCredentials(instanceName, verifyCredentials)
})
} else { // go to network
verifyCredentials = await getVerifyCredentials(instanceName, instanceData.access_token)
database.setInstanceVerifyCredentials(instanceName, verifyCredentials)
}
this.set({
verifyCredentials: verifyCredentials,
selectedTheme: instanceThemes[instanceName]
})
}, },
methods: { methods: {
onThemeChange() { onThemeChange() {
let newTheme = this.get('selectedTheme') let newTheme = this.get('selectedTheme')
let instanceName = this.get('params').instanceName let instanceName = this.get('instanceName')
let instanceThemes = this.store.get('instanceThemes') changeTheme(instanceName, newTheme)
instanceThemes[instanceName] = newTheme
this.store.set({instanceThemes: instanceThemes})
this.store.save()
if (this.get('params').instanceName === this.store.get('currentInstance')) {
switchToTheme(newTheme)
}
}, },
onSwitchToThisInstance(e) { onSwitchToThisInstance(e) {
e.preventDefault() e.preventDefault()
let instanceName = this.get('params').instanceName let instanceName = this.get('instanceName')
let instanceThemes = this.store.get('instanceThemes') switchToInstance(instanceName)
this.store.set({
currentInstance: instanceName
})
this.store.save()
switchToTheme(instanceThemes[instanceName])
}, },
onLogOut(e) { onLogOut(e) {
e.preventDefault() e.preventDefault()
let loggedInInstances = this.store.get('loggedInInstances') let instanceName = this.get('instanceName')
let instanceThemes = this.store.get('instanceThemes') logOutOfInstance(instanceName)
let loggedInInstancesInOrder = this.store.get('loggedInInstancesInOrder')
let instanceName = this.get('params').instanceName
let currentInstance = this.store.get('currentInstance')
loggedInInstancesInOrder.splice(loggedInInstancesInOrder.indexOf(instanceName), 1)
let newInstance = instanceName === currentInstance ?
loggedInInstancesInOrder[0] :
currentInstance
delete loggedInInstances[instanceName]
delete instanceThemes[instanceName]
this.store.set({
loggedInInstances: loggedInInstances,
instanceThemes: instanceThemes,
loggedInInstancesInOrder: loggedInInstancesInOrder,
currentInstance: newInstance
})
this.store.save()
database.clearDatabaseForInstance(instanceName)
switchToTheme(instanceThemes[newInstance] || 'default')
toast.say(`Logged out of ${instanceName}`)
goto('/settings/instances')
} }
} }
} }

View file

@ -0,0 +1,68 @@
import { getVerifyCredentials } from '../../../_utils/mastodon/user'
import { store } from '../../../_utils/store'
import { switchToTheme } from '../../../_utils/themeEngine'
import { toast } from '../../../_utils/toast'
import { database } from '../../../_utils/database/database'
import { goto } from 'sapper/runtime.js'
import pAny from 'p-any'
export function changeTheme(instanceName, newTheme) {
let instanceThemes = store.get('instanceThemes')
instanceThemes[instanceName] = newTheme
store.set({instanceThemes: instanceThemes})
store.save()
if (instanceName === store.get('currentInstance')) {
switchToTheme(newTheme)
}
}
export function switchToInstance(instanceName) {
let instanceThemes = store.get('instanceThemes')
store.set({currentInstance: instanceName})
store.save()
switchToTheme(instanceThemes[instanceName])
}
export async function logOutOfInstance(instanceName) {
let loggedInInstances = store.get('loggedInInstances')
let instanceThemes = store.get('instanceThemes')
let loggedInInstancesInOrder = store.get('loggedInInstancesInOrder')
let currentInstance = store.get('currentInstance')
loggedInInstancesInOrder.splice(loggedInInstancesInOrder.indexOf(instanceName), 1)
let newInstance = instanceName === currentInstance ?
loggedInInstancesInOrder[0] :
currentInstance
delete loggedInInstances[instanceName]
delete instanceThemes[instanceName]
store.set({
loggedInInstances: loggedInInstances,
instanceThemes: instanceThemes,
loggedInInstancesInOrder: loggedInInstancesInOrder,
currentInstance: newInstance
})
store.save()
toast.say(`Logged out of ${instanceName}`)
switchToTheme(instanceThemes[newInstance] || 'default')
await database.clearDatabaseForInstance(instanceName)
goto('/settings/instances')
}
function setStoreVerifyCredentials(instanceName, thisVerifyCredentials) {
let verifyCredentials = store.get('verifyCredentials') || {}
verifyCredentials[instanceName] = thisVerifyCredentials
store.set({verifyCredentials: verifyCredentials})
}
export async function updateVerifyCredentialsForInstance(instanceName) {
let loggedInInstances = store.get('loggedInInstances')
let instanceData = loggedInInstances[instanceName]
await pAny([
database.getInstanceVerifyCredentials(instanceName).then(verifyCredentials => {
setStoreVerifyCredentials(instanceName, verifyCredentials)
}),
getVerifyCredentials(instanceName, instanceData.access_token).then(verifyCredentials => {
setStoreVerifyCredentials(instanceName, verifyCredentials)
return database.setInstanceVerifyCredentials(instanceName, verifyCredentials)
})
])
}

View file

@ -1,10 +1,10 @@
import { getAccessTokenFromAuthCode, registerApplication, generateAuthLink } from '../../../_utils/mastodon/oauth' import { getAccessTokenFromAuthCode, registerApplication, generateAuthLink } from '../../../_utils/mastodon/oauth'
import { getVerifyCredentials } from '../../../_utils/mastodon/user'
import { getInstanceInfo } from '../../../_utils/mastodon/instance' import { getInstanceInfo } from '../../../_utils/mastodon/instance'
import { goto } from 'sapper/runtime.js' import { goto } from 'sapper/runtime.js'
import { switchToTheme } from '../../../_utils/themeEngine' import { switchToTheme } from '../../../_utils/themeEngine'
import { database } from '../../../_utils/database/database' import { database } from '../../../_utils/database/database'
import { store } from '../../../_utils/store' import { store } from '../../../_utils/store'
import { updateVerifyCredentialsForInstance } from './[instanceName]'
const REDIRECT_URI = (typeof location !== 'undefined' ? const REDIRECT_URI = (typeof location !== 'undefined' ?
location.origin : 'https://pinafore.social') + '/settings/instances/add' location.origin : 'https://pinafore.social') + '/settings/instances/add'
@ -86,9 +86,7 @@ async function registerNewInstance(code) {
store.save() store.save()
switchToTheme('default') switchToTheme('default')
// fire off request for account so it's cached // fire off request for account so it's cached
getVerifyCredentials(currentRegisteredInstanceName, instanceData.access_token).then(verifyCredentials => { updateVerifyCredentialsForInstance(currentRegisteredInstanceName)
database.setInstanceVerifyCredentials(currentRegisteredInstanceName, verifyCredentials)
})
goto('/') goto('/')
} }