function view(ctl, params) {
    var nodes = [];
    nodes.push(m("h3", "Basic settings"));
    nodes.push(
        createCheckbox.call(
            this,
            "autoSubmit",
            "Automatically submit forms after filling (not recommended)"
        )
    );
    nodes.push(
        createCheckbox.call(this, "enableOTP", "Enable support for OTP tokens (not recommended)")
    );
    nodes.push(createCheckbox.call(this, "hideBadge", "Hide badge counter on the toolbar icon"));
    nodes.push(createInput.call(this, "username", "Default username", "john.smith"));
    nodes.push(createInput.call(this, "gpgPath", "Custom gpg binary", "/path/to/gpg"));

    nodes.push(m("h3", "Theme"));
    nodes.push(
        createDropdown.call(this, "theme", [
            m("option", { value: "auto" }, "Auto"),
            m("option", { value: "dark" }, "Dark"),
            m("option", { value: "light" }, "Light"),
        ])
    );

    nodes.push(m("h3", "Custom store locations"));
    nodes.push(
        m("div", { class: "notice" }, "(this overrides default store and $PASSWORD_STORE_DIR)")
    );
    for (var storeId in this.settings.stores) {
        nodes.push(createCustomStore.call(this, storeId));
    }
    nodes.push(
        m(
            "a.add-store",
            {
                onclick: () => {
                    addEmptyStore(this.settings.stores);
                    this.saveEnabled = true;
                },
            },
            "Add store"
        )
    );

    if (typeof this.error !== "undefined") {
        nodes.push(m("div.error", this.error.message));
    }
    if (this.settings.hasOwnProperty("hostError")) {
        let hostError = this.settings.hostError;
        nodes.push(m("div.error", hostError.params.message));
    }

    nodes.push(
        m(
            "button.save",
            {
                disabled: !this.saveEnabled,
                onclick: async () => {
                    try {
                        this.settings = await this.saveSettings(this.settings);
                        this.error = undefined;
                    } catch (e) {
                        this.error = e;
                    }
                    this.saveEnabled = false;
                    m.redraw();
                },
            },
            "Save"
        )
    );

    nodes.push(
        m(
            "button.clearUsageData",
            {
                onclick: async () => {
                    try {
                        await this.clearUsageData();
                        this.error = undefined;
                    } catch (e) {
                        this.error = e;
                    }
                    m.redraw();
                },
            },
            "Clear usage data"
        )
    );
    return nodes;
}
Generates vnodes for render

@since 3.0.0

@param function ctl    Controller
@param object   params Runtime params
@return []Vnode