You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

107 lines
3.3 KiB

/* Settings flags */
const settingsFlagsKey = '?';
const settingsFlagsEnum = {
allowCategoryEditing: 1,
isRandomized: 2,
};
const settingsDefaults = {
allowCategoryEditing: true,
isRandomized: false,
};
function loadSettings(data) {
const settings = Object.assign({}, settingsDefaults);
const flags = data[settingsFlagsKey];
for (const settingName of Object.keys(settingsFlagsEnum)) {
settings[settingName] = Boolean(settingsFlagsEnum[settingName] & flags);
}
return settings;
}
function saveSettings(settings) {
let flags = 0;
for (const [settingName, isEnabled] of Object.entries(settings)) {
if (isEnabled) {
flags |= settingsFlagsEnum[settingName];
}
}
return flags;
}
/* Saving and loading */
const uncategorizedKey = '#';
const reservedKeys = [
settingsFlagsKey,
uncategorizedKey,
];
const regexRemoveBasenameFromUrl = /\/[^\/]*?$/;
async function uint8ArrayToBase64(data) {
const base64url = await new Promise((resolve) => {
const reader = new FileReader();
reader.onload = () => resolve(reader.result);
reader.readAsDataURL(new Blob([data]));
});
return base64url.split(',', 2)[1];
}
async function base64ToUint8Array(base64string) {
const response = await fetch('data:;base64,' + base64string);
const blob = await response.blob();
return new Uint8Array(await blob.arrayBuffer());
}
async function saveToString(data) {
const jsonString = JSON.stringify(data);
const compressedData = pako.deflate(new TextEncoder().encode(jsonString));
const base64String = await uint8ArrayToBase64(compressedData);
const webSafeBase64String = base64String.replaceAll('+', '-').replaceAll('/', '_');
return webSafeBase64String;
}
async function loadFromString(webSafeBase64String) {
const base64String = webSafeBase64String.replaceAll('-', '+').replaceAll('_', '/');
const compressedData = await base64ToUint8Array(base64String);
const jsonString = new TextDecoder('utf8').decode(pako.inflate(compressedData));
const data = JSON.parse(jsonString);
return data;
}
function loadFromQueryParameters() {
const data = {};
const settings = Object.assign({}, settingsDefaults);
const params = new URLSearchParams(window.location.search);
const cardTexts = (params.get('cards') || '').split(',').filter(item => !!item);
const categories = (params.get('categories') || '').split(',').filter(item => !!item);
if (params.get('allowCategoryEditing') !== null) {
settings.allowCategoryEditing = Boolean(parseInt(params.get('allowCategoryEditing')));
}
data[uncategorizedKey] = cardTexts;
data[settingsFlagsKey] = saveSettings(settings);
for (const categoryName of categories) {
data[categoryName] = [];
}
return data;
}
/* Utilities */
function debounce(func, wait, immediate) {
let timeout;
return function debouncedFunc() {
const context = this;
const args = arguments;
const later = function () {
timeout = null;
if ( ! immediate) {
func.apply(context, args);
}
};
const callNow = immediate && ! timeout;
clearTimeout(timeout);
timeout = setTimeout(later, wait);
if (callNow) {
func.apply(context, args);
}
};
}
function asTextContent(input) {
const tempElement = document.createElement('span');
tempElement.textContent = input;
return tempElement.innerHTML;
}