From 3d18d295bd3edfc590b6861ede8ff30b359c9f42 Mon Sep 17 00:00:00 2001
From: Puskar-Roy
Date: Thu, 9 Apr 2026 09:44:50 +0530
Subject: [PATCH 1/4] feat : split screen
---
src/renderer/css/components/split-view.css | 223 ++++++++++++++
src/renderer/index.html | 34 +++
src/renderer/js/app.js | 320 +++++++++++++++++----
3 files changed, 521 insertions(+), 56 deletions(-)
create mode 100644 src/renderer/css/components/split-view.css
diff --git a/src/renderer/css/components/split-view.css b/src/renderer/css/components/split-view.css
new file mode 100644
index 0000000..7be13ec
--- /dev/null
+++ b/src/renderer/css/components/split-view.css
@@ -0,0 +1,223 @@
+.split-thread {
+ display: none;
+ flex-direction: row;
+ height: 100%;
+ width: 100%;
+ overflow: hidden;
+ gap: 0;
+}
+
+.split-thread.active {
+ display: flex;
+}
+
+.split-column {
+ flex: 1;
+ display: flex;
+ flex-direction: column;
+ min-width: 0;
+ height: 100%;
+ background: rgba(255, 255, 255, 0.02);
+}
+
+.split-column.left {
+ border-right: none;
+}
+
+.column-header {
+ padding: 12px 16px;
+ border-bottom: 1px solid var(--border-color);
+ background: rgba(0, 0, 0, 0.2);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 10;
+}
+
+.split-messages {
+ flex: 1;
+ overflow-y: auto;
+ padding: 20px;
+ display: flex;
+ flex-direction: column;
+ gap: 16px;
+}
+
+.split-divider {
+ width: 1px;
+ background: var(--border-color);
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ z-index: 5;
+}
+
+.v-pill {
+ position: absolute;
+ top: 10px;
+ background: var(--bg-color);
+ border: 1px solid var(--border-color);
+ color: var(--text-secondary);
+ font-weight: 800;
+ font-size: 10px;
+ width: 24px;
+ height: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ border-radius: 50%;
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
+ transform: translateY(12px);
+}
+
+/* Response Label Style from Mockup */
+.model-response-label {
+ font-size: 11px;
+ font-weight: 700;
+ color: var(--accent-color);
+ text-transform: uppercase;
+ letter-spacing: 0.1em;
+ margin-bottom: 8px;
+ opacity: 0.8;
+}
+
+/* Adjustments for chat bubbles in split view */
+.split-messages .chat-message-ai,
+.split-messages .chat-message-user {
+ max-width: 100%;
+ margin-left: 0;
+ margin-right: 0;
+ font-size: 13px;
+ line-height: 1.5;
+ padding: 12px 16px;
+ border-radius: 12px;
+}
+
+.split-messages .chat-message-ai {
+ background: rgba(255, 255, 255, 0.04);
+}
+
+/* Fix for Thinking box (loading state) */
+.split-messages .chat-message-ai:has(.loading) {
+ background: transparent;
+ padding: 0 12px;
+ margin-bottom: 12px;
+}
+
+.split-messages .loading {
+ margin-top: 0;
+ background: rgba(255, 255, 255, 0.06);
+ padding: 10px 16px;
+ border-radius: 20px;
+ display: inline-flex;
+ align-items: center;
+ border: 1px solid rgba(255, 255, 255, 0.08);
+ box-shadow: 0 4px 15px rgba(0,0,0,0.2);
+}
+
+.split-messages .loading span {
+ font-size: 13px;
+ letter-spacing: 0.02em;
+}
+
+/* Scrollbar styling for split view - Sleeker */
+.split-messages::-webkit-scrollbar {
+ width: 3px;
+}
+
+.split-messages::-webkit-scrollbar-track {
+ background: transparent;
+}
+
+.split-messages::-webkit-scrollbar-thumb {
+ background: rgba(255, 255, 255, 0.12);
+ border-radius: 10px;
+}
+
+.split-messages::-webkit-scrollbar-thumb:hover {
+ background: var(--accent-color);
+}
+
+/* Dropdown Overrides for Split Headers */
+.column-header .custom-dropdown {
+ max-width: 280px;
+}
+
+.column-header .dropdown-trigger {
+ background: rgba(255, 255, 255, 0.04);
+ border: 1px solid rgba(255, 255, 255, 0.06);
+ height: 36px;
+ padding: 0 14px;
+ border-radius: 10px;
+}
+
+.column-header .dropdown-trigger:hover {
+ background: rgba(255, 255, 255, 0.08);
+ border-color: rgba(255, 255, 255, 0.1);
+}
+
+.column-header .dropdown-value {
+ font-weight: 600;
+ font-size: 12px;
+ color: var(--text-primary);
+}
+
+/* Speed and Performance Badges */
+.speed-badge {
+ font-size: 10px;
+ font-weight: 600;
+ color: var(--text-secondary);
+ background: rgba(255, 255, 255, 0.05);
+ padding: 2px 6px;
+ border-radius: 4px;
+ margin-left: 8px;
+ vertical-align: middle;
+}
+
+.faster-badge {
+ color: #ff9d00;
+ background: rgba(255, 157, 0, 0.1);
+ border: 1px solid rgba(255, 157, 0, 0.2);
+ font-size: 9px;
+ padding: 1px 5px;
+ text-transform: uppercase;
+ animation: pulse 2s infinite;
+}
+
+@keyframes pulse {
+ 0% { opacity: 0.8; }
+ 50% { opacity: 1; transform: scale(1.05); }
+ 100% { opacity: 0.8; }
+}
+
+.split-title-header {
+ font-family: 'Outfit', sans-serif;
+ font-size: 14px;
+ font-weight: 700;
+ color: var(--text-primary);
+ letter-spacing: 0.03em;
+ text-transform: uppercase;
+ display: flex;
+ align-items: center;
+ gap: 8px;
+}
+
+.split-title-header::before {
+ content: '';
+ display: block;
+ width: 3px;
+ height: 14px;
+ background: var(--accent-color);
+ border-radius: 10px;
+}
+
+/* Animations */
+.split-thread.active {
+ animation: fadeIn 0.3s ease-out;
+}
+
+@keyframes fadeIn {
+ from { opacity: 0; transform: translateY(10px); }
+ to { opacity: 1; transform: translateY(0); }
+}
diff --git a/src/renderer/index.html b/src/renderer/index.html
index ea1f623..10159fd 100644
--- a/src/renderer/index.html
+++ b/src/renderer/index.html
@@ -21,6 +21,7 @@
+
@@ -51,6 +52,12 @@
+
+
+
+
+
+ Terminal Shutdown
+
+ Exits the application immediately. Use this if shortcuts are disabled or in Stealth Mode.
+
+
Model Management
@@ -580,8 +591,8 @@ Global Keyboard Controls
- Quit
- Application
+ Toggle Visibility
+ (Boss Key)
Ctrl + Shift + Q
diff --git a/src/renderer/js/app.js b/src/renderer/js/app.js
index b744b38..e45b48b 100644
--- a/src/renderer/js/app.js
+++ b/src/renderer/js/app.js
@@ -124,14 +124,16 @@ async function init() {
function applyAppMode(mode) {
try {
+ scrubTooltips(mode);
+
+ // Fortress Mode: Disable mouse resizing in Stealth Mode
if (window.electronAPI && window.electronAPI.setAppMode) {
window.electronAPI.setAppMode(mode);
}
+
if (windowControls) {
windowControls.style.display = mode === 'normal' ? 'flex' : 'none';
}
-
- scrubTooltips(mode);
// Update dropdown if initialized
if (settingsAppMode) settingsAppMode.setValue(mode);
@@ -230,22 +232,65 @@ function handleProviderChange(provider) {
}
}
+let tooltipObserver = null;
+
function scrubTooltips(mode) {
try {
- const elements = document.querySelectorAll('[title], [data-stealth-title]');
- elements.forEach(el => {
- if (mode === 'stealth' || (userConfig && userConfig.appMode === 'stealth')) {
- if (el.hasAttribute('title')) {
- el.setAttribute('data-stealth-title', el.getAttribute('title'));
- el.removeAttribute('title');
- }
- } else {
- if (el.hasAttribute('data-stealth-title')) {
- el.setAttribute('title', el.getAttribute('data-stealth-title'));
- el.removeAttribute('data-stealth-title');
+ const isStealth = mode === 'stealth' || (userConfig && userConfig.appMode === 'stealth');
+
+ const performScrub = (root = document) => {
+ const elements = root.querySelectorAll ? root.querySelectorAll('[title], [data-tooltip]') : [];
+ elements.forEach(el => {
+ if (isStealth) {
+ if (el.hasAttribute('title')) {
+ el.setAttribute('data-tooltip', el.getAttribute('title'));
+ el.removeAttribute('title');
+ }
+ } else {
+ if (el.hasAttribute('data-tooltip')) {
+ el.setAttribute('title', el.getAttribute('data-tooltip'));
+ el.removeAttribute('data-tooltip');
+ }
}
- }
- });
+ });
+ };
+
+ // Initial scrub
+ performScrub();
+
+ // Fortress Mode: Aggressive MutationObserver for dynamic elements
+ if (tooltipObserver) tooltipObserver.disconnect();
+
+ if (isStealth) {
+ tooltipObserver = new MutationObserver((mutations) => {
+ mutations.forEach(mutation => {
+ mutation.addedNodes.forEach(node => {
+ if (node.nodeType === 1) { // Element node
+ performScrub(node);
+ // Also check the node itself
+ if (node.hasAttribute('title')) {
+ node.setAttribute('data-tooltip', node.getAttribute('title'));
+ node.removeAttribute('title');
+ }
+ }
+ });
+ if (mutation.type === 'attributes' && mutation.attributeName === 'title' && isStealth) {
+ const el = mutation.target;
+ if (el.hasAttribute('title')) {
+ el.setAttribute('data-tooltip', el.getAttribute('title'));
+ el.removeAttribute('title');
+ }
+ }
+ });
+ });
+
+ tooltipObserver.observe(document.body, {
+ childList: true,
+ subtree: true,
+ attributes: true,
+ attributeFilter: ['title']
+ });
+ }
} catch (err) {
console.error('[APP] Tooltip scrubbing error:', err);
}
@@ -682,12 +727,18 @@ function setupEventListeners() {
const resetAppBtn = $('reset-app-btn');
if (resetAppBtn) {
resetAppBtn.addEventListener('click', () => {
- const confirmed = confirm('CRITICAL WARNING: This will permanently delete ALL configurations, API keys, and models. You will be redirected to the onboarding screen. Proceed?');
-
- if (confirmed) {
- localStorage.clear();
- window.location.reload();
- }
+ // Removed native confirm() to prevent OS-level leak.
+ // Action is now immediate but restricted to the Settings -> Profile tab.
+ localStorage.clear();
+ window.location.reload();
+ });
+ }
+
+ const quitAppBtn = $('quit-app-btn');
+ if (quitAppBtn) {
+ quitAppBtn.addEventListener('click', () => {
+ // Removed native confirm() to prevent OS-level leak.
+ window.electronAPI.closeApp();
});
}
@@ -1015,6 +1066,18 @@ function setupEventListeners() {
}
});
}
+
+ // Fortress Mode: Security Listeners
+ window.addEventListener('contextmenu', (e) => {
+ // Only block if we aren't in a specific dev-mode context if desired,
+ // but for stealth we block it everywhere.
+ e.preventDefault();
+ });
+
+ window.addEventListener('dragstart', (e) => {
+ // Prevent ghost images during drag to stop OS "shadows" from appearing
+ e.preventDefault();
+ });
}
function appendChatMessage(msg, container) {
From 873d6826b8a63905c6f785c053460c9e2adbbabe Mon Sep 17 00:00:00 2001
From: Puskar-Roy
Date: Sun, 12 Apr 2026 10:10:57 +0530
Subject: [PATCH 4/4] feat: rebrand project to System Utility and implement
core Electron main process and UI infrastructure
---
package.json | 8 ++---
src/main/index.js | 8 +++++
src/main/shortcuts.js | 5 ---
src/main/window-manager.js | 9 +++--
src/renderer/css/base.css | 69 ++++++++++++++++++++++++++++++++++++++
src/renderer/index.html | 3 +-
src/renderer/js/app.js | 16 +++++++--
src/renderer/js/ui.js | 34 +++++++++++++++++++
8 files changed, 136 insertions(+), 16 deletions(-)
diff --git a/package.json b/package.json
index 8bf660c..752e16c 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
- "name": "imposter",
+ "name": "system-utility",
"version": "1.0.0",
- "description": "Imposter: Beating a Broken System",
+ "description": "System Utility: System performance evaluation tool",
"author": "Puskar Roy",
"repository": {
"type": "git",
@@ -37,8 +37,8 @@
"prettier": "^3.2.5"
},
"build": {
- "appId": "com.imposter.app",
- "productName": "Imposter",
+ "appId": "com.system-utility.app",
+ "productName": "System Utility",
"directories": {
"output": "dist"
},
diff --git a/src/main/index.js b/src/main/index.js
index 2151e71..3d28b00 100644
--- a/src/main/index.js
+++ b/src/main/index.js
@@ -2,6 +2,14 @@ const { app, session, BrowserWindow } = require('electron');
const path = require('path');
require('dotenv').config();
+if (app.isPackaged) {
+ console.log = () => {};
+ console.debug = () => {};
+ console.info = () => {};
+ console.warn = () => {};
+ console.error = () => {};
+}
+
const { createMainWindow, getMainWindow } = require('./window-manager');
const { registerShortcuts, unregisterShortcuts } = require('./shortcuts');
const { registerIpcHandlers } = require('./ipc-handlers');
diff --git a/src/main/shortcuts.js b/src/main/shortcuts.js
index 7d266db..10adedb 100644
--- a/src/main/shortcuts.js
+++ b/src/main/shortcuts.js
@@ -100,11 +100,6 @@ function registerShortcuts() {
console.error('[SHORTCUT] Snipping error:', err);
}
});
-
- safeRegister('CommandOrControl+Shift+D', () => {
- const win = getMainWindow();
- if (win && !win.isDestroyed()) win.webContents.toggleDevTools();
- });
}
function unregisterShortcuts() {
diff --git a/src/main/window-manager.js b/src/main/window-manager.js
index 85954a2..a717ff6 100644
--- a/src/main/window-manager.js
+++ b/src/main/window-manager.js
@@ -53,7 +53,8 @@ function createMainWindow(preloadPath) {
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
- preload: preloadPath
+ preload: preloadPath,
+ devTools: false
}
});
@@ -97,7 +98,8 @@ function createIslandWindow(preloadPath) {
webPreferences: {
nodeIntegration: false,
contextIsolation: true,
- preload: preloadPath
+ preload: preloadPath,
+ devTools: false
}
});
@@ -138,7 +140,8 @@ function createSnipperWindow(preloadPath, screenSource) {
enableLargerThanScreen: true,
webPreferences: {
preload: preloadPath,
- contextIsolation: true
+ contextIsolation: true,
+ devTools: false
}
});
diff --git a/src/renderer/css/base.css b/src/renderer/css/base.css
index 01504f7..a1c93d5 100644
--- a/src/renderer/css/base.css
+++ b/src/renderer/css/base.css
@@ -46,3 +46,72 @@ body {
::-webkit-scrollbar-thumb:hover {
background: #666;
}
+
+/* Custom HUD Notifications */
+.notification-container {
+ position: fixed;
+ top: 20px;
+ left: 50%;
+ transform: translateX(-50%);
+ z-index: 10000;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ gap: 10px;
+ pointer-events: none;
+}
+
+.notification {
+ background: rgba(30, 30, 30, 0.95);
+ color: var(--text-primary);
+ padding: 12px 20px;
+ border-radius: 12px;
+ font-size: 13px;
+ font-weight: 500;
+ box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
+ border: 1px solid var(--border-color);
+ backdrop-filter: blur(8px);
+ display: flex;
+ align-items: center;
+ gap: 12px;
+ animation: slideDownIn 0.3s cubic-bezier(0.16, 1, 0.3, 1) forwards;
+ pointer-events: auto;
+ max-width: 400px;
+ width: max-content;
+}
+
+.notification.error {
+ border-left: 4px solid #ff4d4d;
+}
+
+.notification.success {
+ border-left: 4px solid var(--accent-color);
+}
+
+.notification-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+@keyframes slideDownIn {
+ from {
+ opacity: 0;
+ transform: translateY(-20px);
+ }
+ to {
+ opacity: 1;
+ transform: translateY(0);
+ }
+}
+
+.notification.fade-out {
+ animation: fadeOut 0.3s forwards;
+}
+
+@keyframes fadeOut {
+ to {
+ opacity: 0;
+ transform: translateY(-10px);
+ }
+}
diff --git a/src/renderer/index.html b/src/renderer/index.html
index e1d1fe7..832eb66 100644
--- a/src/renderer/index.html
+++ b/src/renderer/index.html
@@ -5,7 +5,7 @@
- Imposter
+ System Utility
Global Keyboard Controls
+