From 85a104caa50e1d8776a34a2442896590c472e7ac Mon Sep 17 00:00:00 2001 From: Sergiotarxz Date: Sat, 2 Dec 2023 17:22:27 +0100 Subject: [PATCH] Adding initial js support of protobuf. --- Build.PL | 1 + generate_proto.sh | 11 + js-src/conquer/index.ts | 1 + .../interface/abstract-top-bar-interface.ts | 29 +++ js-src/conquer/interface/new-node.ts | 10 + js-src/conquer/interface/self-player.ts | 28 +-- js-src/conquer/websocket.ts | 30 +++ .../generated/v1/packet/open-new-node_pb.d.ts | 29 +++ .../generated/v1/packet/open-new-node_pb.js | 206 ++++++++++++++++++ lib/BurguillosInfo/Controller/ConquerTile.pm | 52 +++-- package.json | 4 +- proto/v1/packet/open-new-node.proto | 8 + public/css/styles.css | 1 + public/css/styles.scss | 1 + public/js/bundle.js | 13 +- templates/conquer/index.html.ep | 2 +- 16 files changed, 386 insertions(+), 40 deletions(-) create mode 100644 generate_proto.sh create mode 100644 js-src/conquer/interface/abstract-top-bar-interface.ts create mode 100644 js-src/conquer/interface/new-node.ts create mode 100644 js-src/conquer/websocket.ts create mode 100644 js-src/generated/v1/packet/open-new-node_pb.d.ts create mode 100644 js-src/generated/v1/packet/open-new-node_pb.js create mode 100644 proto/v1/packet/open-new-node.proto diff --git a/Build.PL b/Build.PL index 63ee73a..bf88ecf 100755 --- a/Build.PL +++ b/Build.PL @@ -32,6 +32,7 @@ my $build = Module::Build->new( 'UUID::URandom' => 0, 'Crypt::Bcrypt' => 0, 'DBIx::Class::TimeStamp' => 0, + 'DateTime::Format::HTTP' => 0, }, ); $build->create_build_script; diff --git a/generate_proto.sh b/generate_proto.sh new file mode 100644 index 0000000..27bcb0b --- /dev/null +++ b/generate_proto.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +rm -rf ./js-src/generated/ +mkdir ./js-src/generated/ +protoc --plugin="protoc-gen-ts=./node_modules/.bin/protoc-gen-ts" \ + --plugin="protoc-gen-js=./node_modules/.bin/protoc-gen-js" \ + --ts_opt=esModuleInterop=true \ + --js_out="import_style=commonjs,binary:./js-src/generated" \ + --ts_out="./js-src/generated" \ + --proto_path="proto" \ + $(find proto/ -name '*.proto') diff --git a/js-src/conquer/index.ts b/js-src/conquer/index.ts index 60f4526..88284d5 100644 --- a/js-src/conquer/index.ts +++ b/js-src/conquer/index.ts @@ -20,6 +20,7 @@ import SelfPlayerUI from '@burguillosinfo/conquer/interface/self-player' import CreateNode from '@burguillosinfo/conquer/create-node' import MapState from '@burguillosinfo/conquer/map-state' import MapNode from '@burguillosinfo/conquer/map-node' +import NewNodeUI from '@burguillosinfo/conquer/interface/new-node' type StylesInterface = Record diff --git a/js-src/conquer/interface/abstract-top-bar-interface.ts b/js-src/conquer/interface/abstract-top-bar-interface.ts new file mode 100644 index 0000000..de551d9 --- /dev/null +++ b/js-src/conquer/interface/abstract-top-bar-interface.ts @@ -0,0 +1,29 @@ +import Conquer from '@burguillosinfo/conquer' +import ConquerInterface from '@burguillosinfo/conquer/interface' + +export default abstract class AbstractTopBarInterface extends ConquerInterface { + constructor() { + super() + const exitButton = this.getExitButton() + exitButton.addEventListener('click', () => { + this.runCallbacks('close') + }) + } + protected generateNodes(): HTMLElement[] { + const newNode = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template') + return [newNode] + } + protected getMainNode(): HTMLElement { + return this.getNodes()[0] + } + protected getExitButton(): HTMLElement { + const maybeExitButton = this.getMainNode().querySelector('.conquer-exit-button') + if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) { + Conquer.fail('No exit button.') + } + return maybeExitButton + } + public generateInterfaceElementCentered(): HTMLElement { + return this.getNodeFromTemplateId('conquer-interface-element-padded-template') + } +} diff --git a/js-src/conquer/interface/new-node.ts b/js-src/conquer/interface/new-node.ts new file mode 100644 index 0000000..b0793e6 --- /dev/null +++ b/js-src/conquer/interface/new-node.ts @@ -0,0 +1,10 @@ +import AbstractTopBarInterface from '@burguillosinfo/conquer/interface/abstract-top-bar-interface' +import Conquer from '@burguillosinfo/conquer' + +export default class NewNodeUI extends AbstractTopBarInterface { + private coordinates: number[]; + constructor(coordinates: number[]) { + super() + this.coordinates = coordinates + } +} diff --git a/js-src/conquer/interface/self-player.ts b/js-src/conquer/interface/self-player.ts index 648155f..1417d94 100644 --- a/js-src/conquer/interface/self-player.ts +++ b/js-src/conquer/interface/self-player.ts @@ -1,35 +1,23 @@ -import ConquerInterface from '@burguillosinfo/conquer/interface' import Conquer from '@burguillosinfo/conquer' import ConquerUser from '@burguillosinfo/conquer/user' +import AbstractTopBarInterface from '@burguillosinfo/conquer/interface/abstract-top-bar-interface' -export default class SelfPlayerUI extends ConquerInterface { +export default class SelfPlayerUI extends AbstractTopBarInterface { private selfPlayer: ConquerUser | null = null private userWelcome: HTMLElement | null = null protected generateNodes(): HTMLElement[] { - const player = this.getNodeFromTemplateId('conquer-self-player-template') + const player = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template') return [player] } - public getSelfPlayerNode(): HTMLElement { - return this.getNodes()[0] - } - public getExitButton(): HTMLElement { - const maybeExitButton = this.getSelfPlayerNode().querySelector('.conquer-exit-button') - if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) { - Conquer.fail('No exit button.') - } - return maybeExitButton - } + public generateInterfaceElementCentered(): HTMLElement { return this.getNodeFromTemplateId('conquer-interface-element-padded-template') } + public async run(): Promise { - const selfPlayerNode = this.getSelfPlayerNode() + const selfPlayerNode = this.getMainNode() selfPlayerNode.classList.remove('conquer-display-none') - const exitButton = this.getExitButton() - exitButton.addEventListener('click', () => { - this.runCallbacks('close') - }) const user = await ConquerUser.getSelfUser() if (user === null) { this.runCallbacks('close') @@ -53,14 +41,14 @@ export default class SelfPlayerUI extends ConquerInterface { }) const createNodeButtonInterface = this.generateInterfaceElementCentered() createNodeButtonInterface.appendChild(createNodeButton) - this.getSelfPlayerNode().appendChild(createNodeButtonInterface) + this.getMainNode().appendChild(createNodeButtonInterface) } private populateWelcome(): void { const userWelcome = this.getUserWelcome() const userWelcomeInterface = this.generateInterfaceElementCentered(); userWelcomeInterface.appendChild(userWelcome) - this.getSelfPlayerNode().appendChild(userWelcomeInterface) + this.getMainNode().appendChild(userWelcomeInterface) } private getUserWelcome(): HTMLElement { diff --git a/js-src/conquer/websocket.ts b/js-src/conquer/websocket.ts new file mode 100644 index 0000000..a24c836 --- /dev/null +++ b/js-src/conquer/websocket.ts @@ -0,0 +1,30 @@ +export default class ConquerWebSocket { + private webSocket: WebSocket | null = null + private socketReady = false + + private getWebSocket(): WebSocket { + if (this.webSocket !== null) { + return this.webSocket + } + this.webSocket = new WebSocket(`wss://${window.location.hostname}:${window.location.port}/conquer/websocket`) + this.webSocket.addEventListener('close', (event) => { + this.onSocketClose(event) + }) + this.webSocket.addEventListener('error', (event) => { + this.onSocketClose(event) + }) + this.webSocket.addEventListener('open', (event) => { + this.onSocketOpen(event) + }) + return this.webSocket + } + + private onSocketOpen(event: Event) { + this.socketReady = true + } + + private onSocketClose(event: Event) { + this.socketReady = false + console.error(event) + } +} diff --git a/js-src/generated/v1/packet/open-new-node_pb.d.ts b/js-src/generated/v1/packet/open-new-node_pb.d.ts new file mode 100644 index 0000000..f4c2615 --- /dev/null +++ b/js-src/generated/v1/packet/open-new-node_pb.d.ts @@ -0,0 +1,29 @@ +// package: proto.v1.packet +// file: v1/packet/open-new-node.proto + +import * as jspb from "google-protobuf"; + +export class OpenNewNode extends jspb.Message { + getLatitude(): number; + setLatitude(value: number): void; + + getLongitude(): number; + setLongitude(value: number): void; + + serializeBinary(): Uint8Array; + toObject(includeInstance?: boolean): OpenNewNode.AsObject; + static toObject(includeInstance: boolean, msg: OpenNewNode): OpenNewNode.AsObject; + static extensions: {[key: number]: jspb.ExtensionFieldInfo}; + static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo}; + static serializeBinaryToWriter(message: OpenNewNode, writer: jspb.BinaryWriter): void; + static deserializeBinary(bytes: Uint8Array): OpenNewNode; + static deserializeBinaryFromReader(message: OpenNewNode, reader: jspb.BinaryReader): OpenNewNode; +} + +export namespace OpenNewNode { + export type AsObject = { + latitude: number, + longitude: number, + } +} + diff --git a/js-src/generated/v1/packet/open-new-node_pb.js b/js-src/generated/v1/packet/open-new-node_pb.js new file mode 100644 index 0000000..ac80fed --- /dev/null +++ b/js-src/generated/v1/packet/open-new-node_pb.js @@ -0,0 +1,206 @@ +// source: v1/packet/open-new-node.proto +/** + * @fileoverview + * @enhanceable + * @suppress {missingRequire} reports error on implicit type usages. + * @suppress {messageConventions} JS Compiler reports an error if a variable or + * field starts with 'MSG_' and isn't a translatable message. + * @public + */ +// GENERATED CODE -- DO NOT EDIT! +/* eslint-disable */ +// @ts-nocheck + +var jspb = require('google-protobuf'); +var goog = jspb; +var global = + (typeof globalThis !== 'undefined' && globalThis) || + (typeof window !== 'undefined' && window) || + (typeof global !== 'undefined' && global) || + (typeof self !== 'undefined' && self) || + (function () { return this; }).call(null) || + Function('return this')(); + +goog.exportSymbol('proto.proto.v1.packet.OpenNewNode', null, global); +/** + * Generated by JsPbCodeGenerator. + * @param {Array=} opt_data Optional initial data array, typically from a + * server response, or constructed directly in Javascript. The array is used + * in place and becomes part of the constructed object. It is not cloned. + * If no data is provided, the constructed object will be empty, but still + * valid. + * @extends {jspb.Message} + * @constructor + */ +proto.proto.v1.packet.OpenNewNode = function(opt_data) { + jspb.Message.initialize(this, opt_data, 0, -1, null, null); +}; +goog.inherits(proto.proto.v1.packet.OpenNewNode, jspb.Message); +if (goog.DEBUG && !COMPILED) { + /** + * @public + * @override + */ + proto.proto.v1.packet.OpenNewNode.displayName = 'proto.proto.v1.packet.OpenNewNode'; +} + + + +if (jspb.Message.GENERATE_TO_OBJECT) { +/** + * Creates an object representation of this proto. + * Field names that are reserved in JavaScript and will be renamed to pb_name. + * Optional fields that are not set will be set to undefined. + * To access a reserved field use, foo.pb_, eg, foo.pb_default. + * For the list of reserved names please see: + * net/proto2/compiler/js/internal/generator.cc#kKeyword. + * @param {boolean=} opt_includeInstance Deprecated. whether to include the + * JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @return {!Object} + */ +proto.proto.v1.packet.OpenNewNode.prototype.toObject = function(opt_includeInstance) { + return proto.proto.v1.packet.OpenNewNode.toObject(opt_includeInstance, this); +}; + + +/** + * Static version of the {@see toObject} method. + * @param {boolean|undefined} includeInstance Deprecated. Whether to include + * the JSPB instance for transitional soy proto support: + * http://goto/soy-param-migration + * @param {!proto.proto.v1.packet.OpenNewNode} msg The msg instance to transform. + * @return {!Object} + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.proto.v1.packet.OpenNewNode.toObject = function(includeInstance, msg) { + var f, obj = { + latitude: jspb.Message.getFloatingPointFieldWithDefault(msg, 1, 0.0), + longitude: jspb.Message.getFloatingPointFieldWithDefault(msg, 2, 0.0) + }; + + if (includeInstance) { + obj.$jspbMessageInstance = msg; + } + return obj; +}; +} + + +/** + * Deserializes binary data (in protobuf wire format). + * @param {jspb.ByteSource} bytes The bytes to deserialize. + * @return {!proto.proto.v1.packet.OpenNewNode} + */ +proto.proto.v1.packet.OpenNewNode.deserializeBinary = function(bytes) { + var reader = new jspb.BinaryReader(bytes); + var msg = new proto.proto.v1.packet.OpenNewNode; + return proto.proto.v1.packet.OpenNewNode.deserializeBinaryFromReader(msg, reader); +}; + + +/** + * Deserializes binary data (in protobuf wire format) from the + * given reader into the given message object. + * @param {!proto.proto.v1.packet.OpenNewNode} msg The message object to deserialize into. + * @param {!jspb.BinaryReader} reader The BinaryReader to use. + * @return {!proto.proto.v1.packet.OpenNewNode} + */ +proto.proto.v1.packet.OpenNewNode.deserializeBinaryFromReader = function(msg, reader) { + while (reader.nextField()) { + if (reader.isEndGroup()) { + break; + } + var field = reader.getFieldNumber(); + switch (field) { + case 1: + var value = /** @type {number} */ (reader.readDouble()); + msg.setLatitude(value); + break; + case 2: + var value = /** @type {number} */ (reader.readDouble()); + msg.setLongitude(value); + break; + default: + reader.skipField(); + break; + } + } + return msg; +}; + + +/** + * Serializes the message to binary data (in protobuf wire format). + * @return {!Uint8Array} + */ +proto.proto.v1.packet.OpenNewNode.prototype.serializeBinary = function() { + var writer = new jspb.BinaryWriter(); + proto.proto.v1.packet.OpenNewNode.serializeBinaryToWriter(this, writer); + return writer.getResultBuffer(); +}; + + +/** + * Serializes the given message to binary data (in protobuf wire + * format), writing to the given BinaryWriter. + * @param {!proto.proto.v1.packet.OpenNewNode} message + * @param {!jspb.BinaryWriter} writer + * @suppress {unusedLocalVariables} f is only used for nested messages + */ +proto.proto.v1.packet.OpenNewNode.serializeBinaryToWriter = function(message, writer) { + var f = undefined; + f = message.getLatitude(); + if (f !== 0.0) { + writer.writeDouble( + 1, + f + ); + } + f = message.getLongitude(); + if (f !== 0.0) { + writer.writeDouble( + 2, + f + ); + } +}; + + +/** + * optional double latitude = 1; + * @return {number} + */ +proto.proto.v1.packet.OpenNewNode.prototype.getLatitude = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 1, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.proto.v1.packet.OpenNewNode} returns this + */ +proto.proto.v1.packet.OpenNewNode.prototype.setLatitude = function(value) { + return jspb.Message.setProto3FloatField(this, 1, value); +}; + + +/** + * optional double longitude = 2; + * @return {number} + */ +proto.proto.v1.packet.OpenNewNode.prototype.getLongitude = function() { + return /** @type {number} */ (jspb.Message.getFloatingPointFieldWithDefault(this, 2, 0.0)); +}; + + +/** + * @param {number} value + * @return {!proto.proto.v1.packet.OpenNewNode} returns this + */ +proto.proto.v1.packet.OpenNewNode.prototype.setLongitude = function(value) { + return jspb.Message.setProto3FloatField(this, 2, value); +}; + + +goog.object.extend(exports, proto.proto.v1.packet); diff --git a/lib/BurguillosInfo/Controller/ConquerTile.pm b/lib/BurguillosInfo/Controller/ConquerTile.pm index 34a7984..17fa7ec 100644 --- a/lib/BurguillosInfo/Controller/ConquerTile.pm +++ b/lib/BurguillosInfo/Controller/ConquerTile.pm @@ -10,43 +10,61 @@ use utf8; use Mojo::Base 'Mojolicious::Controller', '-signatures'; use Path::Tiny; use Mojo::UserAgent; +use DateTime::Format::HTTP; +use DateTime; -my $cache_files_dir = path(__FILE__)->parent->parent->parent->parent->child('cache/tiles/'); +my $cache_files_dir = + path(__FILE__)->parent->parent->parent->parent->child('cache/tiles/'); -sub tile($self) { - my $zoom = $self->stash('zoom'); - my $x = $self->stash('x'); - my $y = $self->stash('y'); +sub _cache_response ($self) { + my $tomorrow_same_hour_datetime = DateTime->now->add( days => 1 ); + $self->res->headers->cache_control("max_age=@{[3600*24]}"); + $self->res->headers->expires( + DateTime::Format::HTTP->format_datetime($tomorrow_same_hour_datetime) ); +} + +sub tile ($self) { + my $zoom = $self->stash('zoom'); + my $x = $self->stash('x'); + my $y = $self->stash('y'); my $candidate_file = $cache_files_dir->child("$zoom-$x-$y.png"); - if (-f $candidate_file) { + if ( -f $candidate_file ) { + $self->_cache_response; return $self->_render_png($candidate_file); } - if (!defined $self->current_user) { - return $self->render(status => 401, text => '¡¡No estás loggeado, no puedes cargar mapa nuevo.!!'); + if ( !defined $self->current_user ) { + return $self->render( + status => 401, + text => '¡¡No estás loggeado, no puedes cargar mapa nuevo.!!' + ); } + $self->_cache_response; my $file_to_write = $candidate_file; - my $ua = Mojo::UserAgent->new; - my $png_tile = $ua->get("https://tile.openstreetmap.org/$zoom/$x/$y.png")->result->body; - open my $fh, '|-', 'convert', '/dev/stdin', '-channel', 'RGB', '-negate', $file_to_write; + my $ua = Mojo::UserAgent->new; + my $png_tile = + $ua->get("https://tile.openstreetmap.org/$zoom/$x/$y.png")->result->body; + open my $fh, '|-', 'convert', '/dev/stdin', '-channel', 'RGB', '-negate', + $file_to_write; print $fh $png_tile; close $fh; $self->_render_png($file_to_write); $self->_delete_extra_files(); } -sub _delete_extra_files($self) { - my @files = $cache_files_dir->children; - if (scalar @files < 20001) { +sub _delete_extra_files ($self) { + my @files = $cache_files_dir->children; + if ( scalar @files < 20001 ) { return; } @files = sort { -M $a <=> -M $b } @files; - for (my $i = 0; $i < (scalar @files) - 20000; $i++) { + for ( my $i = 0 ; $i < ( scalar @files ) - 20000 ; $i++ ) { system 'rm', '-v', $files[$i]; } } -sub _render_png($self, $file) { +sub _render_png ( $self, $file ) { system 'touch', $file; - return $self->render(data => $file->slurp_raw, status => 200, format => 'png'); + return $self->render( data => $file->slurp_raw, status => 200, + format => 'png' ); } 1; diff --git a/package.json b/package.json index 6928908..a83cf99 100644 --- a/package.json +++ b/package.json @@ -25,7 +25,9 @@ "dependencies": { "babel-loader": "^9.1.3", "ol": "^8.1.0", + "protoc-gen-js": "^3.21.2", "tablesort": "^5.3.0", - "ts-loader": "^9.5.0" + "ts-loader": "^9.5.0", + "ts-protoc-gen": "^0.15.0" } } diff --git a/proto/v1/packet/open-new-node.proto b/proto/v1/packet/open-new-node.proto new file mode 100644 index 0000000..9eac479 --- /dev/null +++ b/proto/v1/packet/open-new-node.proto @@ -0,0 +1,8 @@ +syntax = "proto3"; + +package proto.v1.packet; + +message OpenNewNode { + double latitude = 1; + double longitude = 2; +} diff --git a/public/css/styles.css b/public/css/styles.css index 5a9ff02..9652173 100644 --- a/public/css/styles.css +++ b/public/css/styles.css @@ -105,6 +105,7 @@ body { body .conquer-display-none { display: none; } body div.conquer-container { + background: black; height: 100dvh; width: 100%; } body div.ol-control { diff --git a/public/css/styles.scss b/public/css/styles.scss index 61ff5fc..4116a26 100644 --- a/public/css/styles.scss +++ b/public/css/styles.scss @@ -126,6 +126,7 @@ body { display: none; } div.conquer-container { + background: black; height: 100dvh; width: 100%; } diff --git a/public/js/bundle.js b/public/js/bundle.js index 64500d0..9d6b603 100644 --- a/public/js/bundle.js +++ b/public/js/bundle.js @@ -105,6 +105,17 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ }), +/***/ "./js-src/conquer/interface/abstract-top-bar-interface.ts": +/*!****************************************************************!*\ + !*** ./js-src/conquer/interface/abstract-top-bar-interface.ts ***! + \****************************************************************/ +/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { + +"use strict"; +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ AbstractTopBarInterface)\n/* harmony export */ });\n/* harmony import */ var _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @burguillosinfo/conquer */ \"./js-src/conquer/index.ts\");\n/* harmony import */ var _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @burguillosinfo/conquer/interface */ \"./js-src/conquer/interface.ts\");\n\n\nclass AbstractTopBarInterface extends _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\n constructor() {\n super();\n const exitButton = this.getExitButton();\n exitButton.addEventListener('click', () => {\n this.runCallbacks('close');\n });\n }\n generateNodes() {\n const newNode = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template');\n return [newNode];\n }\n getMainNode() {\n return this.getNodes()[0];\n }\n getExitButton() {\n const maybeExitButton = this.getMainNode().querySelector('.conquer-exit-button');\n if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) {\n _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_0__[\"default\"].fail('No exit button.');\n }\n return maybeExitButton;\n }\n generateInterfaceElementCentered() {\n return this.getNodeFromTemplateId('conquer-interface-element-padded-template');\n }\n}\n\n\n//# sourceURL=webpack://BurguillosInfo/./js-src/conquer/interface/abstract-top-bar-interface.ts?"); + +/***/ }), + /***/ "./js-src/conquer/interface/login.ts": /*!*******************************************!*\ !*** ./js-src/conquer/interface/login.ts ***! @@ -123,7 +134,7 @@ eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpac /***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => { "use strict"; -eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SelfPlayerUI)\n/* harmony export */ });\n/* harmony import */ var _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @burguillosinfo/conquer/interface */ \"./js-src/conquer/interface.ts\");\n/* harmony import */ var _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @burguillosinfo/conquer */ \"./js-src/conquer/index.ts\");\n/* harmony import */ var _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! @burguillosinfo/conquer/user */ \"./js-src/conquer/user.ts\");\n\n\n\nclass SelfPlayerUI extends _burguillosinfo_conquer_interface__WEBPACK_IMPORTED_MODULE_0__[\"default\"] {\n constructor() {\n super(...arguments);\n this.selfPlayer = null;\n this.userWelcome = null;\n }\n generateNodes() {\n const player = this.getNodeFromTemplateId('conquer-self-player-template');\n return [player];\n }\n getSelfPlayerNode() {\n return this.getNodes()[0];\n }\n getExitButton() {\n const maybeExitButton = this.getSelfPlayerNode().querySelector('.conquer-exit-button');\n if (maybeExitButton === null || !(maybeExitButton instanceof HTMLElement)) {\n _burguillosinfo_conquer__WEBPACK_IMPORTED_MODULE_1__[\"default\"].fail('No exit button.');\n }\n return maybeExitButton;\n }\n generateInterfaceElementCentered() {\n return this.getNodeFromTemplateId('conquer-interface-element-padded-template');\n }\n async run() {\n const selfPlayerNode = this.getSelfPlayerNode();\n selfPlayerNode.classList.remove('conquer-display-none');\n const exitButton = this.getExitButton();\n exitButton.addEventListener('click', () => {\n this.runCallbacks('close');\n });\n const user = await _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_2__[\"default\"].getSelfUser();\n if (user === null) {\n this.runCallbacks('close');\n return;\n }\n this.selfPlayer = user;\n this.populateWelcome();\n this.populateCreateNodeOption();\n }\n populateCreateNodeOption() {\n if (!this.selfPlayer?.isAdmin()) {\n return;\n }\n const createNodeButton = document.createElement('button');\n createNodeButton.innerText = 'Crear Nuevo Nodo';\n createNodeButton.addEventListener('click', () => {\n this.runCallbacks('createNodeStart');\n // We close because it is a sensible thing to do.\n this.runCallbacks('close');\n });\n const createNodeButtonInterface = this.generateInterfaceElementCentered();\n createNodeButtonInterface.appendChild(createNodeButton);\n this.getSelfPlayerNode().appendChild(createNodeButtonInterface);\n }\n populateWelcome() {\n const userWelcome = this.getUserWelcome();\n const userWelcomeInterface = this.generateInterfaceElementCentered();\n userWelcomeInterface.appendChild(userWelcome);\n this.getSelfPlayerNode().appendChild(userWelcomeInterface);\n }\n getUserWelcome() {\n if (this.userWelcome !== null) {\n return this.userWelcome;\n }\n const element = document.createElement('h2');\n if (this.selfPlayer === null) {\n throw new Error('User still not set');\n }\n element.innerText = `¡Hola, ${this.selfPlayer.getUsername()}!`;\n this.userWelcome = element;\n return this.userWelcome;\n }\n}\n\n\n//# sourceURL=webpack://BurguillosInfo/./js-src/conquer/interface/self-player.ts?"); +eval("__webpack_require__.r(__webpack_exports__);\n/* harmony export */ __webpack_require__.d(__webpack_exports__, {\n/* harmony export */ \"default\": () => (/* binding */ SelfPlayerUI)\n/* harmony export */ });\n/* harmony import */ var _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! @burguillosinfo/conquer/user */ \"./js-src/conquer/user.ts\");\n/* harmony import */ var _burguillosinfo_conquer_interface_abstract_top_bar_interface__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! @burguillosinfo/conquer/interface/abstract-top-bar-interface */ \"./js-src/conquer/interface/abstract-top-bar-interface.ts\");\n\n\nclass SelfPlayerUI extends _burguillosinfo_conquer_interface_abstract_top_bar_interface__WEBPACK_IMPORTED_MODULE_1__[\"default\"] {\n constructor() {\n super(...arguments);\n this.selfPlayer = null;\n this.userWelcome = null;\n }\n generateNodes() {\n const player = this.getNodeFromTemplateId('conquer-interface-with-top-bar-template');\n return [player];\n }\n generateInterfaceElementCentered() {\n return this.getNodeFromTemplateId('conquer-interface-element-padded-template');\n }\n async run() {\n const selfPlayerNode = this.getMainNode();\n selfPlayerNode.classList.remove('conquer-display-none');\n const user = await _burguillosinfo_conquer_user__WEBPACK_IMPORTED_MODULE_0__[\"default\"].getSelfUser();\n if (user === null) {\n this.runCallbacks('close');\n return;\n }\n this.selfPlayer = user;\n this.populateWelcome();\n this.populateCreateNodeOption();\n }\n populateCreateNodeOption() {\n if (!this.selfPlayer?.isAdmin()) {\n return;\n }\n const createNodeButton = document.createElement('button');\n createNodeButton.innerText = 'Crear Nuevo Nodo';\n createNodeButton.addEventListener('click', () => {\n this.runCallbacks('createNodeStart');\n // We close because it is a sensible thing to do.\n this.runCallbacks('close');\n });\n const createNodeButtonInterface = this.generateInterfaceElementCentered();\n createNodeButtonInterface.appendChild(createNodeButton);\n this.getMainNode().appendChild(createNodeButtonInterface);\n }\n populateWelcome() {\n const userWelcome = this.getUserWelcome();\n const userWelcomeInterface = this.generateInterfaceElementCentered();\n userWelcomeInterface.appendChild(userWelcome);\n this.getMainNode().appendChild(userWelcomeInterface);\n }\n getUserWelcome() {\n if (this.userWelcome !== null) {\n return this.userWelcome;\n }\n const element = document.createElement('h2');\n if (this.selfPlayer === null) {\n throw new Error('User still not set');\n }\n element.innerText = `¡Hola, ${this.selfPlayer.getUsername()}!`;\n this.userWelcome = element;\n return this.userWelcome;\n }\n}\n\n\n//# sourceURL=webpack://BurguillosInfo/./js-src/conquer/interface/self-player.ts?"); /***/ }), diff --git a/templates/conquer/index.html.ep b/templates/conquer/index.html.ep index 6bb9ba7..ae163da 100644 --- a/templates/conquer/index.html.ep +++ b/templates/conquer/index.html.ep @@ -16,7 +16,7 @@
-
+
X