Pour tout problème contactez-nous par mail : support@froggit.fr | La FAQ :grey_question: | Rejoignez-nous sur le Chat :speech_balloon:

Skip to content
Snippets Groups Projects
game-article.js 7.14 KiB
Newer Older
"use strict";

const ImageCarousel = require("../generic-components/image-carousel");
const { getArticleBody } = require("../lib/article-utils");
const { fetch_json_or_error_text } = require("../lib/fetch");
const { MentaloEngine } = require("mentalo-engine");
const translator = require("ks-cheap-translator");
const { images_url, data_url } = require("../../constants");
const t = translator.trad.bind(translator);


class GameArticle {
    constructor(data) {
        this.data = data;
        this.init_body();
        this.init_details();
    init_body() {
        let body = getArticleBody(this.data.body);
        const play_btn_regex = /\[PLAY_BUTTON\s\{.+\}\]/g;
        const found_play_buttons = body.match(play_btn_regex);
        if (found_play_buttons) {
            this.build_play_button(JSON.parse(found_play_buttons[0].replace(/[\[\]PLAY_BUTTON\s]/g, "")));
            body = body.replace(play_btn_regex, "");
        }
        this.body = body;
    }

    init_details() {
        this.details = this.data.details.filter(d => {
            const { label, value } = d;
            if (label === "video") {
                this.video_link = value;
                return false;
            }
            return true;
        });
    }

    build_play_button(button_data) {
        this.render_play_button = {
            tag: "button",
            class: "play-button",
            contents: "▶️  " + t("Jouer"),
            onclick: this.handle_click_play.bind(this, button_data.filename, button_data.engine)
        };
    }

    load_and_run_mentalo_game(filename, button_element) {
        const button_text = button_element.innerHTML;
        button_element.innerHTML = "Loading ...";
        button_element.style.pointerEvents = "none";

        fetch_json_or_error_text(`${data_url}/${filename}`)
            .then(game_data => {
                const container = document.createElement("div");
                container.style.position = "fixed";
                container.style.top = 0;
                container.style.left = 0;
                container.style.right = 0;
                container.style.bottom = 0;
                container.style.zIndex = 10;
                container.style.display = "flex";
                container.style.justifyContent = "center";
                container.style.alignItems = "center";

                container.id = "kuadrado-tmp-game-player-container";
                document.body.appendChild(container);
                document.body.style.overflow = "hidden";

                const engine = new MentaloEngine({
                    game_data,
                    fullscreen: true,
                    frame_rate: 30,
                    container,
                    on_quit_game: () => {
                        container.remove();
                        document.body.style.overflow = "visible";
                    }
                });

                engine.init();
                engine.run_game();
            })
            .catch(err => console.log(err))
            .finally(() => {
                button_element.innerHTML = button_text;
                button_element.style.pointerEvents = "unset";
            });
    }

    handle_click_play(filename, engine, e) {
        switch (engine) {
            case "mentalo":
                this.load_and_run_mentalo_game(filename, e.target);
                break;
            default:
                console.log("Error, unkown engine")
                return;
        }
    }

    render() {
        const {
            images,
            title,
            subtitle,
        } = this.data;

        const trad_ready = Object.keys(translator.translations).length > 0;

        return {
            tag: "article",
            class: "game-article",
            contents: [
                {
                    tag: "div",
                    id: "article-banner",
                    style_rules: {
                        backgroundImage: `url(${images_url}/${images[0]})`,
                    },
                    contents: [
                        {
                            tag: "div",
                            id: "header-text-container",
                            contents: [
                                {
                                    tag: "h1",
                                    contents: title,
                                    class: "header-text h1",
                                },
                                {
                                    tag: "h2",
                                    contents: subtitle,
                                    class: "header-text h2",
                                },
                                this.render_play_button,
                            ]
                        }
                    ]
                },
                {
                    tag: "div",
                    id: "article-contents",
                    class: "page-contents-center",
                    contents: [
                        {
                            tag: "div",
                            id: "article-body",
                            contents: [
                                {
                                    tag: "p",
                                    contents: this.body
                                },
                                this.video_link && {
                                    tag: "iframe",
                                    src: this.video_link,
                                    frameborder: 0,
                                    allowfullscreen: true,
                                    width: 400,
                                    height: 250,
                                },
                        trad_ready && new ImageCarousel({ images: images.map(img => `${images_url}/${img}`) }).render(),
                        this.details.length > 0 && {
                            tag: "div",
                            class: "article-details",
                            contents: [
                                {
                                    tag: "ul",
                                    class: "details-list",
                                    contents: this.details.map(detail => {
                                        return {
                                            tag: "li",
                                            class: "detail",
                                            contents: [
                                                { tag: "label", contents: detail.label },
                                                {
                                                    tag: "div",
                                                    class: "detail-value",
                                                    contents: detail.value,