aboutsummaryrefslogtreecommitdiff
/**
 * This file is part of Haketilo.
 *
 * Function: Logic for the settings import frame.
 *
 * Copyright (C) 2021 Wojtek Kosior
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * As additional permission under GNU GPL version 3 section 7, you
 * may distribute forms of that code without the copy of the GNU
 * GPL normally required by section 4, provided you include this
 * license notice and, in case of non-source distribution, a URL
 * through which recipients can access the Corresponding Source.
 * If you modify file(s) with this exception, you may extend this
 * exception to your version of the file(s), but you are not
 * obligated to do so. If you do not wish to do so, delete this
 * exception statement from your version.
 *
 * As a special exception to the GPL, any HTML file which merely
 * makes function calls to this code, and for that purpose
 * includes it by reference shall be deemed a separate work for
 * copyright law purposes. If you modify this code, you may extend
 * this exception to your version of the code, but you are not
 * obligated to do so. If you do not wish to do so, delete this
 * exception statement from your version.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 *
 * I, Wojtek Kosior, thereby promise not to sue for violation of this file's
 * license. Although I request that you do not make use this code in a
 * proprietary program, I am not going to enforce this in court.
 */

/*
 * IMPORTS_START
 * IMPORT get_remote_storage
 * IMPORT by_id
 * IMPORT clone_template
 * IMPORT nice_name
 * IMPORT make_once
 * IMPORTS_END
 */

let storage;

let import_list = by_id("import_list");
let import_chbxs_colliding = undefined;
let entry_objects = undefined;
let settings_import_map = undefined;

function add_import_entry(prefix, name)
{
    const cloned_template = clone_template("import_entry");
    Object.assign(cloned_template, {prefix, name});

    cloned_template.name_span.textContent = nice_name(prefix, name);

    if (storage.get(prefix, name) !== undefined) {
	import_chbxs_colliding.push(cloned_template.chbx);
	cloned_template.warning.textContent = "!";
    }

    import_list.appendChild(cloned_template.entry);

    return cloned_template;
}

function check_all_imports()
{
    for (const entry_object of entry_objects)
	entry_object.chbx.checked = true;
}

function uncheck_all_imports()
{
    for (const entry_object of entry_objects)
	entry_object.chbx.checked = false;
}

function uncheck_colliding_imports()
{
    for (let chbx of import_chbxs_colliding)
	chbx.checked = false;
}

function commit_import()
{
    for (const entry_object of entry_objects) {
	if (!entry_object.chbx.checked)
	    continue;

	const key = entry_object.prefix + entry_object.name;
	const value = settings_import_map.get(key);
	storage.set(entry_object.prefix, entry_object.name, value);
    }

    deactivate();
}

const import_loading_radio = by_id("import_loading_radio");

function show_loading()
{
    import_loading_radio.checked = true;
}

const import_failed_radio = by_id("import_failed_radio");
const import_errormsg = by_id("import_errormsg");
const import_errordetail_chbx = by_id("import_errordetail_chbx");
const import_errordetail = by_id("import_errordetail");

function show_error(errormsg, errordetail)
{
    import_failed_radio.checked = true;
    import_errormsg.textContent = errormsg;
    import_errordetail_chbx.checked = errordetail;
    import_errordetail.textContent = errordetail;
}

const import_selection_radio = by_id("import_selection_radio");
const existing_settings_note = by_id("existing_settings_note");

function show_selection(settings)
{
    import_selection_radio.checked = true;

    let old_children = import_list.children;
    while (old_children[0] !== undefined)
	import_list.removeChild(old_children[0]);

    import_chbxs_colliding = [];
    entry_objects = [];
    settings_import_map = new Map();

    for (let setting of settings) {
	let [key, value] = Object.entries(setting)[0];
	let prefix = key[0];
	let name = key.substring(1);
	entry_objects.push(add_import_entry(prefix, name));
	settings_import_map.set(key, value);
    }

    const op = import_chbxs_colliding.length > 0 ? "remove" : "add";
    existing_settings_note.classList[op]("hide");
}

function deactivate()
{
    /* Let GC free some memory */
    import_chbxs_colliding = undefined;
    entry_objects = undefined;
    settings_import_map = undefined;

    if (exports.onclose)
	exports.onclose();
}

const wrapper = by_id("import_table_wrapper");
const style_table = (...cls) => cls.forEach(c => wrapper.classList.add(c));

const exports =
      {show_loading, show_error, show_selection, deactivate, style_table};

async function init()
{
    storage = await get_remote_storage();

    by_id("commit_import_but").addEventListener("click", commit_import);
    by_id("check_all_import_but").addEventListener("click", check_all_imports);
    by_id("uncheck_all_import_but")
	.addEventListener("click", uncheck_all_imports);
    by_id("uncheck_colliding_import_but")
	.addEventListener("click", uncheck_colliding_imports);
    by_id("cancel_import_but").addEventListener("click", deactivate);
    by_id("import_failok_but").addEventListener("click", deactivate);

    return exports;
}

const get_import_frame = make_once(init);

/*
 * EXPORTS_START
 * EXPORT get_import_frame
 * EXPORTS_END
 */