207 lines
6.1 KiB
TypeScript
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;
|
|
});
|
|
}
|