make it possible to fetch and store streaming URL

This commit is contained in:
Nolan Lawson 2018-01-25 08:44:10 -08:00
parent 569f384192
commit 2b943fe0bf
4 changed files with 93 additions and 28 deletions

View file

@ -19,6 +19,7 @@
<script> <script>
import { store } from '../_utils/store' import { store } from '../_utils/store'
import { getTimeline } from '../_utils/mastodon/timelines' import { getTimeline } from '../_utils/mastodon/timelines'
import { getInstanceInfo } from '../_utils/mastodon/instance'
import StatusListItem from './StatusListItem.html' import StatusListItem from './StatusListItem.html'
import LoadingFooter from './LoadingFooter.html' import LoadingFooter from './LoadingFooter.html'
import VirtualList from './virtualList/VirtualList.html' import VirtualList from './virtualList/VirtualList.html'
@ -40,12 +41,15 @@
export default { export default {
async oncreate() { async oncreate() {
let timeline = this.get('timeline') let timeline = this.get('timeline')
let instanceName = this.store.get('currentInstance')
let cachedStatusIds = cachedTimelines[timeline] let cachedStatusIds = cachedTimelines[timeline]
if (cachedStatusIds) { if (cachedStatusIds) {
this.set({statusIds: cachedStatusIds}) this.set({statusIds: cachedStatusIds})
} else { } else {
this.addStatuses(await this.fetchStatusesAndPossiblyFallBack()) this.addStatuses(await this.fetchStatusesAndPossiblyFallBack())
} }
/* no await */ getInstanceInfo(instanceName).then(instanceInfo => database.setInstanceInfo(instanceName, instanceInfo))
let instanceInfo = await database.getInstanceInfo(instanceName)
}, },
ondestroy() { ondestroy() {
cachedTimelines[this.get('timeline')] = this.get('statusIds') cachedTimelines[this.get('timeline')] = this.get('statusIds')

View file

@ -17,6 +17,7 @@ import QuickLRU from 'quick-lru'
const statusesCache = new QuickLRU({maxSize: 100}) const statusesCache = new QuickLRU({maxSize: 100})
const accountsCache = new QuickLRU({maxSize: 50}) const accountsCache = new QuickLRU({maxSize: 50})
const metaCache = new QuickLRU({maxSize: 20})
if (process.browser && process.env.NODE_ENV !== 'production') { if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats = { window.cacheStats = {
@ -29,10 +30,19 @@ if (process.browser && process.env.NODE_ENV !== 'production') {
cache: accountsCache, cache: accountsCache,
hits: 0, hits: 0,
misses: 0 misses: 0
},
meta: {
cache: accountsCache,
hits: 0,
misses: 0
} }
} }
} }
//
// timelines/statuses
//
export async function getTimeline(instanceName, timeline, maxId = null, limit = 20) { export async function getTimeline(instanceName, timeline, maxId = null, limit = 20) {
const db = await getDatabase(instanceName, timeline) const db = await getDatabase(instanceName, timeline)
return await dbPromise(db, [TIMELINE_STORE, STATUSES_STORE], 'readonly', (stores, callback) => { return await dbPromise(db, [TIMELINE_STORE, STATUSES_STORE], 'readonly', (stores, callback) => {
@ -82,25 +92,81 @@ export async function insertStatuses(instanceName, timeline, statuses) {
}) })
} }
export async function getInstanceVerifyCredentials(instanceName) { export async function getStatus(instanceName, statusId) {
if (statusesCache.has(statusId)) {
if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.statuses.hits++
}
return statusesCache.get(statusId)
}
const db = await getDatabase(instanceName) const db = await getDatabase(instanceName)
return await dbPromise(db, META_STORE, 'readonly', (store, callback) => { let result = await dbPromise(db, STATUSES_STORE, 'readonly', (store, callback) => {
store.get('verifyCredentials').onsuccess = (e) => { store.get(statusId).onsuccess = (e) => {
callback(e.target.result && e.target.result)
}
})
statusesCache.set(statusId, result)
if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.statuses.misses++
}
return result
}
//
// meta
//
async function getMetaProperty(instanceName, key) {
if (metaCache.has(key)) {
if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.meta.hits++
}
return metaCache.get(key)
}
const db = await getDatabase(instanceName)
let result = await dbPromise(db, META_STORE, 'readonly', (store, callback) => {
store.get(key).onsuccess = (e) => {
callback(e.target.result && e.target.result.value) callback(e.target.result && e.target.result.value)
} }
}) })
metaCache.set(key, result)
if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.meta.misses++
}
return result
} }
export async function setInstanceVerifyCredentials(instanceName, verifyCredentials) { async function setMetaProperty(instanceName, key, value) {
metaCache.set(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({
key: 'verifyCredentials', key: key,
value: verifyCredentials value: value
}) })
}) })
} }
export async function getInstanceVerifyCredentials(instanceName) {
return await getMetaProperty(instanceName, 'verifyCredentials')
}
export async function setInstanceVerifyCredentials(instanceName, value) {
return await setMetaProperty(instanceName, 'verifyCredentials', value)
}
export async function getInstanceInfo(instanceName) {
return await getMetaProperty(instanceName, 'instance')
}
export async function setInstanceInfo(instanceName, value) {
return await setMetaProperty(instanceName, 'instance', value)
}
//
// accounts
//
export async function getAccount(instanceName, accountId) { export async function getAccount(instanceName, accountId) {
if (accountsCache.has(accountId)) { if (accountsCache.has(accountId)) {
if (process.browser && process.env.NODE_ENV !== 'production') { if (process.browser && process.env.NODE_ENV !== 'production') {
@ -120,26 +186,10 @@ export async function getAccount(instanceName, accountId) {
return result return result
} }
//
// lifecycle
//
export async function clearDatabaseForInstance(instanceName) { export async function clearDatabaseForInstance(instanceName) {
await deleteDatabase(instanceName) await deleteDatabase(instanceName)
}
export async function getStatus(instanceName, statusId) {
if (statusesCache.has(statusId)) {
if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.statuses.hits++
}
return statusesCache.get(statusId)
}
const db = await getDatabase(instanceName)
let result = await dbPromise(db, STATUSES_STORE, 'readonly', (store, callback) => {
store.get(statusId).onsuccess = (e) => {
callback(e.target.result && e.target.result)
}
})
statusesCache.set(statusId, result)
if (process.browser && process.env.NODE_ENV !== 'production') {
window.cacheStats.statuses.misses++
}
return result
} }

View file

@ -0,0 +1,7 @@
import { get } from '../ajax'
import { basename } from './utils'
export function getInstanceInfo(instanceName) {
let url = `${basename(instanceName)}/api/v1/instance`
return get(url)
}

View file

@ -73,6 +73,7 @@
import SettingsLayout from '../_components/SettingsLayout.html' import SettingsLayout from '../_components/SettingsLayout.html'
import { registerApplication, generateAuthLink, getAccessTokenFromAuthCode } from '../../_utils/mastodon/oauth' import { registerApplication, generateAuthLink, getAccessTokenFromAuthCode } from '../../_utils/mastodon/oauth'
import { getVerifyCredentials } from '../../_utils/mastodon/user' import { getVerifyCredentials } from '../../_utils/mastodon/user'
import { getInstanceInfo } from '../../_utils/mastodon/instance'
import { store } from '../../_utils/store' import { store } from '../../_utils/store'
import { goto } from 'sapper/runtime.js' import { goto } from 'sapper/runtime.js'
import { switchToTheme } from '../../_utils/themeEngine' import { switchToTheme } from '../../_utils/themeEngine'
@ -125,7 +126,10 @@
this.set({error: `You've already logged in to ${instanceName}`}) this.set({error: `You've already logged in to ${instanceName}`})
return return
} }
let instanceData = await registerApplication(instanceName, REDIRECT_URI) let registrationPromise = registerApplication(instanceName, REDIRECT_URI)
let instanceInfo = await getInstanceInfo(instanceName)
await database.setInstanceInfo(instanceName, instanceInfo) // cache for later
let instanceData = await registrationPromise
this.store.set({ this.store.set({
currentRegisteredInstanceName: instanceName, currentRegisteredInstanceName: instanceName,
currentRegisteredInstance: instanceData currentRegisteredInstance: instanceData
@ -177,7 +181,7 @@
}) })
this.store.save() this.store.save()
switchToTheme('default') switchToTheme('default')
// fire off request for account so it's cached in the SW // fire off request for account so it's cached
getVerifyCredentials(currentRegisteredInstanceName, instanceData.access_token).then(verifyCredentials => { getVerifyCredentials(currentRegisteredInstanceName, instanceData.access_token).then(verifyCredentials => {
database.setInstanceVerifyCredentials(currentRegisteredInstanceName, verifyCredentials) database.setInstanceVerifyCredentials(currentRegisteredInstanceName, verifyCredentials)
}) })