1
0
mirror of synced 2025-11-06 04:21:11 +08:00

Fix: Safari private browsing

This commit is contained in:
surunzi
2016-12-30 19:19:28 +08:00
parent d0444e65b5
commit 5467df54d1
7 changed files with 211 additions and 22 deletions

30
eustia/safeStorage.js Normal file
View File

@@ -0,0 +1,30 @@
_('isUndef memStorage');
function exports(type, memReplacement)
{
if (isUndef(memReplacement)) memReplacement = true;
var ret;
switch (type)
{
case 'local': ret = window.localStorage; break;
case 'session': ret = window.sessionStorage; break;
}
try
{
// Safari private browsing
var x = 'test-localStorage-' + Date.now();
ret.setItem(x, x);
var y = ret.getItem(x);
ret.removeItem(x);
if (y !== x) throw new Error();
} catch (e)
{
if (memReplacement) return memStorage;
return;
}
return ret;
}

View File

@@ -152,5 +152,7 @@ export default class DevTools extends util.Emitter
}
}
var activeEruda = flag => window.localStorage.setItem('active-eruda', flag);
var localStore = util.safeStorage('local');
var activeEruda = flag => localStore.setItem('active-eruda', flag);

View File

@@ -2,7 +2,7 @@
{{#each messages}}
<li>
<h2 class="eruda-title">{{name}}</h2>
<p class="eruda-content">{{val}}</p>
<div class="eruda-content">{{{val}}}</div>
</li>
{{/each}}
</ul>
</ul>

View File

@@ -87,14 +87,21 @@ export default class Resources extends Tool
}
_refreshStorage(type)
{
var store = util.safeStorage(type, false);
if (!store) return;
var storeData = [];
// Mobile safari is not able to loop through localStorage directly.
var store = JSON.parse(JSON.stringify(window[type + 'Storage']));
store = JSON.parse(JSON.stringify(store));
util.each(store, (val, key) =>
{
if (this._hideErudaSetting && util.startWith(key, 'eruda')) return;
if (this._hideErudaSetting)
{
if (util.startWith(key, 'eruda') || key === 'active-eruda') return;
}
storeData.push({
key: key,

View File

@@ -64,6 +64,7 @@
padding: $padding;
font-size: $font-size-s;
margin-bottom: 10px;
white-space: pre-wrap;
}
}
iframe {

View File

@@ -1,7 +1,7 @@
import util from './util';
var localStore = {
_storage: window.localStorage,
_storage: util.safeStorage('local'),
get(key)
{
var val = this._storage.getItem(key);

View File

@@ -389,7 +389,7 @@ module.exports = (function ()
var idxOf = _.idxOf = (function ()
{
/* Get the index at which the first occurrence of value. TODO
/* Get the index at which the first occurrence of value.
*
* |Name |Type |Desc |
* |-----------|------|--------------------|
@@ -404,7 +404,7 @@ module.exports = (function ()
function exports(arr, val, fromIdx)
{
return Array.prototype.indexOf.call(arr, val);
return Array.prototype.indexOf.call(arr, val, fromIdx);
}
return exports;
@@ -1577,6 +1577,92 @@ module.exports = (function ()
return exports;
})();
/* ------------------------------ memStorage ------------------------------ */
var memStorage = _.memStorage = (function (exports)
{
/* Memory-backed implementation of the Web Storage API.
*
* A replacement for environments where localStorage or sessionStorage is not available.
*
* ```javascript
* var localStorage = window.localStorage || memStorage;
* localStorage.setItem('test', 'eris');
* ```
*/
exports = {
getItem: function (key)
{
return (API_KEYS[key] ? cloak[key] : this[key]) || null;
},
setItem: function (key, val)
{
API_KEYS[key] ? cloak[key] = val : this[key] = val;
},
removeItem: function (key)
{
API_KEYS[key] ? delete cloak[key] : delete this[key];
},
key: function (i)
{
var keys = enumerableKeys();
return i >= 0 && i < keys.length ? keys[i] : null;
},
clear: function ()
{
var keys = uncloakedKeys();
for (var i = 0, key; key = keys[i]; i++) delete this[key];
keys = cloakedKeys();
for (i = 0; key = keys[i]; i++) delete cloak[key];
}
};
Object.defineProperty(exports, 'length', {
enumerable: false,
configurable: true,
get: function ()
{
return enumerableKeys().length;
}
});
var cloak = {};
var API_KEYS = {
getItem: 1,
setItem: 1,
removeItem: 1,
key: 1,
clear: 1,
length: 1
};
function enumerableKeys()
{
return uncloakedKeys().concat(cloakedKeys());
}
function uncloakedKeys()
{
return keys(exports).filter(function (key)
{
return !API_KEYS[key];
});
}
function cloakedKeys()
{
return keys(cloak);
}
return exports;
})({});
/* ------------------------------ noop ------------------------------ */
var noop = _.noop = (function ()
@@ -1616,32 +1702,32 @@ module.exports = (function ()
var optimizeCb = _.optimizeCb = (function ()
{
/* TODO
/* Used for function context binding.
*/
function exports(func, ctx, argCount)
function exports(fn, ctx, argCount)
{
if (isUndef(ctx)) return func;
if (isUndef(ctx)) return fn;
switch (argCount == null ? 3 : argCount)
{
case 1: return function (val)
{
return func.call(ctx, val);
return fn.call(ctx, val);
};
case 3: return function (val, idx, collection)
{
return func.call(ctx, val, idx, collection);
return fn.call(ctx, val, idx, collection);
};
case 4: return function (accumulator, val, idx, collection)
{
return func.call(ctx, accumulator, val, idx, collection);
return fn.call(ctx, accumulator, val, idx, collection);
}
}
return function ()
{
return func.apply(ctx, arguments);
return fn.apply(ctx, arguments);
};
}
@@ -1652,7 +1738,7 @@ module.exports = (function ()
var safeCb = _.safeCb = (function (exports)
{
/* Create callback based on input value. TODO
/* Create callback based on input value.
*/
exports = function (val, ctx, argCount)
@@ -2473,7 +2559,32 @@ module.exports = (function ()
var delegate = _.delegate = (function (exports)
{
/* TODO
/* Event delegation.
*
* ### add
*
* Add event delegation.
*
* |Name |Type |Desc |
* |--------|--------|--------------|
* |el |element |Parent element|
* |type |string |Event type |
* |selector|string |Match selector|
* |cb |function|Event callback|
*
* ### remove
*
* Remove event delegation.
*
* ```javascript
* var container = document.getElementById('container');
* function clickHandler()
* {
* // Do something...
* }
* delegate.add(container, 'click', '.children', clickHandler);
* delegate.remove(container, 'click', '.children', clickHandler);
* ```
*/
function retTrue() { return true }
@@ -2629,13 +2740,15 @@ module.exports = (function ()
var $event = _.$event = (function (exports)
{
/* bind events to certain dom elements. TODO
/* bind events to certain dom elements.
*
* ```javascript
* $event.on('#test', 'click', function ()
* function clickHandler()
* {
* // ...
* });
* // Do something...
* }
* $event.on('#test', 'click', clickHandler);
* $event.off('#test', 'click', clickHandler);
* ```
*/
@@ -3383,6 +3496,42 @@ module.exports = (function ()
return exports;
})();
/* ------------------------------ safeStorage ------------------------------ */
var safeStorage = _.safeStorage = (function ()
{
function exports(type, memReplacement)
{
if (isUndef(memReplacement)) memReplacement = true;
var ret;
switch (type)
{
case 'local': ret = window.localStorage; break;
case 'session': ret = window.sessionStorage; break;
}
try
{
// Safari private browsing
var x = 'test-localStorage-' + Date.now();
ret.setItem(x, x);
var y = ret.getItem(x);
ret.removeItem(x);
if (y !== x) throw new Error();
} catch (e)
{
if (memReplacement) return memStorage;
return;
}
return ret;
}
return exports;
})();
/* ------------------------------ stripHtmlTag ------------------------------ */
var stripHtmlTag = _.stripHtmlTag = (function ()
@@ -3547,7 +3696,7 @@ module.exports = (function ()
* |return|string|Converted string |
*
* ```javascript
* upperFirst('red'); // -> RED
* upperFirst('red'); // -> Red
* ```
*/