va-tracker/src/electron/main.ts

207 lines
6.1 KiB
TypeScript

import { app, BrowserWindow, Menu, desktopCapturer, ipcMain, safeStorage } from 'electron';
import { ipcMainHandle, ipcMainOn, isDev } from './util.js';
import { getStaticData, pollResources } from './resourceManager.js';
import { getPreloadPath, getUIPath } from './pathResolver.js';
import { createTray } from './tray.js';
import { createMenu } from './menu.js';
import Store from 'electron-store';
import * as fs from "fs";
import path from "path";
import axios from 'axios';
import sharp from 'sharp';
app.on('ready', async () => {
console.log("ready")
const mainWindow = new BrowserWindow({
webPreferences: {
preload: getPreloadPath(),
},
// disables default system frame (dont do this if you want a proper working menu bar)
frame: process.platform === 'darwin' ? false : true,
autoHideMenuBar: true
});
if (isDev()) {
mainWindow.loadURL('http://localhost:5123');
mainWindow.webContents.openDevTools();
} else {
mainWindow.loadFile(getUIPath());
}
pollResources(mainWindow);
ipcMainHandle('getStaticData', () => {
return getStaticData();
});
ipcMainOn('sendFrameAction', (payload) => {
switch (payload) {
case 'CLOSE':
mainWindow.close();
break;
case 'MAXIMIZE':
mainWindow.maximize();
break;
case 'MINIMIZE':
mainWindow.minimize();
break;
}
});
// createTray(mainWindow);
handleCloseEvents(mainWindow);
// createMenu(mainWindow);
// await takeScreenshot();
});
// Blur using an offscreen canvas
async function blurAndCompressBase64Image(base64: string) : Promise<Buffer> {
const buffer = Buffer.from(base64.replace(/^data:image\/\w+;base64,/, ''), 'base64');
const outputBuffer = await sharp(buffer)
.blur(8) // adjust blur radius here
.jpeg({ quality: 70 }) // compress output
.toBuffer();
return outputBuffer;
}
async function takeScreenshot() {
// const sources = await desktopCapturer.getSources({ types: ["screen"] });
const sources = await desktopCapturer.getSources({
types: ['window'], thumbnailSize: {
height: 768,
width: 1366
}
});
// Capture the first screen (you can choose others by filtering sources)
const screen = sources[0];
let image = screen.thumbnail.toDataURL();
console.log("blurAndCompressBase64Image Calling")
const blurredBuffer = await blurAndCompressBase64Image(image);
const folderPath = "C:\\Users\\Public\\vatracker\\screenshots";
// Ensure directory exists
if (!fs.existsSync(folderPath)) {
fs.mkdirSync(folderPath, { recursive: true });
}
const filePath = path.join(folderPath, `screenshot-${Date.now()}.png`);
fs.writeFileSync(filePath, blurredBuffer);
console.log(`Screenshot saved at: ${filePath}`);
}
ipcMain.handle('upload-screenshot', async () => {
takeScreenshot()
})
async function saveToken(accessToken: string, refreshToken: string | null = null) {
const encryptedAccessToken = safeStorage.encryptString(accessToken);
let encryptedRefreshToken = null;
if (refreshToken != null) {
encryptedRefreshToken = safeStorage.encryptString(refreshToken);
}
// Store encrypted token (example: using a file or electron-store)
// For simplicity, using Electron's built-in localStorage is not available in main, so use electron-store or filesystem.
// Here assume electron-store is already installed and set up:
const store = new Store();
store.set("access_token", encryptedAccessToken.toString('base64'));
if (encryptedRefreshToken != null) {
store.set("refresh_token", encryptedRefreshToken.toString('base64'));
}
}
async function getToken(TOKEN_KEY: string) {
const store = new Store();
const encryptedBase64 = store.get(TOKEN_KEY) as string | undefined;
if (!encryptedBase64) return null;
const encryptedBuffer = Buffer.from(encryptedBase64, 'base64');
return safeStorage.decryptString(encryptedBuffer);
}
ipcMain.handle('get-token', async (event, TOKEN_KEY) => {
// return decrypted token from secure storage
return await getToken(TOKEN_KEY);
});
ipcMain.handle('save-token', async (event, token) => {
await saveToken(token);
return true;
});
// Handle login request from renderer
ipcMain.handle('login-request', async (event, credentials: { email: string, password: string }) => {
try {
// Call your login API
console.log("🟡 login Request received", credentials);
try {
console.log("➡️ Calling API...");
const response = await axios.post(
'https://wired-terminally-muskrat.ngrok-free.app/api/v1/va/login',
{ userDetails: { ...credentials } },
{ headers: { "ngrok-skip-browser-warning": 69420 } }
);
const { accessToken, refreshToken } = response.data;
await saveToken(accessToken, refreshToken);
return { success: true, user: response.data.user };
} catch (error) {
if (error instanceof Error) {
if ("response" in error && typeof (error.response) == "object" && error.response !== null && ("data" in error.response)) {
console.log("❌ login API call failed:", error?.response.data);
console.log("Server responded:", error?.response.data);
return { success: false, error: error?.response.data || "Request failed" };
} else {
return { success: false, error: error?.message || "Check you Internet connection and try again" };
}
}
}
} catch (err) {
if (err instanceof Error) {
return { success: false, error: err.message };
}
if (typeof err === "object" && err !== null && "response" in err) {
const axiosErr = err as any;
return { success: false, error: axiosErr.response?.data?.message || "Unknown error" };
}
return { success: false, error: "Unexpected error occurred" };
}
});
function handleCloseEvents(mainWindow: BrowserWindow) {
let willClose = false;
mainWindow.on('close', (e) => {
if (willClose) {
return;
}
e.preventDefault();
mainWindow.hide();
if (app.dock) {
app.dock.hide();
}
});
app.on('before-quit', () => {
willClose = true;
});
mainWindow.on('show', () => {
willClose = false;
});
}