Initial commit
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
! /startup/index.js — Central Bootloader Module
|
||||
? Main entry point for initializing the application (with splash screen)
|
||||
*/
|
||||
|
||||
module.exports = async () => {
|
||||
|
||||
// $ create splash screen
|
||||
// ?? Usage: "splash.update(processINT, messageSTRING, staticBOOLEAN)" to update the splash screen and "splash.close()" to close the splash screen
|
||||
const splash = await require('./screen/init')(); // execute electron initialization script
|
||||
splash.update(0, "Starting"); // update splash screen via ipc
|
||||
await new Promise(resolve => setTimeout(resolve, 3500)); // set 3.5 second waiting timer
|
||||
|
||||
// % load node dependencies
|
||||
// ?? Usage: "npm.packageName" (e.g. npm.express)
|
||||
splash.update(0, "Loading Packages"); // update splash screen via ipc
|
||||
const npm = require('./modules/nodeDependencies'); // execute nodejs initialization script
|
||||
await new Promise(resolve => setTimeout(resolve, 1500)); // set 1.5 second waiting timer
|
||||
|
||||
// % load directories
|
||||
// ?? Usage: "dir.dirName" (e.g. dir.coreDir)
|
||||
splash.update(0, "Loading Directories"); // update splash screen via ipc
|
||||
await new Promise(resolve => setTimeout(resolve, 1500)); // set 1.5 second waiting timer
|
||||
const dir = await require('./modules/directoryDependencies')(splash, npm); // execute directory initialization script
|
||||
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
/*
|
||||
! /startup/modules/directoryDependencies.js — Directory Dependency Loader
|
||||
? This module loads every directory, creates or updates the user folder and returns them to the boot loader.
|
||||
*/
|
||||
|
||||
module.exports = async (splash, npm) => {
|
||||
};
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
! /startup/modules/nodeDependencies.js — NodeJS Dependency Loader
|
||||
? This module loads every nodejs dependency and returns them to the boot loader.
|
||||
*/
|
||||
|
||||
module.exports = {
|
||||
// % dev packages
|
||||
bSync: require('browser-sync'), // automatic sync in browser after changes
|
||||
|
||||
// % file system packages
|
||||
path: require('path'), // handling file and directory paths
|
||||
fs: require('fs'), // filesystem operations
|
||||
AdmZip: require('AdmZip'), // zip file manager
|
||||
|
||||
// % server packages
|
||||
net: require('net'), // network identification
|
||||
express: require('express'), // local server
|
||||
electron: require('electron'), // window creation
|
||||
ws: require('ws'), // pure websockets for data streams
|
||||
sio: require('socket.io'), // real-time events for ui
|
||||
axios: require('axios'), // http client for api requests
|
||||
|
||||
// % utility packages
|
||||
os: require('os'), // operating system information
|
||||
si: require('systeminformation'), // get system information
|
||||
|
||||
// % database packages
|
||||
ini: require('ini'), // read & manage .conf or .ini files
|
||||
sqlite: require('better-sqlite3'), // fast local sql database
|
||||
|
||||
// % security packages
|
||||
crypto: require('crypto'), // secure features for server connection
|
||||
bcrypt: require('bcrypt'), // hashing features for pass hashing
|
||||
|
||||
// % media packages
|
||||
ffmpeg: require('fluent-ffmpeg'), // interface for video encoding
|
||||
ffmpegPath: require('ffmpeg-static'), // reference for physical ffmpeg path
|
||||
|
||||
// % load minify dependencies
|
||||
minify: require('express-minify'), // js & css compression
|
||||
minifyHTML: require('express-minify-html-2'), // html minification
|
||||
cleanCSS: require('clean-css'), // stylesheet optimization
|
||||
uglifyJS: require('uglify-js'), // javascript compression
|
||||
|
||||
// % external packages
|
||||
obs: require('obs-websocket-js'), // obs studio remote control
|
||||
gemini: require('@google/generative-ai'), // google gemini ai sdk
|
||||
};
|
||||
@@ -0,0 +1,104 @@
|
||||
<html>
|
||||
<head>
|
||||
<style>
|
||||
body {
|
||||
width: 100vw;
|
||||
height: 100vh;
|
||||
overflow: hidden;
|
||||
margin: 0;
|
||||
display: flex;
|
||||
background: transparent;
|
||||
flex-direction: column;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: Arial, Helvetica, sans-serif;
|
||||
}
|
||||
|
||||
.loading {
|
||||
position: relative;
|
||||
width: 500px;
|
||||
height: auto;
|
||||
padding: 10px 0;
|
||||
border-radius: 15px;
|
||||
background: #101010;
|
||||
text-align: center;
|
||||
border: 1px solid #AA5CC3;
|
||||
box-shadow:
|
||||
0 0 10px rgba(0, 164, 220, 0.6),
|
||||
0 0 20px rgba(170, 92, 195, 0.5),
|
||||
0 0 35px rgba(139, 92, 246, 0.4);
|
||||
}
|
||||
|
||||
img {
|
||||
position: relative;
|
||||
width: 400px;
|
||||
height: auto;
|
||||
user-select: none;
|
||||
-webkit-user-drag: none;
|
||||
}
|
||||
|
||||
.processBar {
|
||||
width: 450px;
|
||||
height: 8px;
|
||||
background: rgba(170, 92, 195, .18);
|
||||
border-radius: 10px;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
left: 50%;
|
||||
transform: translate(-50%);
|
||||
}
|
||||
|
||||
.processBar100 {
|
||||
position: absolute;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
#processBar {
|
||||
height: 100%;
|
||||
width: 0%;
|
||||
background: linear-gradient(
|
||||
90deg,
|
||||
#00A4DC 0%,
|
||||
#AA5CC3 40%,
|
||||
#8B5CF6 100%
|
||||
);
|
||||
transition: width .3s ease;
|
||||
}
|
||||
|
||||
#processText {
|
||||
margin-top: 10px;
|
||||
color: white;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<section class="loading">
|
||||
|
||||
<img src="../../resources/images/full_logo.png" alt="App Logo">
|
||||
|
||||
<div class="processBar">
|
||||
<div class="processBar100"></div>
|
||||
<div id="processBar"></div>
|
||||
</div>
|
||||
|
||||
<p id="processText"></p>
|
||||
</section>
|
||||
|
||||
<script>
|
||||
window.splashAPI.onUpdate((data) => {
|
||||
const bar = document.getElementById("processBar");
|
||||
const text = document.getElementById("processText");
|
||||
|
||||
if (data.progress !== undefined) {
|
||||
bar.style.width = `${data.progress}%`;
|
||||
}
|
||||
|
||||
if (data.message) {
|
||||
text.textContent = data.message;
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
! /startup/screen/init.js – Splash Screen Initialization Module
|
||||
? This module will initialize the startup loading screen
|
||||
*/
|
||||
|
||||
module.exports = async () => {
|
||||
|
||||
// % load node dependencies
|
||||
const { app, BrowserWindow, Menu } = require('electron');
|
||||
const path = require('path');
|
||||
|
||||
// % splash screen variables
|
||||
let splashWin; // reference to the splash screen window
|
||||
let isReady = false; // initial ready state
|
||||
let pendingUpdate = null; // initial pending update state
|
||||
let animationInterval = null; // initial animation interval null
|
||||
|
||||
// $ create window function
|
||||
const createWindow = () => {
|
||||
// ~ initialize browser window
|
||||
splashWin = new BrowserWindow({
|
||||
title: "LupiNex Broadcast Studio",
|
||||
|
||||
// § window measures
|
||||
width: 600,
|
||||
height: 300,
|
||||
|
||||
// § window settings
|
||||
frame: false,
|
||||
transparent: true,
|
||||
alwaysOnTop: true,
|
||||
closable: false,
|
||||
show: false,
|
||||
|
||||
// § window webprefs
|
||||
webPreferences: {
|
||||
preload: path.join(__dirname, 'preload.js'),
|
||||
nodeIntegration: false,
|
||||
contextIsolation: true
|
||||
}
|
||||
});
|
||||
|
||||
// ~ check if window is ready to be displayed
|
||||
splashWin.once('ready-to-show', () => {
|
||||
splashWin.show(); // show the splash screen
|
||||
isReady = true; // set ready state to true
|
||||
if (pendingUpdate) updateWindow(pendingUpdate.progress, pendingUpdate.message); // execute a pending update
|
||||
});
|
||||
|
||||
// ~ ignore mouse events
|
||||
splashWin.setIgnoreMouseEvents(true);
|
||||
|
||||
// ~ remove application menu
|
||||
Menu.setApplicationMenu(null);
|
||||
|
||||
// ~ load html file
|
||||
splashWin.loadFile(path.join(__dirname, 'index.html'));
|
||||
|
||||
// ~ return window reference
|
||||
return splashWin;
|
||||
};
|
||||
|
||||
// $ update window function
|
||||
const updateWindow = (progress, message, isStatic = false) => {
|
||||
// ~ stop running intervals if applicable
|
||||
if (animationInterval) clearInterval(animationInterval);
|
||||
|
||||
// ~ create dot animation if not static
|
||||
if (!isStatic) {
|
||||
let dots = 0; // initial dot count
|
||||
|
||||
// § create interval
|
||||
animationInterval = setInterval(() => {
|
||||
dots = (dots + 1) % 4; // calculate dot count
|
||||
const animatedMessage = message + ".".repeat(dots); // add dots to message
|
||||
sendToWebContents(progress, animatedMessage); // execute update function
|
||||
}, 750);
|
||||
}
|
||||
|
||||
// ~ send status immediately
|
||||
sendToWebContents(progress, message);
|
||||
};
|
||||
|
||||
// ~ helper function to send update data
|
||||
const sendToWebContents = (progress, message) => {
|
||||
// § wait if electron is not ready
|
||||
if (!isReady) {
|
||||
pendingUpdate = { progress, message };
|
||||
return;
|
||||
}
|
||||
|
||||
// § send message to electron ipc
|
||||
if (splashWin && !splashWin.isDestroyed()) {
|
||||
splashWin.webContents.send('update-splash', {
|
||||
...(progress !== null && { progress }),
|
||||
message
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// $ close window function
|
||||
const closeWindow = () => {
|
||||
if (splashWin && !splashWin.isDestroyed()) splashWin.close();
|
||||
};
|
||||
|
||||
// $ electron lifecycle
|
||||
app.whenReady().then(() => { createWindow() });
|
||||
|
||||
// $ return window functions
|
||||
return {
|
||||
update: updateWindow,
|
||||
close: closeWindow
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
/*
|
||||
! /startup/screen/preload.js – Splash-Screen-IPC-Bridge
|
||||
? This small module creates a secure bridge between the Electron backend and the splash screen frontend
|
||||
*/
|
||||
|
||||
// % load electron dependencies
|
||||
const { contextBridge, ipcRenderer } = require('electron');
|
||||
|
||||
// $ listener for splash screen updates from main process
|
||||
contextBridge.exposeInMainWorld('splashAPI', {
|
||||
onUpdate: (callback) => ipcRenderer.on('update-splash', (event, data) => callback(data))
|
||||
});
|
||||
Reference in New Issue
Block a user