Práctica 4: Home chat - Sianats/LTAW-Practicas GitHub Wiki
El objetivo de esta práctica es convertir el servidor de Chat de la práctica 3 en una aplicación Electron nativa. Esta, tiene una interfaz gráfica que muestra la siguiente información:
- Versión de node
- Versión de Electron
- Versión de Chrome
- URL a la que se deben conectar los clientes para chatear
- Mostrar los mensajes que llegan al servidor, del resto de usuarios
- Botón de pruebas para enviar un mensaje a todos los clientes conectados
Mi código de esta práctica se encuentra en mi Repositorio 4. Consta de la carpeta public de mi Práctica 3 y de tres nuevos archivos: index.html, index.js, main.js.
Tanto en los css como en el html, hay especificaciones de qué hace cada cosa. Por lo que solo me queda enseñar el resultado estético. Al entrar en el servidor, Aparece lo siguiente:
Al acceder, cambia el número de usuarios y aparece el servidor, estéticamente igual al de mi práctica 3:
Y, por último, si pulsas el botón aparece un mensaje de prueba enviado por el servidor:
Adjunto mi código, con sus funciones explicadas una a una en los comentarios del propio:
- Código de mi fichero index.js:
const electron = require('electron');
console.log("Hola desde el proceso de la web...");
//-- Obtener elementos de la interfaz
const btn_test = document.getElementById("btn_test");
const display = document.getElementById("display");
const info1 = document.getElementById("info1");
const info2 = document.getElementById("info2");
const info3 = document.getElementById("info3");
const node = document.getElementById("node");
const chrome = document.getElementById("chrome");
const electron1 = document.getElementById("electron1");
const ip1 = document.getElementById("ip1");
const numus = document.getElementById("numus");
//-- Acceder a la API de node para obtener la info
//-- Sólo es posible si nos han dado permisos desde
//-- el proceso princpal
info1.textContent = process.arch;
info2.textContent = process.platform;
info3.textContent = process.cwd();
node.textContent = process.versions.node;
chrome.textContent = process.versions.chrome;
electron1.textContent = process.versions.electron;
// Se muestra la url declarada en el main
electron.ipcRenderer.on('ip', (event, msg) => {
console.log("Recibido: " + msg);
ip1.textContent = msg;
});
// Al pulsar en botón, aparece el mensaje
btn_test.onclick = () => {
console.log("Botón apretado");
//-- Enviar mensaje al proceso principal
electron.ipcRenderer.invoke('test', "Boton de prueba... funciona :)");
}
// Enseña el número de usuarios conectados
electron.ipcRenderer.on('numus', (event, msg) => {
console.log("Usuarios: " + msg);
numus.textContent = msg;
});
//-- Mensaje recibido del proceso MAIN
electron.ipcRenderer.on('display', (event, msg) => {
console.log("Recibido: " + msg);
if(!msg.includes(' se ha unido</h5>')){
display.innerHTML += '<p class="mess mess-r" style="text-align: right";>' + msg + '</p>';
} else {
// Si aparece ese mensaje en el texto, no declaro ninguna clase o estilo definido
//(es puramente estético. Solo es css, no tiene funcionalidad js).
display.innerHTML += '<p>' + msg + '</p>';
}
});
- Código de mi fichero main.js:
//-- Cargar las dependencias
const socketServer = require('socket.io').Server;
const http = require('http');
const express = require('express');
const colors = require('colors');
const electron = require ('electron');
const ip = require('ip');
const PUERTO = 9090;
//-- Crear una nueva aplciacion web
const app = express();
let win = null;
//-- Crear un servidor, asosiaco a la App de express
const server = http.Server(app);
//-- Crear el servidor de websockets, asociado al servidor http
const io = new socketServer(server);
//-------- PUNTOS DE ENTRADA DE LA APLICACION WEB
//-- Definir el punto de entrada principal de mi aplicación web
app.get('/', (req, res) => {
let path = __dirname + 'public/chat.html';
res.sendFile(path);
});
//-- Esto es necesario para que el servidor le envíe al cliente la
//-- biblioteca socket.io para el cliente
app.use('/', express.static(__dirname +'/'));
//-- El directorio publico contiene ficheros estáticos
app.use(express.static('public'));
//Establezco un valor predeterminado para la variable num
let num = 0;
//------------------- GESTION SOCKETS IO
//-- Evento: Nueva conexion recibida
io.on('connect', (socket) => {
console.log('** NUEVA CONEXIÓN **'.yellow);
// Mensaje de bienvenida al chat
socket.write('¡Bienvenido al chat de ISAM!');
// El numero de usuarios aumenta 1 cada vez que alguien se conecta
num += 1;
win.webContents.send('numus', num);
//-- Evento de desconexión
socket.on('disconnect', function(){
console.log('** CONEXIÓN TERMINADA **'.yellow);
//Mensaje a los demás usuarios informando de que alguién abandonó el chat
io.send('Un usuario ha abandonado el chat');
// El número de usuarios en el servidor disminuye 1
num -= 1;
win.webContents.send('numus', num);
});
//-- Mensaje recibido: Reenviarlo a todos los clientes conectados
socket.on("message", (msg)=> {
// Establezco ifs que determinan que si el mensaje incluye ese comando y no la frase ' se ha unido</h5>',
// entonces hará una cosa u otra dependiendo del comando que le pides
if (msg.includes('/help') && !msg.includes(' se ha unido</h5>')){
// imprime una lista de comandos a usar y sus funciones
socket.write('Los comandos disponibles son: <br> <strong>/help:</strong> Este mismo :) <br> <strong>/list:</strong> Devolverá el número de usuarios conectados <br> <strong>/hello:</strong> El servidor nos devolverá el saludo <br> <strong>/date:</strong> Nos devolverá la fecha');
}else if(msg.includes('/hello') && !msg.includes(' se ha unido</h5>')){
// Te saluda
socket.write('¡Hola! Mucho ánimo con la carrera :)');
}else if(msg.includes('/list') && !msg.includes(' se ha unido</h5>')){
// Te dice el número total de usuarios conectados al servidor
socket.write('Hay un total de ' + num + ' usuarios conectados');
}else if(msg.includes('/date') && !msg.includes(' se ha unido</h5>')){
// Establece la fecha
const tiempoTranscurrido = Date.now();
const hoy = new Date(tiempoTranscurrido);
// Imprime la fecha, específicamente la de España, en el formato Español
socket.write('Hoy es: ' + hoy.toLocaleString('es-ES'));
}else if(msg.includes('/' + '') && !msg.includes(' se ha unido</h5>') && !msg.includes('/date') && !msg.includes('/list') && !msg.includes('/help') && !msg.includes('/hello') ){
// Si usas un comando no establecido, te salta un error con el siguiente mensaje:
socket.write('Lo siento pero no es un comando válido :(');
}else{
// Si lo escrito no es un comando, se imprime en el chat y en el terminal el mensaje que has escrito
console.log("Mensaje Recibido!: " + msg.blue);
//-- Reenviarlo a todos los clientes conectados
io.send(msg);
}
// Se envía al display
win.webContents.send('display', msg);
});
});
electron.app.on('ready', () => {
win = new electron.BrowserWindow({
width: 600,
height: 600,
// permitir acceso al sistema
webPreferences: {
nodeIntegration: true,
contextIsolation: false
}
})
win.loadFile("index.html");
win.on('ready-to-show', () => {
win.webContents.send('port', PUERTO);
})
// Se envía la url del usuario
win.on('ready-to-show', () => {
win.webContents.send('ip', 'http://' + ip.address() + ':' + PUERTO + '/public/chat.html');
});
});
electron.ipcMain.handle('test', (event, msg) => {
console.log(msg);
//-- Enviar mensaje de prueba
io.send(msg);
win.webContents.send('msg', msg);
});
//-- Lanzar el servidor HTTP
//-- ¡Que empiecen los juegos de los WebSockets!
server.listen(PUERTO);
console.log("Escuchando en puerto: " + PUERTO);
Para empezar a usar mi servidor y después de haberte descargado mi carpeta P4, debes ingresar los siguientes comandos (uno a uno) en el terminal de la carpeta. Asegúrate de primero haberte descargado también el fichero package.json de mi P4 (sino tendrás que crearte uno tu mismo, abajo te dejo el código del package.json que te tendrías que crear ANTES DE INTRODUCIR LOS COMANDOS):
-
npm i ip
-
npm i colors
-
npm i express
-
npm i electron
-
npm i socket.io
-
npm i
(este es por si a caso) -
Package.json:
{
"name": "mi-electron-app",
"description": "Estas es mi primera aplicación de escritorio en Electron",
"version": "0.1.0",
"main": "main.js",
"scripts": {
"start": "electron ."
},
"dependencies": {
"electron": "^18.0.1"
}
}
Después, solo hace falta introducir el siguiente comando para iniciarlo:
npm start
Una vez en el servidor, copia el URL del usuario y pégalo en tu navegador. ¡Ahora puedes escribir mensajes y enviarlos al servidor, donde podrás hablar con más gente conectada! En el servidor te aparecerá el número de usuarios conectados (para asegurarte de que no estás hablando solo ;) ). Puedes pulsar el botón de prueba para enviar un mensaje de prueba a todos los usuarios en línea si quieres. También podrás personalizar tu nombre de usuario, como en la práctica 3.