Frontend <-> Backend Communication
Nui provides a way to communicate between frontend and the main process running the WebView. This intentionally does not use async in the frontend, because using Asyncify comes with a considerable size overhead and some quirky behaviour that nui does not want to enforce. Instead a callback style is used.
Setup RPC in the Main Process
#include <nui/backend/rpc_hub.hpp>
#include <nui/core.hpp>
#include <nui/window.hpp>
#include <index.hpp>
int main()
{
    Window window{"Minecraft Modpack Maker", true /* may open debug window */};
    window.setSize(1200, 800, WebViewHint::WEBVIEW_HINT_NONE);
    window.setHtml(index());
    // Create RpcHub class responsible for communication:
    RpcHub hub{window};
    // Convenience function to enable all extensions. Prefer to enable only what you need.
    hub.enableAll();
    window.run();
}
RpcHub comes with some extensions what can be enabled. All are disabled by default for security reasons.
Usage
Backend
Registering a function that is callable from the frontend:
#include <nui/backend/rpc_hub.hpp>
#include <nui/core.hpp>
#include <nui/window.hpp>
#include <index.hpp>
int main()
{
    Window window{"Minecraft Modpack Maker", true /* may open debug window */};
    window.setSize(1200, 800, WebViewHint::WEBVIEW_HINT_NONE);
    window.setHtml(index());
    // Create RpcHub class responsible for communication:
    RpcHub hub{window};
    hub.registerFunction(
        "functionName",
        // Parameters can either be be converted from json by nlohmann::json.get<decay_t<T>>...
        [&hub](std::string const& responseId, int param2){
            // ...
            hub.callRemote(responseId, nlohmann::json{});
        }
    );
    hub.registerFunction(
        "functionName",
        // ...or a nlohmann::json and you can dissect it yourself:
        [](nlohmann::json const& args){
            // ...
        }
    );
    window.run();
}
Calling a frontend Function:
#include <nui/backend/rpc_hub.hpp>
#include <nui/core.hpp>
#include <nui/window.hpp>
#include <index.hpp>
int main()
{
    Window window{"Minecraft Modpack Maker", true /* may open debug window */};
    window.setSize(1200, 800, WebViewHint::WEBVIEW_HINT_NONE);
    window.setHtml(index());
    // Create RpcHub class responsible for communication:
    RpcHub hub{window};
    hub.callRemote("remoteFunctionName", nlohmann::json{/*...*/});
    window.run();
}
Frontend
Registering callable functions:
#include <nui/frontend/rpc_client.hpp>
void foo()
{
    Nui::RpcClient::registerFunction("someCallable", [](Nui::val val){
        // ...
    });
    Nui::RpcClient::registerFunction("someCallable2", [](std::string const& param){
        // ...
    });
    // Useful RAII unregister (also available in backend):
    {
        auto unregisterWhenThisFallsOutOfScope =
            Nui::RpcClient::autoRegisterFunction("asdf", [](){});
    } // asdf no longer exists here.
    // Removing callable:
    Nui::RpcClient::unregisterFunction("someCallable");
}
Calling backend functions:
#include <nui/frontend/rpc_client.hpp>
struct InterchangeObject
{
    std::string bla;
    int f;
};
BOOST_DESCRIBE_STRUCT(
    InterchangeObject,
    (),
    (bla, f)
);
void foo()
{
    // When the called function shall receive a responseId as first argument.
    // This allows the backend to reply by calling the passed callback.
    Nui::RpcClient::getRemoteCallableWithBackChannel(
        "backendFunctionName", [](InterchangeObject&& obj /* or a Nui::val */){
            // ...
        }
    )("parameter 1", 232);
    // Trivial case, where the backend is not able to reply here:
    Nui::RpcClient::getRemoteCallable("functionName")("parameter 1", true);
    Nui::RpcClient::getRemoteCallable("functionName2")(Nui::val{});
}
RPC Plugins
File Dialogs
RpcHub::enableFileDialogs: Enable file dialogs to pick files on the system.
Example:
#include <nui/frontend/filesystem/file_dialog.hpp>
void foo()
{
    Nui::FileDialog::showOpenDialog({
        // all are optional
        .title = "Open something please",
        /*
         * ~ Linux: home. Windows: home
         * %userprofile% Linux: home. Windows: home
         * %appdata% Linux: home. Windows: CSIDL_APPDATA
         * %localappdata% Linux: home. Windows: CSIDL_APPDATA_LOCAL
         * %temp% Linux: /tmp. Windows: ${USER}\AppData\Local\Temp
         */
        .defaultPath = "%userprofile%",
        .filters = {
            {.name = "Images", .masks = {".jpg", ".png"}},
        },
        .forcePath = false,
        .allowMultiSelect = false
    }, [](std::optional<std::vector<std::filesystem::path>> results){
        if (!results) // The dialog was closed without selecting a file
            return;
        if (results->empty()) // nothing was selected, but the dialog was closed with ok.
            return;
        // ...
    });
    // Same, but does not allow for multiselect:
    // showDirectoryDialog()
    // additionally has forceOverwrite option, which disables any warnings about existing files.
    // showSaveDialog()
}
Async Files
RpcHub::enableFile: A way to open/read/write files in the frontend from the system. It is recommended to do file reads and writes in the backend/main process entirely and wrapping them in a function call.
Example - The usage experience is a bit suboptimal due to everything being done through callbacks. Prefer moving all file related operations to the backend process.
#include <nui/filesystem/file.hpp>
void foo()
{
    openFile("/home/user/bla.txt", std::ios_base::read, [](std::optional<AsyncFile>&& file) {
        if (!file)
            return;
        // file provides the following functions, all are asynchronous through a callback:
        // file->tellg([](int32_t){});
        // file->tellp([](int32_t){});
        // file->seekg(int32_t pos, [](){}, std::ios_base::beg);
        // file->seekp(int32_t pos, [](){}, std::ios_base::beg);
        // file->read(int32_t size, [](std::string&&){});
        // file->readAll([](std::string&&){});
        // file->write(std::string data, [](){});
    });
}
Window Functions
RpcHub::enableWindowFunctions: Allow frontend to use the Window class.
Example:
#include <nui/frontend/window.hpp>
void foo()
{
    Window wnd;
    wnd.setTitle("title");
    wnd.setSize(200, 300);
    wnd.navigate("https://www.github.com");
    // Might not work on some systems, which is an external bug
    wnd.openDevTools();
    wnd.setPosition(0, 0);
    wnd.centerOnPrimaryDisplay();
    wnd.terminate();
}
Barebones Fetch
RpcHub::enableFetch: Enables an alternative barebones fetch implementation for the frontend, because standard fetch requires async.
Can be used in the frontend, if enabled, like this:
#include <nui/frontend/api/fetch.hpp>
Nui::fetch("www.bla.org", {
    // all of these have defaults and can be omitted
    .method = "GET",
    .headers = {
        {"Accept-Encoding", "*"}
    },
    .body = "",
    .followRedirects = false,
    .maxRedirects = 255,
    .autoReferer = false,
    // Dont auto decode base64 or other understood encodings:
    .dontDecodeBody = false,
    // For HTTPS:
    .verifyPeer = true,
    .verifyHost = true
})
If you need more than this, you need to implement your own networking functions and make them available.
Throttle
RpcHub::enableThrottle: Enables a throttle function.
Example:
#include <nui/frontend/api/throttle.hpp>
Nui::ThrottledFunction throttled;
void foo() {
    throttle(
        200 /*ms*/,
        [](){
            std::cout << "Not printed faster than 200ms after the last call.";
        },
        // Called when the throttled function is prepared and ready for use:
        [&throttled](Nui::ThrottledFunction&& throttledFunc){
            throttled = std::move(throttledFunc);
        },
        false /* call when ready, if it was not ready during the wait period */
    );
}
void bar() {
    throttled();
    // does nothing, because it cannot be called within 200ms.
    // unless callWhenReady is true, then it is called again after 200ms
    throttled();
}
Timer
RpcHub::enableTimer: Enables the timer functions
Example
#include <nui/frontend/api/timer.hpp>
Nui::TimerHandle timer;
void foo()
{
    Nui::setInterval(
        500 /*ms*/,
        // Called every 500ms
        [](){std::cout << "Hello!\n";},
        [&timer](Nui::TimerHandle&& t){
            // Timer is ready and you get access over it here:
            timer = std::move(t);
        }
    );
}
void stopTimer()
{
    if (timer.hasActiveTimer())
        timer.stop();
}
Screen
RpcHub::enableScreen: Enables access to screen size and positioning functions.
Example
#include <nui/frontend/screen.hpp>
void foo()
{
    Nui::Screen::getDisplays([](std::vector<Nui::Display>&& displays){
        for (auto const& display : displays) {
            std::cout << display.x() << "\n";
            std::cout << display.y() << "\n";
            std::cout << display.width() << "\n";
            std::cout << display.height() << "\n";
            std::cout << display.isPrimary() << "\n";
            std::cout << display.deviceName() << "\n";
        }
    });
    Nui::Screen::getPrimaryDisplay([](Nui::Display&& primary){
        // ...
    });
}
Environment Variables
RpcHub::enableEnvironmentVariables: Enables access to environment variables.
Example
#include <nui/frontend/environment_variables.hpp>
void foo()
{
    Nui::getEnvironmentVariables([](std::unordered_map<std::string, std::string>&& variables){
        // ...
    })
}