fix: detect private browsing and safari blocked cookies (#733)
* WIP: detect private browsing and safari blocked cookies * just check for indexeddb * just check for indexeddb * change warning text * change text * change text again * change text again fixes #444
This commit is contained in:
parent
c0f857336a
commit
0e524f3e9a
|
@ -3,7 +3,17 @@
|
|||
// the build process and write it to inline-script-checksum.json.
|
||||
window.__themeColors = process.env.THEME_COLORS
|
||||
|
||||
if (localStorage.store_currentInstance && localStorage.store_instanceThemes) {
|
||||
const hasLocalStorage = (() => {
|
||||
try {
|
||||
// iOS safari throws here if cookies are disabled
|
||||
let unused = localStorage.length // eslint-disable-line
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
})()
|
||||
|
||||
if (hasLocalStorage && localStorage.store_currentInstance && localStorage.store_instanceThemes) {
|
||||
let safeParse = (str) => str === 'undefined' ? undefined : JSON.parse(str)
|
||||
let theme = safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)]
|
||||
if (theme && theme !== 'default') {
|
||||
|
@ -18,14 +28,14 @@ if (localStorage.store_currentInstance && localStorage.store_instanceThemes) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!localStorage.store_currentInstance) {
|
||||
if (!hasLocalStorage || !localStorage.store_currentInstance) {
|
||||
// if not logged in, show all these 'hidden-from-ssr' elements
|
||||
let style = document.createElement('style')
|
||||
style.textContent = '.hidden-from-ssr { opacity: 1 !important; }'
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
|
||||
if (localStorage.store_disableCustomScrollbars === 'true') {
|
||||
if (hasLocalStorage && localStorage.store_disableCustomScrollbars === 'true') {
|
||||
// if user has disabled custom scrollbars, remove this style
|
||||
let theScrollbarStyle = document.getElementById('theScrollbarStyle')
|
||||
theScrollbarStyle.setAttribute('media', 'only x') // disables the style
|
||||
|
|
5
package-lock.json
generated
5
package-lock.json
generated
|
@ -6003,6 +6003,11 @@
|
|||
"json5": "^0.5.0"
|
||||
}
|
||||
},
|
||||
"localstorage-memory": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/localstorage-memory/-/localstorage-memory-1.0.3.tgz",
|
||||
"integrity": "sha512-t9P8WB6DcVttbw/W4PIE8HOqum8Qlvx5SjR6oInwR9Uia0EEmyUeBh7S+weKByW+l/f45Bj4L/dgZikGFDM6ng=="
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
|
||||
|
|
|
@ -72,6 +72,7 @@
|
|||
"idb-keyval": "^3.1.0",
|
||||
"indexeddb-getall-shim": "^1.3.5",
|
||||
"intersection-observer": "^0.5.1",
|
||||
"localstorage-memory": "^1.0.3",
|
||||
"lodash-es": "^4.17.11",
|
||||
"lodash-webpack-plugin": "^0.11.5",
|
||||
"mini-css-extract-plugin": "^0.4.5",
|
||||
|
|
|
@ -3,6 +3,14 @@
|
|||
|
||||
<form class="add-new-instance" on:submit='onSubmit(event)' aria-labelledby="add-an-instance-h1">
|
||||
|
||||
{#if !hasIndexedDB}
|
||||
<div class="form-error form-error-user-error" role="alert">
|
||||
Your browser doesn't support IndexedDB, possibly because it's in private browsing mode
|
||||
or blocking cookies. Pinafore stores all data locally, and requires IndexedDB to work
|
||||
correctly.
|
||||
</div>
|
||||
{/if}
|
||||
|
||||
{#if $logInToInstanceError && $logInToInstanceErrorForText === $instanceNameInSearch}
|
||||
<div class="form-error form-error-user-error" role="alert">
|
||||
Error: {$logInToInstanceError}
|
||||
|
@ -69,19 +77,25 @@
|
|||
import { store } from '../../../_store/store'
|
||||
import { logInToInstance, handleOauthCode } from '../../../_actions/addInstance'
|
||||
import ExternalLink from '../../../_components/ExternalLink.html'
|
||||
import { testHasIndexedDB } from '../../../_utils/testStorage'
|
||||
|
||||
export default {
|
||||
async oncreate () {
|
||||
let codeMatch = location.search.match(/code=([^&]+)/)
|
||||
if (codeMatch) {
|
||||
handleOauthCode(codeMatch[1])
|
||||
return handleOauthCode(codeMatch[1])
|
||||
}
|
||||
let hasIndexedDB = await testHasIndexedDB()
|
||||
this.set({ hasIndexedDB })
|
||||
},
|
||||
components: {
|
||||
SettingsLayout,
|
||||
ExternalLink
|
||||
},
|
||||
store: () => store,
|
||||
data: () => ({
|
||||
hasIndexedDB: true
|
||||
}),
|
||||
methods: {
|
||||
onSubmit (event) {
|
||||
event.preventDefault()
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { Store } from 'svelte/store'
|
||||
import { safeLocalStorage as LS } from '../_utils/safeLocalStorage'
|
||||
|
||||
let lifecycle
|
||||
if (process.browser) {
|
||||
lifecycle = require('page-lifecycle/dist/lifecycle.mjs').default
|
||||
}
|
||||
|
||||
const LS = process.browser && localStorage
|
||||
|
||||
function safeParse (str) {
|
||||
return !str ? undefined : (str === 'undefined' ? undefined : JSON.parse(str))
|
||||
}
|
||||
|
|
6
routes/_utils/safeLocalStorage.js
Normal file
6
routes/_utils/safeLocalStorage.js
Normal file
|
@ -0,0 +1,6 @@
|
|||
import localStorageMemory from 'localstorage-memory'
|
||||
import { testHasLocalStorage } from './testStorage'
|
||||
|
||||
const safeLocalStorage = testHasLocalStorage() ? localStorage : localStorageMemory
|
||||
|
||||
export { safeLocalStorage }
|
42
routes/_utils/testStorage.js
Normal file
42
routes/_utils/testStorage.js
Normal file
|
@ -0,0 +1,42 @@
|
|||
// LocalStorage and IDB may be disabled in private mode, when "blocking cookies" in Safari,
|
||||
// or other cases
|
||||
|
||||
import { thunk } from './thunk'
|
||||
|
||||
const testKey = '__test__'
|
||||
|
||||
export const testHasLocalStorage = thunk(() => {
|
||||
try {
|
||||
localStorage.setItem(testKey, testKey)
|
||||
if (!localStorage.length || localStorage.getItem(testKey) !== testKey) {
|
||||
return false
|
||||
}
|
||||
localStorage.removeItem(testKey)
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
||||
|
||||
export const testHasIndexedDB = thunk(async () => {
|
||||
if (typeof indexedDB === 'undefined') {
|
||||
return false
|
||||
}
|
||||
|
||||
try {
|
||||
let idbFailed = await new Promise(resolve => {
|
||||
let db = indexedDB.open(testKey)
|
||||
db.onerror = () => resolve(true)
|
||||
db.onsuccess = () => {
|
||||
indexedDB.deleteDatabase(testKey)
|
||||
resolve(false)
|
||||
}
|
||||
})
|
||||
if (idbFailed) {
|
||||
return false
|
||||
}
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
})
|
11
routes/_utils/thunk.js
Normal file
11
routes/_utils/thunk.js
Normal file
|
@ -0,0 +1,11 @@
|
|||
export function thunk (func) {
|
||||
let cached
|
||||
let runOnce
|
||||
return () => {
|
||||
if (!runOnce) {
|
||||
cached = func()
|
||||
runOnce = true
|
||||
}
|
||||
return cached
|
||||
}
|
||||
}
|
|
@ -52,7 +52,17 @@ html{scrollbar-face-color:var(--scrollbar-face-color);scrollbar-track-color:var(
|
|||
// the build process and write it to inline-script-checksum.json.
|
||||
window.__themeColors = {"default":"royalblue","scarlet":"#e04e41","seafoam":"#177380","hotpants":"hotpink","oaken":"saddlebrown","majesty":"blueviolet","gecko":"#4ab92f","ozark":"#5263af","cobalt":"#08439b","sorcery":"#ae91e8","punk":"#e04e41","riot":"hotpink","hacker":"#4ab92f","pitchblack":"#000"}
|
||||
|
||||
if (localStorage.store_currentInstance && localStorage.store_instanceThemes) {
|
||||
const hasLocalStorage = (() => {
|
||||
try {
|
||||
// iOS safari throws here if cookies are disabled
|
||||
let unused = localStorage.length // eslint-disable-line
|
||||
return true
|
||||
} catch (e) {
|
||||
return false
|
||||
}
|
||||
})()
|
||||
|
||||
if (hasLocalStorage && localStorage.store_currentInstance && localStorage.store_instanceThemes) {
|
||||
let safeParse = (str) => str === 'undefined' ? undefined : JSON.parse(str)
|
||||
let theme = safeParse(localStorage.store_instanceThemes)[safeParse(localStorage.store_currentInstance)]
|
||||
if (theme && theme !== 'default') {
|
||||
|
@ -67,14 +77,14 @@ if (localStorage.store_currentInstance && localStorage.store_instanceThemes) {
|
|||
}
|
||||
}
|
||||
|
||||
if (!localStorage.store_currentInstance) {
|
||||
if (!hasLocalStorage || !localStorage.store_currentInstance) {
|
||||
// if not logged in, show all these 'hidden-from-ssr' elements
|
||||
let style = document.createElement('style')
|
||||
style.textContent = '.hidden-from-ssr { opacity: 1 !important; }'
|
||||
document.head.appendChild(style)
|
||||
}
|
||||
|
||||
if (localStorage.store_disableCustomScrollbars === 'true') {
|
||||
if (hasLocalStorage && localStorage.store_disableCustomScrollbars === 'true') {
|
||||
// if user has disabled custom scrollbars, remove this style
|
||||
let theScrollbarStyle = document.getElementById('theScrollbarStyle')
|
||||
theScrollbarStyle.setAttribute('media', 'only x') // disables the style
|
||||
|
|
Loading…
Reference in a new issue