Adding initial js support of protobuf.

This commit is contained in:
Sergiotarxz 2023-12-02 17:22:27 +01:00
parent 24b4f7db9f
commit 85a104caa5
16 changed files with 386 additions and 40 deletions

View File

@ -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;

11
generate_proto.sh Normal file
View File

@ -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')

View File

@ -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<string, Style>

View File

@ -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')
}
}

View File

@ -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
}
}

View File

@ -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<void> {
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 {

View File

@ -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)
}
}

View File

@ -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<jspb.Message>};
static extensionsBinary: {[key: number]: jspb.ExtensionFieldBinaryInfo<jspb.Message>};
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,
}
}

View File

@ -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_<name>, 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);

View File

@ -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;

View File

@ -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"
}
}

View File

@ -0,0 +1,8 @@
syntax = "proto3";
package proto.v1.packet;
message OpenNewNode {
double latitude = 1;
double longitude = 2;
}

View File

@ -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 {

View File

@ -126,6 +126,7 @@ body {
display: none;
}
div.conquer-container {
background: black;
height: 100dvh;
width: 100%;
}

View File

@ -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?");
/***/ }),

View File

@ -16,7 +16,7 @@
</div>
<div id="conquer-interface-element-padded-template" class="conquer-interface-element-padded">
</div>
<div id="conquer-self-player-template" class="conquer-self-player conquer-display-none">
<div id="conquer-interface-with-top-bar-template" class="conquer-self-player conquer-display-none">
<div class="conquer-top-bar">
<a href="#" class="conquer-exit-button">X</a>
</div>