project created

This commit is contained in:
2025-07-25 22:03:20 +12:00
parent b80f759df2
commit 1b6c58a348
27 changed files with 211 additions and 5271 deletions
+77 -230
View File
@@ -1,245 +1,92 @@
// main.js
const { app, BrowserWindow, BrowserView, ipcMain } = require('electron'); // Add ipcMain here
const path = require('node:path');
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain, session } = require('electron');
const { pathToFileURL } = require('url');
const path = require('path');
const os = require('os');
const fs = require('fs');
let mainWindow;
let browserView;
const createWindow = () => {
mainWindow = new BrowserWindow({
width: 1000,
height: 700,
minWidth: 800,
minHeight: 600,
titleBarStyle: 'hiddenInset',
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
nodeIntegration: false,
contextIsolation: true,
webviewTag: false
}
});
app.commandLine.appendSwitch('ignore-gpu-blacklist');
mainWindow.loadFile('index.html');
// Open the DevTools.
// mainWindow.webContents.openDevTools();
if (process.platform === 'win32') {
app.commandLine.appendSwitch('disable-gpu-sandbox');
app.commandLine.appendSwitch('no-sandbox');
}
browserView = new BrowserView({
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
}
});
mainWindow.setBrowserView(browserView);
const navBarHeight = 80; // Make sure this matches your CSS navbar height
const updateBrowserViewBounds = () => {
const { width, height } = mainWindow.getBounds();
browserView.setBounds({ x: 0, y: navBarHeight, width: width, height: height - navBarHeight });
};
// Function to check if the application is running on SteamOS
const isSteamOS = () => {
updateBrowserViewBounds(); // Set initial bounds
browserView.webContents.loadURL('https://www.google.com');
return os.platform() === 'linux' && os.release().includes('steam');
mainWindow.on('resize', updateBrowserViewBounds);
// --- IPC Handlers ---
ipcMain.on('load-url', (event, url) => {
let formattedUrl = url;
// Basic URL formatting: if no protocol, assume https://
if (!formattedUrl.match(/^[a-zA-Z]+:\/\//)) {
formattedUrl = 'https://' + formattedUrl;
}
browserView.webContents.loadURL(formattedUrl).catch(err => {
console.error('Failed to load URL:', err);
// Optionally send an error back to the renderer
});
});
ipcMain.on('go-back', () => {
if (browserView.webContents.canGoBack()) {
browserView.webContents.goBack();
}
});
ipcMain.on('go-forward', () => {
if (browserView.webContents.canGoForward()) {
browserView.webContents.goForward();
}
});
ipcMain.on('refresh-page', () => {
browserView.webContents.reload();
});
// --- End IPC Handlers ---
};
// Bookmark management functions
const bookmarksPath = path.join(__dirname, 'data', 'bookmarks.json');
const homeBookmarksPath = path.join(__dirname, 'data', 'home-bookmarks.json');
const loadBookmarks = () => {
try {
if (fs.existsSync(bookmarksPath)) {
const data = fs.readFileSync(bookmarksPath, 'utf8');
return JSON.parse(data);
}
} catch (error) {
console.error('Error loading bookmarks:', error);
}
return { bookmarks: [] };
};
const saveBookmarks = (bookmarksData) => {
try {
fs.writeFileSync(bookmarksPath, JSON.stringify(bookmarksData, null, 2));
return true;
} catch (error) {
console.error('Error saving bookmarks:', error);
return false;
}
};
const loadHomeBookmarks = () => {
try {
if (fs.existsSync(homeBookmarksPath)) {
const data = fs.readFileSync(homeBookmarksPath, 'utf8');
return JSON.parse(data);
}
} catch (error) {
console.error('Error loading home bookmarks:', error);
}
return { home_bookmarks: [] };
};
const saveHomeBookmarks = (bookmarksData) => {
try {
fs.writeFileSync(homeBookmarksPath, JSON.stringify(bookmarksData, null, 2));
return true;
} catch (error) {
console.error('Error saving home bookmarks:', error);
return false;
}
};
// IPC handlers for bookmark functionality
ipcMain.handle('get-bookmarks', () => {
return loadBookmarks();
});
ipcMain.handle('get-home-bookmarks', () => {
return loadHomeBookmarks();
});
ipcMain.handle('add-bookmark', (event, bookmark) => {
const bookmarksData = loadBookmarks();
// Check if bookmark already exists
const exists = bookmarksData.bookmarks.some(b => b.url === bookmark.url);
if (exists) {
return { success: false, message: 'Bookmark already exists' };
}
// Add timestamp
bookmark.dateAdded = new Date().toISOString();
bookmarksData.bookmarks.push(bookmark);
const saved = saveBookmarks(bookmarksData);
return { success: saved, message: saved ? 'Bookmark added' : 'Failed to save bookmark' };
});
ipcMain.handle('add-home-bookmark', (event, bookmark) => {
const bookmarksData = loadHomeBookmarks();
// Check if bookmark already exists
const exists = bookmarksData.home_bookmarks.some(b => b.url === bookmark.url);
if (exists) {
return { success: false, message: 'Bookmark already exists' };
}
// Add timestamp
bookmark.dateAdded = new Date().toISOString();
bookmarksData.home_bookmarks.push(bookmark);
const saved = saveHomeBookmarks(bookmarksData);
return { success: saved, message: saved ? 'Bookmark added' : 'Failed to save bookmark' };
});
ipcMain.handle('remove-bookmark', (event, url) => {
const bookmarksData = loadBookmarks();
const initialLength = bookmarksData.bookmarks.length;
bookmarksData.bookmarks = bookmarksData.bookmarks.filter(b => b.url !== url);
if (bookmarksData.bookmarks.length < initialLength) {
const saved = saveBookmarks(bookmarksData);
return { success: saved, message: saved ? 'Bookmark removed' : 'Failed to save bookmarks' };
}
return { success: false, message: 'Bookmark not found' };
});
ipcMain.handle('remove-home-bookmark', (event, url) => {
const bookmarksData = loadHomeBookmarks();
const initialLength = bookmarksData.home_bookmarks.length;
bookmarksData.home_bookmarks = bookmarksData.home_bookmarks.filter(b => b.url !== url);
if (bookmarksData.home_bookmarks.length < initialLength) {
const saved = saveHomeBookmarks(bookmarksData);
return { success: saved, message: saved ? 'Bookmark removed' : 'Failed to save bookmarks' };
}
return { success: false, message: 'Bookmark not found' };
});
// Handle clear cookies request from settings page
ipcMain.handle('clear-cookies', async (event) => {
try {
const ses = event.sender.session;
await ses.clearStorageData({ storages: ['cookies'] });
return { success: true };
} catch (error) {
console.error('Error clearing cookies:', error);
return { success: false, error: error.message };
}
});
// Handle go-home request from settings page to navigate back to home
ipcMain.handle('go-home', (event) => {
// event.sender is the webContents of the webview
const wc = event.sender;
const homePath = path.join(__dirname, 'frontend', 'pages', 'home.html');
// Convert file path to file:// URL and load in the webview
const homeUrl = pathToFileURL(homePath).href;
wc.loadURL(homeUrl);
return { success: true };
});
// Handle clear bookmarks request from settings page
ipcMain.handle('clear-bookmarks', (event) => {
try {
fs.writeFileSync(bookmarksPath, JSON.stringify({ bookmarks: [] }, null, 2));
return { success: true };
} catch (error) {
console.error('Error clearing bookmarks:', error);
return { success: false, error: error.message };
}
});
// Handle clear home bookmarks request from settings page
ipcMain.handle('clear-home-bookmarks', (event) => {
try {
fs.writeFileSync(homeBookmarksPath, JSON.stringify({ home_bookmarks: [] }, null, 2));
return { success: true };
} catch (error) {
console.error('Error clearing home bookmarks:', error);
return { success: false, error: error.message };
}
});
function createWindow() {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 1280,
height: 720,
webPreferences: {
preload: path.join(__dirname, 'preload.js'),
// The webview tag is essential for our browser's core functionality.
webviewTag: true,
// For security reasons, it's good practice to disable nodeIntegration
// and use a preload script to expose specific functionalities.
nodeIntegration: false,
contextIsolation: true,
},
});
// Remove default application menu (File, Edit, View)
mainWindow.removeMenu();
// Load the index.html of the app.
mainWindow.loadFile('frontend/index.html');
// Pass the SteamOS status to the renderer process
mainWindow.webContents.on('did-finish-load', () => {
mainWindow.webContents.send('is-steam-os', isSteamOS());
});
// Open the DevTools.
// mainWindow.webContents.openDevTools()
}
// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.whenReady().then(() => {
createWindow();
createWindow();
app.on('activate', function () {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
app.on('activate', () => {
if (BrowserWindow.getAllWindows().length === 0) {
createWindow();
}
});
});
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit();
});
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') {
app.quit();
}
});