mirror of
https://codeberg.org/nobody/LocalCDN.git
synced 2025-06-05 21:49:31 +02:00
StorageHandler implemented (#92)
This commit is contained in:
@@ -139,7 +139,7 @@ interceptor.relatedSettings.push(Setting.XHR_TEST_DOMAIN);
|
|||||||
interceptor.relatedSettings.push(Setting.BLOCK_MISSING);
|
interceptor.relatedSettings.push(Setting.BLOCK_MISSING);
|
||||||
interceptor.relatedSettings.push(Setting.ALLOWED_DOMAINS_GOOGLE_FONTS);
|
interceptor.relatedSettings.push(Setting.ALLOWED_DOMAINS_GOOGLE_FONTS);
|
||||||
|
|
||||||
chrome.storage.sync.get(interceptor.relatedSettings, function (items) {
|
storageManager.type.get(interceptor.relatedSettings, function (items) {
|
||||||
interceptor.amountInjected = items.amountInjected || 0;
|
interceptor.amountInjected = items.amountInjected || 0;
|
||||||
interceptor.xhrTestDomain = items.xhrTestDomain || Address.LOCALCDN;
|
interceptor.xhrTestDomain = items.xhrTestDomain || Address.LOCALCDN;
|
||||||
interceptor.blockMissing = items.blockMissing || false;
|
interceptor.blockMissing = items.blockMissing || false;
|
||||||
|
23
core/main.js
23
core/main.js
@@ -30,7 +30,9 @@ var main = {};
|
|||||||
|
|
||||||
main._initializeSettings = function () {
|
main._initializeSettings = function () {
|
||||||
|
|
||||||
chrome.storage.sync.get(settingDefaults, function (items) {
|
storageManager.checkStorageType();
|
||||||
|
|
||||||
|
storageManager.type.get(SettingDefaults, function (items) {
|
||||||
|
|
||||||
if (items === null) {
|
if (items === null) {
|
||||||
items = SettingDefaults; // Restore setting defaults.
|
items = SettingDefaults; // Restore setting defaults.
|
||||||
@@ -47,21 +49,23 @@ main._initializeSettings = function () {
|
|||||||
'path': stateManager.selectedIcon
|
'path': stateManager.selectedIcon
|
||||||
}, 'Enabled');
|
}, 'Enabled');
|
||||||
|
|
||||||
chrome.storage.sync.set(items);
|
storageManager.type.set(items);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
main._showReleaseNotes = function (details) {
|
main._showReleaseNotes = function (details) {
|
||||||
|
|
||||||
|
storageManager.checkStorageType();
|
||||||
|
|
||||||
if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {
|
if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {
|
||||||
|
|
||||||
chrome.storage.sync.set({
|
storageManager.type.set({
|
||||||
[Setting.LAST_MAPPING_UPDATE]: lastMappingUpdate
|
[Setting.LAST_MAPPING_UPDATE]: lastMappingUpdate
|
||||||
}, function() {
|
}, function() {
|
||||||
|
|
||||||
if (details.temporary !== true) {
|
if (details.temporary !== true) {
|
||||||
|
|
||||||
chrome.storage.sync.get([Setting.HIDE_RELEASE_NOTES], function (items) {
|
storageManager.type.get([Setting.HIDE_RELEASE_NOTES], function (items) {
|
||||||
|
|
||||||
if (items.hideReleaseNotes !== true) {
|
if (items.hideReleaseNotes !== true) {
|
||||||
|
|
||||||
@@ -75,17 +79,22 @@ main._showReleaseNotes = function (details) {
|
|||||||
});
|
});
|
||||||
} else if (details.reason === chrome.runtime.OnInstalledReason.UPDATE) {
|
} else if (details.reason === chrome.runtime.OnInstalledReason.UPDATE) {
|
||||||
|
|
||||||
|
// TODO: Remove me in v2.4.1
|
||||||
|
storageManager.migrateData('local');
|
||||||
|
|
||||||
// If add-on update true, check last update of mappings.js
|
// If add-on update true, check last update of mappings.js
|
||||||
chrome.storage.sync.get([Setting.LAST_MAPPING_UPDATE, Setting.HIDE_RELEASE_NOTES], function (items) {
|
storageManager.type.get([Setting.LAST_MAPPING_UPDATE, Setting.HIDE_RELEASE_NOTES], function (items) {
|
||||||
|
|
||||||
let mappingUpdate = items.lastMappingUpdate !== lastMappingUpdate;
|
let mappingUpdate = items.lastMappingUpdate !== lastMappingUpdate;
|
||||||
|
|
||||||
if (mappingUpdate || !items.hideReleaseNotes) {
|
if (mappingUpdate || !items.hideReleaseNotes) {
|
||||||
// Updated mappings.js
|
// Updated mappings.js
|
||||||
chrome.storage.sync.set({
|
storageManager.type.set({
|
||||||
[Setting.LAST_MAPPING_UPDATE]: lastMappingUpdate
|
[Setting.LAST_MAPPING_UPDATE]: lastMappingUpdate
|
||||||
}, function() {
|
}, function() {
|
||||||
if (!items.hideReleaseNotes) {
|
// TODO: Remove me in v2.4.1
|
||||||
|
// if (!items.hideReleaseNotes) {
|
||||||
|
if (true) {
|
||||||
chrome.tabs.create({
|
chrome.tabs.create({
|
||||||
'url': chrome.extension.getURL('pages/updates/updates.html?mappingupdate=' + mappingUpdate),
|
'url': chrome.extension.getURL('pages/updates/updates.html?mappingupdate=' + mappingUpdate),
|
||||||
'active': false
|
'active': false
|
||||||
|
@@ -112,7 +112,7 @@ requestAnalyzer._matchBasePath = function (hostMappings, channelPath) {
|
|||||||
requestAnalyzer._findLocalTarget = function (resourceMappings, basePath, channelHost, channelPath, destinationSearchString) {
|
requestAnalyzer._findLocalTarget = function (resourceMappings, basePath, channelHost, channelPath, destinationSearchString) {
|
||||||
let resourcePath, versionNumber, resourcePattern, filename, shorthandResource;
|
let resourcePath, versionNumber, resourcePattern, filename, shorthandResource;
|
||||||
|
|
||||||
chrome.storage.sync.get(Setting.LOGGING, function (items) {
|
storageManager.type.get(Setting.LOGGING, function (items) {
|
||||||
requestAnalyzer.logging = items.enableLogging;
|
requestAnalyzer.logging = items.enableLogging;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -171,17 +171,17 @@ requestAnalyzer._findLocalTarget = function (resourceMappings, basePath, channel
|
|||||||
};
|
};
|
||||||
|
|
||||||
requestAnalyzer._applyWhitelistedDomains = function () {
|
requestAnalyzer._applyWhitelistedDomains = function () {
|
||||||
chrome.storage.sync.get(Setting.WHITELISTED_DOMAINS, function (items) {
|
storageManager.type.get(Setting.WHITELISTED_DOMAINS, function (items) {
|
||||||
requestAnalyzer.whitelistedDomains = items.whitelistedDomains || {};
|
requestAnalyzer.whitelistedDomains = items.whitelistedDomains || {};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
requestAnalyzer._applyManipulateDOMDomains = function () {
|
requestAnalyzer._applyManipulateDOMDomains = function () {
|
||||||
chrome.storage.sync.get(Setting.DOMAINS_MANIPULATE_DOM, function (items) {
|
storageManager.type.get(Setting.DOMAINS_MANIPULATE_DOM, function (items) {
|
||||||
requestAnalyzer.domainsManipulateDOM = items.domainsManipulateDOM || {};
|
requestAnalyzer.domainsManipulateDOM = items.domainsManipulateDOM || {};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
requestAnalyzer._applyAllowedDomainsGoogleFonts = function () {
|
requestAnalyzer._applyAllowedDomainsGoogleFonts = function () {
|
||||||
chrome.storage.sync.get(Setting.ALLOWED_DOMAINS_GOOGLE_FONTS, function (items) {
|
storageManager.type.get(Setting.ALLOWED_DOMAINS_GOOGLE_FONTS, function (items) {
|
||||||
requestAnalyzer.domainsGoogleFonts = items.allowedDomainsGoogleFonts || {};
|
requestAnalyzer.domainsGoogleFonts = items.allowedDomainsGoogleFonts || {};
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
@@ -65,7 +65,7 @@ requestSanitizer._stripMetadata = function (requestDetails) {
|
|||||||
* Initializations
|
* Initializations
|
||||||
*/
|
*/
|
||||||
|
|
||||||
chrome.storage.sync.get({[Setting.STRIP_METADATA]: true}, function (items) {
|
storageManager.type.get({[Setting.STRIP_METADATA]: true}, function (items) {
|
||||||
|
|
||||||
if (items === null || items.stripMetadata !== false) {
|
if (items === null || items.stripMetadata !== false) {
|
||||||
requestSanitizer.enable();
|
requestSanitizer.enable();
|
||||||
|
@@ -56,18 +56,18 @@ stateManager.registerInjection = function (tabIdentifier, injection) {
|
|||||||
|
|
||||||
if (isNaN(interceptor.amountInjected)) {
|
if (isNaN(interceptor.amountInjected)) {
|
||||||
|
|
||||||
chrome.storage.sync.get(Setting.AMOUNT_INJECTED, function (items) {
|
storageManager.type.get(Setting.AMOUNT_INJECTED, function (items) {
|
||||||
|
|
||||||
interceptor.amountInjected = items.amountInjected;
|
interceptor.amountInjected = items.amountInjected;
|
||||||
|
|
||||||
chrome.storage.sync.set({
|
storageManager.type.set({
|
||||||
[Setting.AMOUNT_INJECTED]: ++interceptor.amountInjected
|
[Setting.AMOUNT_INJECTED]: ++interceptor.amountInjected
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
chrome.storage.sync.set({
|
chrome.storage.local.set({
|
||||||
[Setting.AMOUNT_INJECTED]: ++interceptor.amountInjected
|
[Setting.AMOUNT_INJECTED]: ++interceptor.amountInjected
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -83,7 +83,7 @@ stateManager.addDomainToWhitelist = function (domain) {
|
|||||||
let whitelistedDomains = requestAnalyzer.whitelistedDomains;
|
let whitelistedDomains = requestAnalyzer.whitelistedDomains;
|
||||||
whitelistedDomains[domain] = true;
|
whitelistedDomains[domain] = true;
|
||||||
|
|
||||||
chrome.storage.sync.set({whitelistedDomains}, resolve);
|
storageManager.type.set({whitelistedDomains}, resolve);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ stateManager.removeDomainFromWhitelist = function (domain) {
|
|||||||
let whitelistedDomains = requestAnalyzer.whitelistedDomains;
|
let whitelistedDomains = requestAnalyzer.whitelistedDomains;
|
||||||
delete whitelistedDomains[domain];
|
delete whitelistedDomains[domain];
|
||||||
|
|
||||||
chrome.storage.sync.set({whitelistedDomains}, resolve);
|
storageManager.type.set({whitelistedDomains}, resolve);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -105,7 +105,7 @@ stateManager.addDomainToManipulateDOMlist = function (domain) {
|
|||||||
let domainsManipulateDOM = requestAnalyzer.domainsManipulateDOM;
|
let domainsManipulateDOM = requestAnalyzer.domainsManipulateDOM;
|
||||||
domainsManipulateDOM[domain] = true;
|
domainsManipulateDOM[domain] = true;
|
||||||
|
|
||||||
chrome.storage.sync.set({domainsManipulateDOM}, resolve);
|
storageManager.type.set({domainsManipulateDOM}, resolve);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -116,7 +116,7 @@ stateManager.removeDomainFromManipulateDOMlist = function (domain) {
|
|||||||
let domainsManipulateDOM = requestAnalyzer.domainsManipulateDOM;
|
let domainsManipulateDOM = requestAnalyzer.domainsManipulateDOM;
|
||||||
delete domainsManipulateDOM[domain];
|
delete domainsManipulateDOM[domain];
|
||||||
|
|
||||||
chrome.storage.sync.set({domainsManipulateDOM}, resolve);
|
storageManager.type.set({domainsManipulateDOM}, resolve);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -288,7 +288,7 @@ chrome.tabs.query({}, function (tabs) {
|
|||||||
tabs.forEach(stateManager._createTab);
|
tabs.forEach(stateManager._createTab);
|
||||||
});
|
});
|
||||||
|
|
||||||
chrome.storage.sync.get([Setting.SHOW_ICON_BADGE, Setting.SELECTED_ICON], function (items) {
|
storageManager.type.get([Setting.SHOW_ICON_BADGE, Setting.SELECTED_ICON], function (items) {
|
||||||
|
|
||||||
if (items.showIconBadge === undefined) {
|
if (items.showIconBadge === undefined) {
|
||||||
items.showIconBadge = true;
|
items.showIconBadge = true;
|
||||||
|
@@ -6,6 +6,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="../../core/constants.js"></script>
|
<script src="../../core/constants.js"></script>
|
||||||
|
<script src="../../core/storage-manager.js"></script>
|
||||||
|
|
||||||
<script src="../../modules/internal/wrappers.js"></script>
|
<script src="../../modules/internal/wrappers.js"></script>
|
||||||
<script src="../../modules/internal/helpers.js"></script>
|
<script src="../../modules/internal/helpers.js"></script>
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="../../core/constants.js"></script>
|
<script src="../../core/constants.js"></script>
|
||||||
|
<script src="../../core/storage-manager.js"></script>
|
||||||
<script src="../../modules/internal/helpers.js"></script>
|
<script src="../../modules/internal/helpers.js"></script>
|
||||||
<script src="../../modules/internal/rule-generator.js"></script>
|
<script src="../../modules/internal/rule-generator.js"></script>
|
||||||
<script src="../../modules/internal/wrappers.js"></script>
|
<script src="../../modules/internal/wrappers.js"></script>
|
||||||
|
@@ -79,6 +79,7 @@ options._renderOptionsPanel = function () {
|
|||||||
elements.selectedIcon.value = options._optionValues.selectedIcon;
|
elements.selectedIcon.value = options._optionValues.selectedIcon;
|
||||||
elements.internalStatistics.checked = options._optionValues.internalStatistics;
|
elements.internalStatistics.checked = options._optionValues.internalStatistics;
|
||||||
elements.allowedDomainsGoogleFonts.value = domainAllowedGoogleFonts;
|
elements.allowedDomainsGoogleFonts.value = domainAllowedGoogleFonts;
|
||||||
|
elements.storageType = options._optionValues.storageType;
|
||||||
|
|
||||||
options._registerOptionChangedEventListeners(elements);
|
options._registerOptionChangedEventListeners(elements);
|
||||||
options._registerMiscellaneousEventListeners();
|
options._registerMiscellaneousEventListeners();
|
||||||
@@ -105,6 +106,8 @@ options._renderOptionsPanel = function () {
|
|||||||
document.getElementById('link-faq').addEventListener('click', options._onClickFaq);
|
document.getElementById('link-faq').addEventListener('click', options._onClickFaq);
|
||||||
document.getElementById('ruleset-help-icon').addEventListener('click', options._onClickRulesetHelp);
|
document.getElementById('ruleset-help-icon').addEventListener('click', options._onClickRulesetHelp);
|
||||||
document.getElementById('link-statistic').addEventListener('click', options._onClickStatistics);
|
document.getElementById('link-statistic').addEventListener('click', options._onClickStatistics);
|
||||||
|
document.getElementById('storage-type-local').addEventListener('change', options._onStorageOptionChanged);
|
||||||
|
document.getElementById('storage-type-sync').addEventListener('change', options._onStorageOptionChanged);
|
||||||
};
|
};
|
||||||
|
|
||||||
options._renderBlockMissingNotice = function () {
|
options._renderBlockMissingNotice = function () {
|
||||||
@@ -157,7 +160,7 @@ options._determineOptionValues = function () {
|
|||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
let optionKeys = Object.keys(options._optionElements);
|
let optionKeys = Object.keys(options._optionElements);
|
||||||
|
|
||||||
chrome.storage.sync.get(optionKeys, function (items) {
|
storageManager.type.get(optionKeys, function (items) {
|
||||||
options._optionValues = items;
|
options._optionValues = items;
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
@@ -166,8 +169,9 @@ options._determineOptionValues = function () {
|
|||||||
|
|
||||||
options._determineLocalOptionValues = function () {
|
options._determineLocalOptionValues = function () {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
chrome.storage.local.get([Setting.INTERNAL_STATISTICS], function (items) {
|
chrome.storage.local.get([Setting.INTERNAL_STATISTICS, Setting.STORAGE_TYPE], function (items) {
|
||||||
options._internalStatistics = items.internalStatistics;
|
options._internalStatistics = items.internalStatistics;
|
||||||
|
options._storageType = items.storageType;
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
@@ -193,6 +197,7 @@ options._getOptionElements = function () {
|
|||||||
[Setting.BLOCK_GOOGLE_FONTS]: options._getOptionElement(Setting.BLOCK_GOOGLE_FONTS),
|
[Setting.BLOCK_GOOGLE_FONTS]: options._getOptionElement(Setting.BLOCK_GOOGLE_FONTS),
|
||||||
[Setting.SELECTED_ICON]: options._getOptionElement(Setting.SELECTED_ICON),
|
[Setting.SELECTED_ICON]: options._getOptionElement(Setting.SELECTED_ICON),
|
||||||
[Setting.ALLOWED_DOMAINS_GOOGLE_FONTS]: options._getOptionElement(Setting.ALLOWED_DOMAINS_GOOGLE_FONTS),
|
[Setting.ALLOWED_DOMAINS_GOOGLE_FONTS]: options._getOptionElement(Setting.ALLOWED_DOMAINS_GOOGLE_FONTS),
|
||||||
|
[Setting.STORAGE_TYPE]: options._getOptionElement(Setting.STORAGE_TYPE)
|
||||||
};
|
};
|
||||||
|
|
||||||
return optionElements;
|
return optionElements;
|
||||||
@@ -252,7 +257,7 @@ options._onDocumentLoaded = function () {
|
|||||||
};
|
};
|
||||||
|
|
||||||
options._onOptionChanged = function ({ target }) {
|
options._onOptionChanged = function ({ target }) {
|
||||||
let optionKey, optionType, optionValue, storageType;
|
let optionKey, optionType, optionValue;
|
||||||
|
|
||||||
optionKey = target.getAttribute('data-option');
|
optionKey = target.getAttribute('data-option');
|
||||||
optionType = target.getAttribute('type');
|
optionType = target.getAttribute('type');
|
||||||
@@ -300,18 +305,17 @@ options._onOptionChanged = function ({ target }) {
|
|||||||
if (optionKey === Setting.SELECTED_ICON) {
|
if (optionKey === Setting.SELECTED_ICON) {
|
||||||
wrappers.setIcon({ path: optionValue }, 'Enabled');
|
wrappers.setIcon({ path: optionValue }, 'Enabled');
|
||||||
}
|
}
|
||||||
|
storageManager.type.set({
|
||||||
if (optionKey === Setting.INTERNAL_STATISTICS) {
|
|
||||||
storageType = chrome.storage.local;
|
|
||||||
} else {
|
|
||||||
storageType = chrome.storage.sync;
|
|
||||||
}
|
|
||||||
|
|
||||||
storageType.set({
|
|
||||||
[optionKey]: optionValue,
|
[optionKey]: optionValue,
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
options._onStorageOptionChanged = function ({ target }) {
|
||||||
|
chrome.storage.local.set({
|
||||||
|
[Setting.STORAGE_TYPE]: target.value,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
options._onClickHTMLFilterWarning = function () {
|
options._onClickHTMLFilterWarning = function () {
|
||||||
chrome.tabs.create({
|
chrome.tabs.create({
|
||||||
url: 'https://codeberg.org/nobody/LocalCDN/wiki/Blank-websites-or-weird-characters',
|
url: 'https://codeberg.org/nobody/LocalCDN/wiki/Blank-websites-or-weird-characters',
|
||||||
@@ -383,6 +387,7 @@ options._updatesDomainLists = function (changes) {
|
|||||||
* Initializations
|
* Initializations
|
||||||
*/
|
*/
|
||||||
options._internalStatistics = false;
|
options._internalStatistics = false;
|
||||||
|
options._storageType = 'local';
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', options._onDocumentLoaded);
|
document.addEventListener('DOMContentLoaded', options._onDocumentLoaded);
|
||||||
|
|
||||||
|
@@ -9,6 +9,7 @@
|
|||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script src="../../core/constants.js"></script>
|
<script src="../../core/constants.js"></script>
|
||||||
|
<script src="../../core/storage-manager.js"></script>
|
||||||
<script src="../../modules/internal/helpers.js"></script>
|
<script src="../../modules/internal/helpers.js"></script>
|
||||||
<script src="popup.js"></script>
|
<script src="popup.js"></script>
|
||||||
<header>
|
<header>
|
||||||
|
@@ -237,7 +237,7 @@ popup._determineTargetTab = function () {
|
|||||||
|
|
||||||
popup._determineAmountInjected = function () {
|
popup._determineAmountInjected = function () {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
chrome.storage.sync.get(Setting.AMOUNT_INJECTED, function (items) {
|
chrome.storage.local.get(Setting.AMOUNT_INJECTED, function (items) {
|
||||||
popup._amountInjected = items.amountInjected || 0;
|
popup._amountInjected = items.amountInjected || 0;
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
@@ -246,7 +246,7 @@ popup._determineAmountInjected = function () {
|
|||||||
|
|
||||||
popup._determineNegateHtmlFilterOption = function () {
|
popup._determineNegateHtmlFilterOption = function () {
|
||||||
return new Promise((resolve) => {
|
return new Promise((resolve) => {
|
||||||
chrome.storage.sync.get(Setting.NEGATE_HTML_FILTER_LIST, function (items) {
|
storageManager.type.get(Setting.NEGATE_HTML_FILTER_LIST, function (items) {
|
||||||
popup.negateHtmlFilterList = items.negateHtmlFilterList;
|
popup.negateHtmlFilterList = items.negateHtmlFilterList;
|
||||||
resolve();
|
resolve();
|
||||||
});
|
});
|
||||||
|
@@ -28,6 +28,7 @@
|
|||||||
<li>Added CDN: gitcdn.github.io (<a href="https://codeberg.org/nobody/LocalCDN/issues/90">#90</a>)</li>
|
<li>Added CDN: gitcdn.github.io (<a href="https://codeberg.org/nobody/LocalCDN/issues/90">#90</a>)</li>
|
||||||
<li>Added: Bootstrap Toggle v2.2.2 (<a href="https://codeberg.org/nobody/LocalCDN/issues/90">#90</a>)</li>
|
<li>Added: Bootstrap Toggle v2.2.2 (<a href="https://codeberg.org/nobody/LocalCDN/issues/90">#90</a>)</li>
|
||||||
<li>Implemented: Open options in new tab (<a href="https://codeberg.org/nobody/LocalCDN/issues/91">#91</a>)</li>
|
<li>Implemented: Open options in new tab (<a href="https://codeberg.org/nobody/LocalCDN/issues/91">#91</a>)</li>
|
||||||
|
<li>Implemented: Storage handler (<a href="https://codeberg.org/nobody/LocalCDN/issues/92">#92</a>)</li>
|
||||||
<li>Updated: Google Material Icons (<a href="https://codeberg.org/nobody/LocalCDN/issues/94">#94</a>)</li>
|
<li>Updated: Google Material Icons (<a href="https://codeberg.org/nobody/LocalCDN/issues/94">#94</a>)</li>
|
||||||
<li>Added: P2P Media Loader Hls.js (v0.6.2) (<a href="https://codeberg.org/nobody/LocalCDN/issues/95">#95</a>)</li>
|
<li>Added: P2P Media Loader Hls.js (v0.6.2) (<a href="https://codeberg.org/nobody/LocalCDN/issues/95">#95</a>)</li>
|
||||||
</ul>
|
</ul>
|
||||||
|
Reference in New Issue
Block a user