317 lines
9.1 KiB
TypeScript
317 lines
9.1 KiB
TypeScript
import path, { resolve } from "path";
|
|
import { app, ipcMain } from "electron";
|
|
import serve from "electron-serve";
|
|
import { createWindow } from "./helpers";
|
|
import { SerialPort } from "serialport";
|
|
import { print } from "pdf-to-printer";
|
|
import fs from "fs";
|
|
import download from "download";
|
|
|
|
const isProd = process.env.NODE_ENV === "production";
|
|
|
|
if (isProd) {
|
|
serve({ directory: "app" });
|
|
} else {
|
|
app.setPath("userData", `${app.getPath("userData")} (development)`);
|
|
}
|
|
|
|
(async () => {
|
|
await app.whenReady();
|
|
|
|
const mainWindow = createWindow("main", {
|
|
width: 1000,
|
|
height: 600,
|
|
webPreferences: {
|
|
preload: path.join(__dirname, "preload.js"),
|
|
},
|
|
});
|
|
|
|
if (isProd) {
|
|
await mainWindow.loadURL("app://./home");
|
|
mainWindow.setMenuBarVisibility(false);
|
|
mainWindow.setFullScreen(true);
|
|
} else {
|
|
const port = process.argv[2];
|
|
await mainWindow.loadURL(`http://localhost:${port}/configuracionMonedero`);
|
|
mainWindow.setMenuBarVisibility(false);
|
|
mainWindow.webContents.openDevTools();
|
|
}
|
|
})();
|
|
|
|
app.on("window-all-closed", () => {
|
|
app.quit();
|
|
});
|
|
|
|
ipcMain.on("message", async (event, arg) => {
|
|
event.reply("message", `${arg} World!`);
|
|
});
|
|
|
|
/* Variables */
|
|
const api = process.env.REACT_APP_ROOT;
|
|
let PuertoSerialMonedero = null;
|
|
let dinero: number = 0;
|
|
|
|
/* Configuracion del kiosco*/
|
|
|
|
ipcMain.on("getApi", async (event, arg) => {
|
|
event.reply("getApi", api);
|
|
});
|
|
|
|
ipcMain.on("BuscarMonedero", async (event, path) => {
|
|
try {
|
|
const list = await SerialPort.list();
|
|
|
|
if (list.length === 0) {
|
|
throw new Error("La lista de puertos está vacia");
|
|
}
|
|
|
|
const puerto = buscarPuerto(list);
|
|
|
|
if (!puerto) {
|
|
throw new Error("No se pudo detectar el monedero");
|
|
}
|
|
|
|
const puertoMonedero = puerto.path;
|
|
|
|
event.sender.send("GetPuertoMonedero", `${puertoMonedero}`);
|
|
} catch (error) {
|
|
console.log("Ha ocurrido un error en: Monedero");
|
|
}
|
|
});
|
|
|
|
ipcMain.on("AbrirPuerto", async (event, path) => {
|
|
try {
|
|
if (!PuertoSerialMonedero) {
|
|
// Si el puerto es null, creamos una nueva instancia del puerto serie
|
|
PuertoSerialMonedero = new SerialPort({
|
|
path: path,
|
|
baudRate: 9600,
|
|
});
|
|
|
|
// Evento 'open' para cuando el puerto se abre con éxito
|
|
PuertoSerialMonedero.on("open", () => {
|
|
event.reply("EstadoPuerto", { abierto: true }); // Enviar mensaje si el puerto está abierto
|
|
});
|
|
|
|
// Evento 'error' para manejar errores que puedan ocurrir durante la operación del puerto
|
|
PuertoSerialMonedero.on("error", (error) => {
|
|
console.error("Error en Puerto Serial:", error);
|
|
event.reply("EstadoPuerto", { abierto: false }); // Enviar mensaje si se produce un error al abrir el puerto
|
|
});
|
|
} else if (!PuertoSerialMonedero.isOpen) {
|
|
// Si el puerto existe pero está cerrado, intentamos abrirlo
|
|
PuertoSerialMonedero.open((error) => {
|
|
if (error) {
|
|
console.error("Error al abrir el puerto:", error);
|
|
event.reply("EstadoPuerto", { abierto: false }); // Enviar mensaje si se produce un error al abrir el puerto
|
|
} else {
|
|
event.reply("EstadoPuerto", { abierto: true }); // Enviar mensaje si el puerto está abierto
|
|
}
|
|
});
|
|
} else {
|
|
// Si el puerto ya está abierto, mostramos un mensaje indicando que ya está en uso
|
|
console.log("El Puerto Serial ya está abierto");
|
|
event.reply("EstadoPuerto", { abierto: true }); // Enviar mensaje si el puerto está abierto
|
|
}
|
|
|
|
PuertoSerialMonedero.on("data", (data) => {
|
|
let coin = parseInt(data, 10);
|
|
dinero = dinero + coin;
|
|
console.log("Dinero Depositado: ", dinero);
|
|
|
|
event.sender.send("CantidadDinero", dinero);
|
|
});
|
|
} catch (error) {
|
|
console.error("Ha ocurrido un error en: AbrirPuerto", error);
|
|
event.sender.send("EstadoPuerto", { abierto: false }); // Enviar mensaje si se produce un error
|
|
}
|
|
});
|
|
|
|
ipcMain.on("openDial", async (event, data) => {
|
|
console.log("Peticion de impresion");
|
|
try {
|
|
if (!data.api || !data.fileId || !data.token) {
|
|
throw new Error("Datos incompletos");
|
|
}
|
|
|
|
const filePath = await descargarArchivo(data.api, data.fileId, data.token);
|
|
const res = await imprimirArchivo(filePath);
|
|
|
|
/* console.log(res); */
|
|
if (res) {
|
|
console.log("Proceso Main de impresion finalizado con exito");
|
|
event.reply("finishPrint", data.fileId);
|
|
}
|
|
|
|
// Limpiar eventos adicionales si es necesario
|
|
event.reply("cleanFinishPrint", "");
|
|
} catch (error) {
|
|
console.error(error);
|
|
// Enviar mensaje de error al cliente
|
|
event.reply("finishPrintError", error.message);
|
|
}
|
|
});
|
|
|
|
/* Auxiliares */
|
|
|
|
const buscarPuerto = (puertos) => {
|
|
for (const puerto of puertos) {
|
|
const friendlyName = puerto.friendlyName.substring(0, 10);
|
|
|
|
if (friendlyName === "USB-SERIAL") {
|
|
return puerto;
|
|
}
|
|
}
|
|
|
|
return undefined;
|
|
};
|
|
|
|
ipcMain.on("getApi", async (event, arg) => {
|
|
event.reply("getApi", api);
|
|
});
|
|
|
|
ipcMain.on("LimpiarDinero", (event, path) => {
|
|
dinero = 0;
|
|
console.log("Dinero Limpio: ", dinero);
|
|
event.reply("LimpiarDinero", dinero);
|
|
});
|
|
|
|
ipcMain.on("statusPuerto", async (event, arg) => {
|
|
try {
|
|
if (PuertoSerialMonedero && PuertoSerialMonedero.isOpen) {
|
|
event.reply("statusPuerto", { abierto: true });
|
|
} else {
|
|
event.reply("statusPuerto", { abierto: false });
|
|
}
|
|
} catch (error) {
|
|
console.error("Error al verificar estado del puerto:", error);
|
|
event.reply("statusPuerto", { abierto: false }); // Enviar mensaje de estado false en caso de error
|
|
}
|
|
});
|
|
|
|
async function descargarArchivo(api, fileId, token) {
|
|
const url = `${api}/getFile/${fileId}/${token}`;
|
|
const filePath = "public/file.pdf";
|
|
await download(url).pipe(fs.createWriteStream(filePath));
|
|
return filePath;
|
|
}
|
|
|
|
async function imprimirArchivo(filePath) {
|
|
try {
|
|
await print(filePath, {});
|
|
console.log("Exito al imprimir");
|
|
return true;
|
|
} catch (error) {
|
|
console.log("Error al imprimir", error);
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
import { BrowserWindow, BrowserView, WebContentsView } from "electron";
|
|
import { URL } from "url";
|
|
import axios from "axios";
|
|
|
|
ipcMain.handle("login-with-google", async () => {
|
|
return new Promise(async (resolve, reject) => {
|
|
const authWindow = new BrowserWindow({
|
|
width: 800,
|
|
height: 700,
|
|
fullscreen: true,
|
|
frame: false,
|
|
webPreferences: {
|
|
nodeIntegration: false,
|
|
contextIsolation: true,
|
|
},
|
|
});
|
|
|
|
await authWindow.webContents.session.clearStorageData({
|
|
storages: ["cookies"],
|
|
});
|
|
|
|
await authWindow.loadURL("http://localhost:3000/persona/google");
|
|
|
|
// ---------------------------------------------------------
|
|
// 🔹 Teclado virtual en WebContentsView
|
|
// ---------------------------------------------------------
|
|
const keyboardView = new BrowserView({
|
|
webPreferences: {
|
|
preload: path.join(__dirname, "preload.js"),
|
|
nodeIntegration: false,
|
|
contextIsolation: true,
|
|
},
|
|
});
|
|
|
|
authWindow.addBrowserView(keyboardView);
|
|
|
|
keyboardView.webContents.loadURL("http://localhost:8888/teclado");
|
|
|
|
const bounds = authWindow.getBounds();
|
|
keyboardView.setBounds({
|
|
x: 0,
|
|
y: bounds.height - 260, // altura del teclado
|
|
width: bounds.width,
|
|
height: 260,
|
|
});
|
|
|
|
keyboardView.setAutoResize({
|
|
width: true,
|
|
horizontal: true,
|
|
vertical: false,
|
|
});
|
|
// ---------------------------------------------------------
|
|
|
|
// BOTÓN DE CANCELAR
|
|
const cancelView = new BrowserView({
|
|
webPreferences: {
|
|
nodeIntegration: true,
|
|
contextIsolation: false,
|
|
},
|
|
});
|
|
authWindow.addBrowserView(cancelView);
|
|
cancelView.setBounds({ x: 1000, y: 50, width: 50, height: 50 });
|
|
|
|
cancelView.webContents.loadURL(
|
|
"data:text/html," +
|
|
encodeURIComponent(`
|
|
<button id="cancel" style="width:100%;height:100%;font-size:20px;color:white;background:red;border:none;borderRadius:10px;">X</button>
|
|
<script>
|
|
const { ipcRenderer } = require('electron');
|
|
document.getElementById('cancel').addEventListener('click', () => {
|
|
ipcRenderer.send('google-login-cancel');
|
|
});
|
|
</script>
|
|
`)
|
|
);
|
|
|
|
ipcMain.once("google-login-cancel", () => {
|
|
authWindow.close();
|
|
reject(new Error("Login cancelado por el usuario"));
|
|
});
|
|
|
|
authWindow.webContents.on("will-redirect", async (event, url) => {
|
|
if (url.startsWith("http://localhost:8888/oauth-callback")) {
|
|
event.preventDefault();
|
|
const token = new URL(url).searchParams.get("token");
|
|
const error = new URL(url).searchParams.get("error");
|
|
|
|
if (error || !token) {
|
|
authWindow.close();
|
|
return reject(new Error("Login cancelado o fallido"));
|
|
}
|
|
|
|
try {
|
|
const response = await axios.get("http://localhost:3000/persona/me", {
|
|
headers: { Authorization: `Bearer ${token}` },
|
|
});
|
|
resolve({ data: { ...response.data.data, token } });
|
|
} catch (err) {
|
|
reject(err);
|
|
} finally {
|
|
authWindow.close();
|
|
}
|
|
}
|
|
});
|
|
|
|
authWindow.on("closed", () => reject(new Error("Login cancelado")));
|
|
});
|
|
}); |