use standard
This commit is contained in:
parent
537a112adb
commit
2e83bc0ff9
|
@ -11,7 +11,7 @@ const readFile = pify(fs.readFile.bind(fs))
|
||||||
const glob = pify(require('glob'))
|
const glob = pify(require('glob'))
|
||||||
const rimraf = pify(require('rimraf'))
|
const rimraf = pify(require('rimraf'))
|
||||||
|
|
||||||
const selectorRegex = /\n[ \t]*([0-9\w\- \t\.:#,]+?)[ \t]*\{/g
|
const selectorRegex = /\n[ \t]*([0-9\w\- \t.:#,]+?)[ \t]*{/g
|
||||||
const styleRegex = /<style>[\s\S]+?<\/style>/
|
const styleRegex = /<style>[\s\S]+?<\/style>/
|
||||||
|
|
||||||
async function main () {
|
async function main () {
|
||||||
|
@ -29,7 +29,7 @@ async function main() {
|
||||||
let text = await readFile(filename, 'utf8')
|
let text = await readFile(filename, 'utf8')
|
||||||
let newText = text.replace(styleRegex, style => {
|
let newText = text.replace(styleRegex, style => {
|
||||||
return style.replace(selectorRegex, selectorMatch => {
|
return style.replace(selectorRegex, selectorMatch => {
|
||||||
return selectorMatch.replace(/\S[^\{]+/, selector => `:global(${selector})`)
|
return selectorMatch.replace(/\S[^{]+/, selector => `:global(${selector})`)
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
let newFilename = path.join(path.dirname(filename), '.tmp-' + path.basename(filename))
|
let newFilename = path.join(path.dirname(filename), '.tmp-' + path.basename(filename))
|
||||||
|
|
|
@ -22,5 +22,5 @@ module.exports = [
|
||||||
{id: 'fa-comments', src: 'node_modules/font-awesome-svg-png/white/svg/comments.svg', title: 'Conversations'},
|
{id: 'fa-comments', src: 'node_modules/font-awesome-svg-png/white/svg/comments.svg', title: 'Conversations'},
|
||||||
{id: 'fa-paperclip', src: 'node_modules/font-awesome-svg-png/white/svg/paperclip.svg', title: 'Paperclip'},
|
{id: 'fa-paperclip', src: 'node_modules/font-awesome-svg-png/white/svg/paperclip.svg', title: 'Paperclip'},
|
||||||
{id: 'fa-thumbtack', src: 'node_modules/font-awesome-svg-png/white/svg/thumb-tack.svg', title: 'Thumbtack'},
|
{id: 'fa-thumbtack', src: 'node_modules/font-awesome-svg-png/white/svg/thumb-tack.svg', title: 'Thumbtack'},
|
||||||
{id:'fa-bars', src:'node_modules/font-awesome-svg-png/white/svg/bars.svg', title: 'List'},
|
{id: 'fa-bars', src: 'node_modules/font-awesome-svg-png/white/svg/bars.svg', title: 'List'}
|
||||||
]
|
]
|
802
package-lock.json
generated
802
package-lock.json
generated
File diff suppressed because it is too large
Load diff
22
package.json
22
package.json
|
@ -3,6 +3,7 @@
|
||||||
"description": "TODO",
|
"description": "TODO",
|
||||||
"version": "0.0.1",
|
"version": "0.0.1",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"lint": "standard",
|
||||||
"dev": "npm run build-svg && concurrently --kill-others \"npm run build-sass-watch\" \"node server.js\"",
|
"dev": "npm run build-svg && concurrently --kill-others \"npm run build-sass-watch\" \"node server.js\"",
|
||||||
"build": "npm run globalize-css && npm run build-sass && npm run build-svg && sapper build && npm run deglobalize-css",
|
"build": "npm run globalize-css && npm run build-sass && npm run build-svg && sapper build && npm run deglobalize-css",
|
||||||
"start": "cross-env NODE_ENV=production node server.js",
|
"start": "cross-env NODE_ENV=production node server.js",
|
||||||
|
@ -47,6 +48,7 @@
|
||||||
"rimraf": "^2.6.2",
|
"rimraf": "^2.6.2",
|
||||||
"sapper": "nolanlawson/sapper#fix-style-loader-built",
|
"sapper": "nolanlawson/sapper#fix-style-loader-built",
|
||||||
"serve-static": "^1.13.1",
|
"serve-static": "^1.13.1",
|
||||||
|
"standard": "^10.0.3",
|
||||||
"style-loader": "^0.19.1",
|
"style-loader": "^0.19.1",
|
||||||
"svelte": "^1.54.0",
|
"svelte": "^1.54.0",
|
||||||
"svelte-extras": "^1.6.0",
|
"svelte-extras": "^1.6.0",
|
||||||
|
@ -63,5 +65,25 @@
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">= 8"
|
"node": ">= 8"
|
||||||
|
},
|
||||||
|
"standard": {
|
||||||
|
"globals": [
|
||||||
|
"fetch",
|
||||||
|
"IDBKeyRange",
|
||||||
|
"IDBObjectStore",
|
||||||
|
"indexedDB",
|
||||||
|
"requestAnimationFrame",
|
||||||
|
"requestIdleCallback",
|
||||||
|
"location",
|
||||||
|
"localStorage",
|
||||||
|
"URLSearchParams",
|
||||||
|
"IntersectionObserver",
|
||||||
|
"URL"
|
||||||
|
],
|
||||||
|
"ignore": [
|
||||||
|
"dist",
|
||||||
|
"cypress",
|
||||||
|
"routes/_utils/asyncModules.js"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import { database } from '../_database/database'
|
||||||
import { store } from '../_store/store'
|
import { store } from '../_store/store'
|
||||||
import { updateVerifyCredentialsForInstance } from './instances'
|
import { updateVerifyCredentialsForInstance } from './instances'
|
||||||
|
|
||||||
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'
|
||||||
|
|
||||||
async function redirectToOauth () {
|
async function redirectToOauth () {
|
||||||
let instanceName = store.get('instanceNameInSearch')
|
let instanceName = store.get('instanceNameInSearch')
|
||||||
|
@ -42,9 +42,9 @@ export async function logInToInstance() {
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err)
|
console.error(err)
|
||||||
let error = `${err.message || err.name}. ` +
|
let error = `${err.message || err.name}. ` +
|
||||||
(navigator.onLine ?
|
(navigator.onLine
|
||||||
`Is this a valid Mastodon instance?` :
|
? `Is this a valid Mastodon instance?`
|
||||||
`Are you offline?`)
|
: `Are you offline?`)
|
||||||
store.set({logInToInstanceError: error})
|
store.set({logInToInstanceError: error})
|
||||||
} finally {
|
} finally {
|
||||||
store.set({logInToInstanceLoading: false})
|
store.set({logInToInstanceLoading: false})
|
||||||
|
@ -95,4 +95,3 @@ export async function handleOauthCode(code) {
|
||||||
store.set({logInToInstanceLoading: false})
|
store.set({logInToInstanceLoading: false})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,9 +29,9 @@ export async function logOutOfInstance(instanceName) {
|
||||||
let loggedInInstancesInOrder = store.get('loggedInInstancesInOrder')
|
let loggedInInstancesInOrder = store.get('loggedInInstancesInOrder')
|
||||||
let currentInstance = store.get('currentInstance')
|
let currentInstance = store.get('currentInstance')
|
||||||
loggedInInstancesInOrder.splice(loggedInInstancesInOrder.indexOf(instanceName), 1)
|
loggedInInstancesInOrder.splice(loggedInInstancesInOrder.indexOf(instanceName), 1)
|
||||||
let newInstance = instanceName === currentInstance ?
|
let newInstance = instanceName === currentInstance
|
||||||
loggedInInstancesInOrder[0] :
|
? loggedInInstancesInOrder[0]
|
||||||
currentInstance
|
: currentInstance
|
||||||
delete loggedInInstances[instanceName]
|
delete loggedInInstances[instanceName]
|
||||||
delete instanceThemes[instanceName]
|
delete instanceThemes[instanceName]
|
||||||
store.set({
|
store.set({
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
|
import { post, paramsString } from '../_utils/ajax'
|
||||||
|
import { basename } from './utils'
|
||||||
|
|
||||||
const WEBSITE = 'https://pinafore.social'
|
const WEBSITE = 'https://pinafore.social'
|
||||||
const SCOPES = 'read write follow'
|
const SCOPES = 'read write follow'
|
||||||
const CLIENT_NAME = 'Pinafore'
|
const CLIENT_NAME = 'Pinafore'
|
||||||
import { post, get, paramsString } from '../_utils/ajax'
|
|
||||||
import { basename } from './utils'
|
|
||||||
|
|
||||||
export function registerApplication (instanceName, redirectUri) {
|
export function registerApplication (instanceName, redirectUri) {
|
||||||
const url = `${basename(instanceName)}/api/v1/apps`
|
const url = `${basename(instanceName)}/api/v1/apps`
|
||||||
|
|
|
@ -9,4 +9,3 @@ export function search(instanceName, accessToken, query) {
|
||||||
'Authorization': `Bearer ${accessToken}`
|
'Authorization': `Bearer ${accessToken}`
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,6 @@ virtualListStore.compute('heightWithoutFooter',
|
||||||
return sum
|
return sum
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
||||||
virtualListStore.compute('height',
|
virtualListStore.compute('height',
|
||||||
['heightWithoutFooter', 'showFooter', 'footerHeight'],
|
['heightWithoutFooter', 'showFooter', 'footerHeight'],
|
||||||
(heightWithoutFooter, showFooter, footerHeight) => {
|
(heightWithoutFooter, showFooter, footerHeight) => {
|
||||||
|
|
|
@ -3,17 +3,17 @@ import { accountsCache, relationshipsCache } from './cache'
|
||||||
import { getGenericEntityWithId, setGenericEntityWithId } from './helpers'
|
import { getGenericEntityWithId, setGenericEntityWithId } from './helpers'
|
||||||
|
|
||||||
export async function getAccount (instanceName, accountId) {
|
export async function getAccount (instanceName, accountId) {
|
||||||
return await getGenericEntityWithId(ACCOUNTS_STORE, accountsCache, instanceName, accountId)
|
return getGenericEntityWithId(ACCOUNTS_STORE, accountsCache, instanceName, accountId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setAccount (instanceName, account) {
|
export async function setAccount (instanceName, account) {
|
||||||
return await setGenericEntityWithId(ACCOUNTS_STORE, accountsCache, instanceName, account)
|
return setGenericEntityWithId(ACCOUNTS_STORE, accountsCache, instanceName, account)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getRelationship (instanceName, accountId) {
|
export async function getRelationship (instanceName, accountId) {
|
||||||
return await getGenericEntityWithId(RELATIONSHIPS_STORE, relationshipsCache, instanceName, accountId)
|
return getGenericEntityWithId(RELATIONSHIPS_STORE, relationshipsCache, instanceName, accountId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setRelationship (instanceName, relationship) {
|
export async function setRelationship (instanceName, relationship) {
|
||||||
return await setGenericEntityWithId(RELATIONSHIPS_STORE, relationshipsCache, instanceName, relationship)
|
return setGenericEntityWithId(RELATIONSHIPS_STORE, relationshipsCache, instanceName, relationship)
|
||||||
}
|
}
|
|
@ -1,8 +1,3 @@
|
||||||
const openReqs = {}
|
|
||||||
const databaseCache = {}
|
|
||||||
|
|
||||||
const DB_VERSION = 1
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
META_STORE,
|
META_STORE,
|
||||||
STATUS_TIMELINES_STORE,
|
STATUS_TIMELINES_STORE,
|
||||||
|
@ -13,6 +8,11 @@ import {
|
||||||
NOTIFICATION_TIMELINES_STORE
|
NOTIFICATION_TIMELINES_STORE
|
||||||
} from './constants'
|
} from './constants'
|
||||||
|
|
||||||
|
const openReqs = {}
|
||||||
|
const databaseCache = {}
|
||||||
|
|
||||||
|
const DB_VERSION = 1
|
||||||
|
|
||||||
export function getDatabase (instanceName) {
|
export function getDatabase (instanceName) {
|
||||||
if (!instanceName) {
|
if (!instanceName) {
|
||||||
throw new Error('instanceName is undefined in getDatabase()')
|
throw new Error('instanceName is undefined in getDatabase()')
|
||||||
|
@ -29,7 +29,7 @@ export function getDatabase(instanceName) {
|
||||||
console.log('idb blocked')
|
console.log('idb blocked')
|
||||||
}
|
}
|
||||||
req.onupgradeneeded = (e) => {
|
req.onupgradeneeded = (e) => {
|
||||||
let db = req.result;
|
let db = req.result
|
||||||
db.createObjectStore(META_STORE, {keyPath: 'key'})
|
db.createObjectStore(META_STORE, {keyPath: 'key'})
|
||||||
db.createObjectStore(STATUSES_STORE, {keyPath: 'id'})
|
db.createObjectStore(STATUSES_STORE, {keyPath: 'id'})
|
||||||
db.createObjectStore(ACCOUNTS_STORE, {keyPath: 'id'})
|
db.createObjectStore(ACCOUNTS_STORE, {keyPath: 'id'})
|
||||||
|
@ -46,25 +46,25 @@ export function getDatabase(instanceName) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function dbPromise (db, storeName, readOnlyOrReadWrite, cb) {
|
export async function dbPromise (db, storeName, readOnlyOrReadWrite, cb) {
|
||||||
return await new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const tx = db.transaction(storeName, readOnlyOrReadWrite)
|
const tx = db.transaction(storeName, readOnlyOrReadWrite)
|
||||||
let store = typeof storeName === 'string' ?
|
let store = typeof storeName === 'string'
|
||||||
tx.objectStore(storeName) :
|
? tx.objectStore(storeName)
|
||||||
storeName.map(name => tx.objectStore(name))
|
: storeName.map(name => tx.objectStore(name))
|
||||||
let res
|
let res
|
||||||
cb(store, (result) => {
|
cb(store, (result) => {
|
||||||
res = result
|
res = result
|
||||||
})
|
})
|
||||||
|
|
||||||
tx.oncomplete = () => resolve(res)
|
tx.oncomplete = () => resolve(res)
|
||||||
tx.onerror = () => reject(tx.error.name + ' ' + tx.error.message)
|
tx.onerror = () => reject(tx.error)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
export function deleteDatabase (instanceName) {
|
export function deleteDatabase (instanceName) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
// close any open requests
|
// close any open requests
|
||||||
let openReq = openReqs[instanceName];
|
let openReq = openReqs[instanceName]
|
||||||
if (openReq && openReq.result) {
|
if (openReq && openReq.result) {
|
||||||
openReq.result.close()
|
openReq.result.close()
|
||||||
}
|
}
|
||||||
|
@ -72,6 +72,6 @@ export function deleteDatabase(instanceName) {
|
||||||
delete databaseCache[instanceName]
|
delete databaseCache[instanceName]
|
||||||
let req = indexedDB.deleteDatabase(instanceName)
|
let req = indexedDB.deleteDatabase(instanceName)
|
||||||
req.onsuccess = () => resolve()
|
req.onsuccess = () => resolve()
|
||||||
req.onerror = () => reject(req.error.name + ' ' + req.error.message)
|
req.onerror = () => reject(req.error)
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -16,7 +16,7 @@ export async function getGenericEntityWithId(store, cache, instanceName, id) {
|
||||||
export async function setGenericEntityWithId (store, cache, instanceName, entity) {
|
export async function setGenericEntityWithId (store, cache, instanceName, entity) {
|
||||||
setInCache(cache, instanceName, entity.id, entity)
|
setInCache(cache, instanceName, entity.id, entity)
|
||||||
const db = await getDatabase(instanceName)
|
const db = await getDatabase(instanceName)
|
||||||
return await dbPromise(db, store, 'readwrite', (store) => {
|
return dbPromise(db, store, 'readwrite', (store) => {
|
||||||
store.put(entity)
|
store.put(entity)
|
||||||
})
|
})
|
||||||
}
|
}
|
|
@ -19,7 +19,7 @@ async function getMetaProperty(instanceName, key) {
|
||||||
async function setMetaProperty (instanceName, key, value) {
|
async function setMetaProperty (instanceName, key, value) {
|
||||||
setInCache(metaCache, instanceName, 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 dbPromise(db, META_STORE, 'readwrite', (store) => {
|
||||||
store.put({
|
store.put({
|
||||||
key: key,
|
key: key,
|
||||||
value: value
|
value: value
|
||||||
|
@ -28,25 +28,25 @@ async function setMetaProperty(instanceName, key, value) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getInstanceVerifyCredentials (instanceName) {
|
export async function getInstanceVerifyCredentials (instanceName) {
|
||||||
return await getMetaProperty(instanceName, 'verifyCredentials')
|
return getMetaProperty(instanceName, 'verifyCredentials')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setInstanceVerifyCredentials (instanceName, value) {
|
export async function setInstanceVerifyCredentials (instanceName, value) {
|
||||||
return await setMetaProperty(instanceName, 'verifyCredentials', value)
|
return setMetaProperty(instanceName, 'verifyCredentials', value)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getInstanceInfo (instanceName) {
|
export async function getInstanceInfo (instanceName) {
|
||||||
return await getMetaProperty(instanceName, 'instance')
|
return getMetaProperty(instanceName, 'instance')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setInstanceInfo (instanceName, value) {
|
export async function setInstanceInfo (instanceName, value) {
|
||||||
return await setMetaProperty(instanceName, 'instance', value)
|
return setMetaProperty(instanceName, 'instance', value)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getLists (instanceName) {
|
export async function getLists (instanceName) {
|
||||||
return await getMetaProperty(instanceName, 'lists')
|
return getMetaProperty(instanceName, 'lists')
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function setLists (instanceName, value) {
|
export async function setLists (instanceName, value) {
|
||||||
return await setMetaProperty(instanceName, 'lists', value)
|
return setMetaProperty(instanceName, 'lists', value)
|
||||||
}
|
}
|
|
@ -17,7 +17,7 @@ function createKeyRange(timeline, maxId) {
|
||||||
async function getNotificationTimeline (instanceName, timeline, maxId, limit) {
|
async function getNotificationTimeline (instanceName, timeline, maxId, limit) {
|
||||||
let storeNames = [NOTIFICATION_TIMELINES_STORE, NOTIFICATIONS_STORE]
|
let storeNames = [NOTIFICATION_TIMELINES_STORE, NOTIFICATIONS_STORE]
|
||||||
const db = await getDatabase(instanceName)
|
const db = await getDatabase(instanceName)
|
||||||
return await dbPromise(db, storeNames, 'readonly', (stores, callback) => {
|
return dbPromise(db, storeNames, 'readonly', (stores, callback) => {
|
||||||
let [ timelineStore, notificationsStore ] = stores
|
let [ timelineStore, notificationsStore ] = stores
|
||||||
let keyRange = createKeyRange(timeline, maxId)
|
let keyRange = createKeyRange(timeline, maxId)
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ async function getNotificationTimeline(instanceName, timeline, maxId, limit) {
|
||||||
async function getStatusTimeline (instanceName, timeline, maxId, limit) {
|
async function getStatusTimeline (instanceName, timeline, maxId, limit) {
|
||||||
let storeNames = [STATUS_TIMELINES_STORE, STATUSES_STORE]
|
let storeNames = [STATUS_TIMELINES_STORE, STATUSES_STORE]
|
||||||
const db = await getDatabase(instanceName)
|
const db = await getDatabase(instanceName)
|
||||||
return await dbPromise(db, storeNames, 'readonly', (stores, callback) => {
|
return dbPromise(db, storeNames, 'readonly', (stores, callback) => {
|
||||||
let [ timelineStore, statusesStore ] = stores
|
let [ timelineStore, statusesStore ] = stores
|
||||||
let keyRange = createKeyRange(timeline, maxId)
|
let keyRange = createKeyRange(timeline, maxId)
|
||||||
|
|
||||||
|
@ -55,9 +55,9 @@ async function getStatusTimeline(instanceName, timeline, maxId, limit) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getTimeline (instanceName, timeline, maxId = null, limit = 20) {
|
export async function getTimeline (instanceName, timeline, maxId = null, limit = 20) {
|
||||||
return timeline === 'notifications' ?
|
return timeline === 'notifications'
|
||||||
await getNotificationTimeline(instanceName, timeline, maxId, limit) :
|
? getNotificationTimeline(instanceName, timeline, maxId, limit)
|
||||||
await getStatusTimeline(instanceName, timeline, maxId, limit)
|
: getStatusTimeline(instanceName, timeline, maxId, limit)
|
||||||
}
|
}
|
||||||
|
|
||||||
function createTimelineId (timeline, id) {
|
function createTimelineId (timeline, id) {
|
||||||
|
@ -112,15 +112,15 @@ async function insertTimelineStatuses(instanceName, timeline, statuses) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function insertTimelineItems (instanceName, timeline, timelineItems) {
|
export async function insertTimelineItems (instanceName, timeline, timelineItems) {
|
||||||
return timeline === 'notifications' ?
|
return timeline === 'notifications'
|
||||||
await insertTimelineNotifications(instanceName, timeline, timelineItems) :
|
? insertTimelineNotifications(instanceName, timeline, timelineItems)
|
||||||
await insertTimelineStatuses(instanceName, timeline, timelineItems)
|
: insertTimelineStatuses(instanceName, timeline, timelineItems)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getStatus (instanceName, statusId) {
|
export async function getStatus (instanceName, statusId) {
|
||||||
return await getGenericEntityWithId(STATUSES_STORE, statusesCache, instanceName, statusId)
|
return getGenericEntityWithId(STATUSES_STORE, statusesCache, instanceName, statusId)
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function getNotification (instanceName, notificationId) {
|
export async function getNotification (instanceName, notificationId) {
|
||||||
return await getGenericEntityWithId(NOTIFICATIONS_STORE, notificationsCache, instanceName, notificationId)
|
return getGenericEntityWithId(NOTIFICATIONS_STORE, notificationsCache, instanceName, notificationId)
|
||||||
}
|
}
|
|
@ -70,5 +70,4 @@ export function instanceComputations(store) {
|
||||||
return list ? list.title : ''
|
return list ? list.title : ''
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
}
|
}
|
|
@ -4,16 +4,16 @@ import { mixins } from './mixins'
|
||||||
import { LocalStorageStore } from './LocalStorageStore'
|
import { LocalStorageStore } from './LocalStorageStore'
|
||||||
|
|
||||||
const KEYS_TO_STORE_IN_LOCAL_STORAGE = new Set([
|
const KEYS_TO_STORE_IN_LOCAL_STORAGE = new Set([
|
||||||
"currentInstance",
|
'currentInstance',
|
||||||
"currentRegisteredInstance",
|
'currentRegisteredInstance',
|
||||||
"currentRegisteredInstanceName",
|
'currentRegisteredInstanceName',
|
||||||
"instanceNameInSearch",
|
'instanceNameInSearch',
|
||||||
"instanceThemes",
|
'instanceThemes',
|
||||||
"loggedInInstances",
|
'loggedInInstances',
|
||||||
"loggedInInstancesInOrder",
|
'loggedInInstancesInOrder',
|
||||||
"autoplayGifs",
|
'autoplayGifs',
|
||||||
"markMediaAsSensitive",
|
'markMediaAsSensitive',
|
||||||
"pinnedPages"
|
'pinnedPages'
|
||||||
])
|
])
|
||||||
|
|
||||||
class PinaforeStore extends LocalStorageStore {
|
class PinaforeStore extends LocalStorageStore {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
export async function post (url, body) {
|
export async function post (url, body) {
|
||||||
return await (await fetch(url, {
|
return (await fetch(url, {
|
||||||
method: 'POST',
|
method: 'POST',
|
||||||
headers: {
|
headers: {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json',
|
||||||
|
@ -18,10 +18,10 @@ export function paramsString(paramsObject) {
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function get (url, headers = {}) {
|
export async function get (url, headers = {}) {
|
||||||
return await (await fetch(url, {
|
return (await fetch(url, {
|
||||||
method: 'GET',
|
method: 'GET',
|
||||||
headers: Object.assign(headers, {
|
headers: Object.assign(headers, {
|
||||||
'Accept': 'application/json',
|
'Accept': 'application/json'
|
||||||
})
|
})
|
||||||
})).json()
|
})).json()
|
||||||
}
|
}
|
|
@ -20,10 +20,10 @@ export function imgLoad (node, callback) {
|
||||||
|
|
||||||
export function mouseover (node, callback) {
|
export function mouseover (node, callback) {
|
||||||
function onMouseEnter () {
|
function onMouseEnter () {
|
||||||
callback(true)
|
callback(true) // eslint-disable-line
|
||||||
}
|
}
|
||||||
function onMouseLeave () {
|
function onMouseLeave () {
|
||||||
callback(false)
|
callback(false) // eslint-disable-line
|
||||||
}
|
}
|
||||||
node.addEventListener('mouseenter', onMouseEnter)
|
node.addEventListener('mouseenter', onMouseEnter)
|
||||||
node.addEventListener('mouseleave', onMouseLeave)
|
node.addEventListener('mouseleave', onMouseLeave)
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
export const isFullscreen = () => !!(document.fullscreenElement ||
|
export const isFullscreen = () => !!(document.fullscreenElement ||
|
||||||
document.webkitFullscreenElement ||
|
document.webkitFullscreenElement ||
|
||||||
document.mozFullScreenElement);
|
document.mozFullScreenElement)
|
||||||
|
|
||||||
export const attachFullscreenListener = (listener) => {
|
export const attachFullscreenListener = (listener) => {
|
||||||
if ('onfullscreenchange' in document) {
|
if ('onfullscreenchange' in document) {
|
||||||
document.addEventListener('fullscreenchange', listener);
|
document.addEventListener('fullscreenchange', listener)
|
||||||
} else if ('onwebkitfullscreenchange' in document) {
|
} else if ('onwebkitfullscreenchange' in document) {
|
||||||
document.addEventListener('webkitfullscreenchange', listener);
|
document.addEventListener('webkitfullscreenchange', listener)
|
||||||
} else if ('onmozfullscreenchange' in document) {
|
} else if ('onmozfullscreenchange' in document) {
|
||||||
document.addEventListener('mozfullscreenchange', listener);
|
document.addEventListener('mozfullscreenchange', listener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
||||||
|
|
||||||
export const detachFullscreenListener = (listener) => {
|
export const detachFullscreenListener = (listener) => {
|
||||||
if ('onfullscreenchange' in document) {
|
if ('onfullscreenchange' in document) {
|
||||||
document.removeEventListener('fullscreenchange', listener);
|
document.removeEventListener('fullscreenchange', listener)
|
||||||
} else if ('onwebkitfullscreenchange' in document) {
|
} else if ('onwebkitfullscreenchange' in document) {
|
||||||
document.removeEventListener('webkitfullscreenchange', listener);
|
document.removeEventListener('webkitfullscreenchange', listener)
|
||||||
} else if ('onmozfullscreenchange' in document) {
|
} else if ('onmozfullscreenchange' in document) {
|
||||||
document.removeEventListener('mozfullscreenchange', listener);
|
document.removeEventListener('mozfullscreenchange', listener)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
|
|
@ -1,18 +1,18 @@
|
||||||
// Get the bounding client rect from an IntersectionObserver entry.
|
// Get the bounding client rect from an IntersectionObserver entry.
|
||||||
// This is to work around a bug in Chrome: https://crbug.com/737228
|
// This is to work around a bug in Chrome: https://crbug.com/737228
|
||||||
|
|
||||||
let hasBoundingRectBug;
|
let hasBoundingRectBug
|
||||||
|
|
||||||
export function getRectFromEntry (entry) {
|
export function getRectFromEntry (entry) {
|
||||||
if (typeof hasBoundingRectBug !== 'boolean') {
|
if (typeof hasBoundingRectBug !== 'boolean') {
|
||||||
const boundingRect = entry.target.getBoundingClientRect();
|
const boundingRect = entry.target.getBoundingClientRect()
|
||||||
const observerRect = entry.boundingClientRect;
|
const observerRect = entry.boundingClientRect
|
||||||
hasBoundingRectBug = boundingRect.height !== observerRect.height ||
|
hasBoundingRectBug = boundingRect.height !== observerRect.height ||
|
||||||
boundingRect.top !== observerRect.top ||
|
boundingRect.top !== observerRect.top ||
|
||||||
boundingRect.width !== observerRect.width ||
|
boundingRect.width !== observerRect.width ||
|
||||||
boundingRect.bottom !== observerRect.bottom ||
|
boundingRect.bottom !== observerRect.bottom ||
|
||||||
boundingRect.left !== observerRect.left ||
|
boundingRect.left !== observerRect.left ||
|
||||||
boundingRect.right !== observerRect.right;
|
boundingRect.right !== observerRect.right
|
||||||
}
|
}
|
||||||
return hasBoundingRectBug ? entry.target.getBoundingClientRect() : entry.boundingClientRect;
|
return hasBoundingRectBug ? entry.target.getBoundingClientRect() : entry.boundingClientRect
|
||||||
}
|
}
|
|
@ -2,8 +2,7 @@ import {
|
||||||
importURLSearchParams,
|
importURLSearchParams,
|
||||||
importIntersectionObserver,
|
importIntersectionObserver,
|
||||||
importRequestIdleCallback,
|
importRequestIdleCallback,
|
||||||
importIndexedDBGetAllShim,
|
importIndexedDBGetAllShim
|
||||||
importDialogPolyfill
|
|
||||||
} from './asyncModules'
|
} from './asyncModules'
|
||||||
|
|
||||||
export function loadPolyfills () {
|
export function loadPolyfills () {
|
||||||
|
|
|
@ -19,8 +19,7 @@ const observe = online => {
|
||||||
meta.content = oldTheme || window.__themeColors['default']
|
meta.content = oldTheme || window.__themeColors['default']
|
||||||
} else {
|
} else {
|
||||||
let offlineThemeColor = window.__themeColors.offline
|
let offlineThemeColor = window.__themeColors.offline
|
||||||
if (meta.content !== offlineThemeColor)
|
if (meta.content !== offlineThemeColor) { oldTheme = meta.content }
|
||||||
oldTheme = meta.content
|
|
||||||
meta.content = offlineThemeColor
|
meta.content = offlineThemeColor
|
||||||
notifyOffline()
|
notifyOffline()
|
||||||
}
|
}
|
||||||
|
@ -30,5 +29,5 @@ if (!navigator.onLine) {
|
||||||
observe(false)
|
observe(false)
|
||||||
}
|
}
|
||||||
|
|
||||||
window.addEventListener('offline', () => observe(false));
|
window.addEventListener('offline', () => observe(false))
|
||||||
window.addEventListener('online', () => observe(true));
|
window.addEventListener('online', () => observe(true))
|
||||||
|
|
|
@ -7,7 +7,7 @@ function onUpdateFound(registration) {
|
||||||
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
|
if (newWorker.state === 'installed' && navigator.serviceWorker.controller) {
|
||||||
toast.say('Update available. Refresh to update.')
|
toast.say('Update available. Refresh to update.')
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!location.origin.match('localhost') && 'serviceWorker' in navigator) {
|
if (!location.origin.match('localhost') && 'serviceWorker' in navigator) {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { loadCSS } from 'fg-loadcss';
|
import { loadCSS } from 'fg-loadcss'
|
||||||
|
|
||||||
let meta = process.browser && document.querySelector('meta[name="theme-color"]')
|
let meta = process.browser && document.querySelector('meta[name="theme-color"]')
|
||||||
|
|
||||||
|
|
29
server.js
29
server.js
|
@ -1,24 +1,23 @@
|
||||||
const fs = require('fs');
|
const app = require('express')()
|
||||||
const app = require('express')();
|
const compression = require('compression')
|
||||||
const compression = require('compression');
|
const sapper = require('sapper')
|
||||||
const sapper = require('sapper');
|
const serveStatic = require('serve-static')
|
||||||
const static = require('serve-static');
|
|
||||||
|
|
||||||
const { PORT = 4002 } = process.env;
|
const { PORT = 4002 } = process.env
|
||||||
|
|
||||||
// this allows us to do e.g. `fetch('/_api/blog')` on the server
|
// this allows us to do e.g. `fetch('/_api/blog')` on the server
|
||||||
const fetch = require('node-fetch');
|
const fetch = require('node-fetch')
|
||||||
global.fetch = (url, opts) => {
|
global.fetch = (url, opts) => {
|
||||||
if (url[0] === '/') url = `http://localhost:${PORT}${url}`;
|
if (url[0] === '/') url = `http://localhost:${PORT}${url}`
|
||||||
return fetch(url, opts);
|
return fetch(url, opts)
|
||||||
};
|
}
|
||||||
|
|
||||||
app.use(compression({ threshold: 0 }));
|
app.use(compression({ threshold: 0 }))
|
||||||
|
|
||||||
app.use(static('assets'));
|
app.use(serveStatic('assets'))
|
||||||
|
|
||||||
app.use(sapper());
|
app.use(sapper())
|
||||||
|
|
||||||
app.listen(PORT, () => {
|
app.listen(PORT, () => {
|
||||||
console.log(`listening on port ${PORT}`);
|
console.log(`listening on port ${PORT}`)
|
||||||
});
|
})
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
|
/* global __routes__ */
|
||||||
|
|
||||||
import { init } from 'sapper/runtime.js'
|
import { init } from 'sapper/runtime.js'
|
||||||
import { offlineNotifiction } from '../routes/_utils/offlineNotification'
|
import { offlineNotifiction } from '../routes/_utils/offlineNotification'
|
||||||
import { serviceWorkerClient } from '../routes/_utils/serviceWorkerClient'
|
import { serviceWorkerClient } from '../routes/_utils/serviceWorkerClient'
|
||||||
import { loadPolyfills } from '../routes/_utils/loadPolyfills'
|
import { loadPolyfills } from '../routes/_utils/loadPolyfills'
|
||||||
|
|
||||||
|
console.log(offlineNotifiction, serviceWorkerClient)
|
||||||
|
|
||||||
loadPolyfills().then(() => {
|
loadPolyfills().then(() => {
|
||||||
// `routes` is an array of route objects injected by Sapper
|
// `routes` is an array of route objects injected by Sapper
|
||||||
init(document.querySelector('#sapper'), __routes__)
|
init(document.querySelector('#sapper'), __routes__)
|
||||||
|
|
|
@ -1,10 +1,12 @@
|
||||||
|
/* global self, caches, __shell__, __assets__, __routes__ */
|
||||||
|
|
||||||
const timestamp = '__timestamp__'
|
const timestamp = '__timestamp__'
|
||||||
const ASSETS = `cache${timestamp}`
|
const ASSETS = `cache${timestamp}`
|
||||||
|
|
||||||
// `shell` is an array of all the files generated by webpack,
|
// `shell` is an array of all the files generated by webpack,
|
||||||
// `assets` is an array of everything in the `assets` directory
|
// `assets` is an array of everything in the `assets` directory
|
||||||
const to_cache = __shell__.concat(__assets__)
|
const toCache = __shell__.concat(__assets__)
|
||||||
const cached = new Set(to_cache)
|
const cached = new Set(toCache)
|
||||||
|
|
||||||
// `routes` is an array of `{ pattern: RegExp }` objects that
|
// `routes` is an array of `{ pattern: RegExp }` objects that
|
||||||
// match the pages in your app
|
// match the pages in your app
|
||||||
|
@ -14,7 +16,7 @@ self.addEventListener('install', event => {
|
||||||
event.waitUntil(
|
event.waitUntil(
|
||||||
caches
|
caches
|
||||||
.open(ASSETS)
|
.open(ASSETS)
|
||||||
.then(cache => cache.addAll(to_cache))
|
.then(cache => cache.addAll(toCache))
|
||||||
.then(() => {
|
.then(() => {
|
||||||
self.skipWaiting()
|
self.skipWaiting()
|
||||||
})
|
})
|
||||||
|
|
|
@ -4,7 +4,7 @@ const UglifyJSPlugin = require('uglifyjs-webpack-plugin')
|
||||||
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
|
||||||
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
|
const LodashModuleReplacementPlugin = require('lodash-webpack-plugin')
|
||||||
|
|
||||||
const isDev = config.dev;
|
const isDev = config.dev
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: config.client.entry(),
|
entry: config.client.entry(),
|
||||||
|
@ -82,11 +82,11 @@ module.exports = {
|
||||||
generateStatsFile: true,
|
generateStatsFile: true,
|
||||||
statsOptions: {
|
statsOptions: {
|
||||||
// allows usage with http://chrisbateman.github.io/webpack-visualizer/
|
// allows usage with http://chrisbateman.github.io/webpack-visualizer/
|
||||||
chunkModules: true,
|
chunkModules: true
|
||||||
},
|
},
|
||||||
openAnalyzer: false,
|
openAnalyzer: false,
|
||||||
logLevel: 'silent', // do not bother Webpacker, who runs with --json and parses stdout
|
logLevel: 'silent' // do not bother Webpacker, who runs with --json and parses stdout
|
||||||
}),
|
})
|
||||||
]).filter(Boolean),
|
]).filter(Boolean),
|
||||||
devtool: isDev && 'inline-source-map'
|
devtool: isDev && 'inline-source-map'
|
||||||
};
|
}
|
||||||
|
|
|
@ -1,7 +1,4 @@
|
||||||
const config = require('sapper/webpack/config.js');
|
const config = require('sapper/webpack/config.js')
|
||||||
const webpack = require('webpack');
|
|
||||||
const ExtractTextPlugin = require("extract-text-webpack-plugin");
|
|
||||||
const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
entry: config.server.entry(),
|
entry: config.server.entry(),
|
||||||
|
@ -27,4 +24,4 @@ module.exports = {
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
|
|
Loading…
Reference in a new issue