import/export settings to file

This commit is contained in:
Áron Hegymegi-Kiss
2022-01-08 19:03:46 +01:00
parent 90eaab4e50
commit dc560cd73e
3 changed files with 102 additions and 34 deletions

View File

@@ -460,6 +460,15 @@
"exportOptions": { "exportOptions": {
"message": "Import/Export All Options" "message": "Import/Export All Options"
}, },
"exportOptionsCopy": {
"message": "Edit/copy"
},
"exportOptionsDownload": {
"message": "Save to file"
},
"exportOptionsUpload": {
"message": "Load from file"
},
"whatExportOptions": { "whatExportOptions": {
"message": "This is your entire configuration in JSON. This includes your userID, so be sure to share this wisely." "message": "This is your entire configuration in JSON. This includes your userID, so be sure to share this wisely."
}, },

View File

@@ -355,8 +355,19 @@
</div> </div>
<div data-type="private-text-change" data-sync="*" data-confirm-message="exportOptionsWarning"> <div data-type="private-text-change" data-sync="*" data-confirm-message="exportOptionsWarning">
<div class="option-button trigger-button"> <h2>__MSG_exportOptions__</h2>
__MSG_exportOptions__
<div>
<div class="option-button trigger-button inline">
__MSG_exportOptionsCopy__
</div>
<div class="option-button download-button inline">
__MSG_exportOptionsDownload__
</div>
<label for="importOptions" class="option-button inline">
__MSG_exportOptionsUpload__
</label>
<input id="importOptions" type="file" class="upload-button hidden" />
</div> </div>
<div class="small-description">__MSG_whatExportOptions__</div> <div class="small-description">__MSG_whatExportOptions__</div>

View File

@@ -176,6 +176,14 @@ async function init() {
const button = optionsElements[i].querySelector(".trigger-button"); const button = optionsElements[i].querySelector(".trigger-button");
button.addEventListener("click", () => activatePrivateTextChange(<HTMLElement> optionsElements[i])); button.addEventListener("click", () => activatePrivateTextChange(<HTMLElement> optionsElements[i]));
if (option == "*") {
const downloadButton = optionsElements[i].querySelector(".download-button");
downloadButton.addEventListener("click", downloadConfig);
const uploadButton = optionsElements[i].querySelector(".upload-button");
uploadButton.addEventListener("change", (e) => uploadConfig(e));
}
const privateTextChangeOption = optionsElements[i].getAttribute("data-sync"); const privateTextChangeOption = optionsElements[i].getAttribute("data-sync");
// See if anything extra must be done // See if anything extra must be done
switch (privateTextChangeOption) { switch (privateTextChangeOption) {
@@ -490,6 +498,37 @@ function activatePrivateTextChange(element: HTMLElement) {
const setButton = element.querySelector(".text-change-set"); const setButton = element.querySelector(".text-change-set");
setButton.addEventListener("click", async () => { setButton.addEventListener("click", async () => {
setTextOption(option, element, textBox.value);
});
// See if anything extra must be done
switch (option) {
case "userID":
utils.asyncRequestToServer("GET", "/api/userInfo", {
userID: Config.config[option],
values: ["warnings", "banned"]
}).then((result) => {
const userInfo = JSON.parse(result.responseText);
if (userInfo.warnings > 0 || userInfo.banned) {
setButton.classList.add("hidden");
}
});
break;
}
element.querySelector(".option-hidden-section").classList.remove("hidden");
}
/**
* Function to run when a textbox change is submitted
*
* @param option data-sync value
* @param element main container div
* @param value new text
* @param callbackOnError function to run if confirmMessage was denied
*/
async function setTextOption(option: string, element: HTMLElement, value: string, callbackOnError?: () => void) {
const confirmMessage = element.getAttribute("data-confirm-message"); const confirmMessage = element.getAttribute("data-confirm-message");
if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) { if (confirmMessage === null || confirm(chrome.i18n.getMessage(confirmMessage))) {
@@ -498,7 +537,7 @@ function activatePrivateTextChange(element: HTMLElement) {
switch (option) { switch (option) {
case "*": case "*":
try { try {
const newConfig = JSON.parse(textBox.value); const newConfig = JSON.parse(value);
for (const key in newConfig) { for (const key in newConfig) {
Config.config[key] = newConfig[key]; Config.config[key] = newConfig[key];
} }
@@ -519,28 +558,37 @@ function activatePrivateTextChange(element: HTMLElement) {
break; break;
default: default:
Config.config[option] = textBox.value; Config.config[option] = value;
}
} else {
if (typeof callbackOnError == "function")
callbackOnError();
} }
} }
function downloadConfig() {
const file = document.createElement("a");
const jsonData = JSON.parse(JSON.stringify(Config.localConfig));
jsonData.segmentTimes = Config.encodeStoredItem(Config.localConfig.segmentTimes);
file.setAttribute("href", "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(jsonData)));
file.setAttribute("download", "SponsorBlockConfig.json");
document.body.append(file);
file.click();
file.remove();
}
function uploadConfig(e) {
if (e.target.files.length == 1) {
const file = e.target.files[0];
const reader = new FileReader();
const element = document.querySelector("[data-sync='*']") as HTMLElement;
reader.onload = function(ev) {
setTextOption("*", element, ev.target.result as string, () => {
e.target.value = null;
}); });
};
// See if anything extra must be done reader.readAsText(file);
switch (option) {
case "userID":
utils.asyncRequestToServer("GET", "/api/userInfo", {
userID: Config.config[option],
values: ["warnings", "banned"]
}).then((result) => {
const userInfo = JSON.parse(result.responseText);
if (userInfo.warnings > 0 || userInfo.banned) {
setButton.classList.add("hidden");
} }
});
break;
}
element.querySelector(".option-hidden-section").classList.remove("hidden");
} }
/** /**