apply transparent bg dynamically

This commit is contained in:
Siddharth
2025-10-12 14:45:22 -07:00
parent 632baa2552
commit de6d1aed98
8 changed files with 198 additions and 127 deletions
+49 -7
View File
@@ -10,13 +10,12 @@ const MAIN_DIST = path.join(process.env.APP_ROOT, "dist-electron");
const RENDERER_DIST = path.join(process.env.APP_ROOT, "dist");
process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path.join(process.env.APP_ROOT, "public") : RENDERER_DIST;
let win;
function createWindow() {
function createHudOverlayWindow() {
win = new BrowserWindow({
icon: path.join(process.env.VITE_PUBLIC, "electron-vite.svg"),
width: 250,
height: 80,
minWidth: 360,
maxWidth: 360,
minWidth: 250,
maxWidth: 250,
minHeight: 80,
maxHeight: 80,
frame: false,
@@ -26,7 +25,10 @@ function createWindow() {
skipTaskbar: true,
hasShadow: false,
webPreferences: {
preload: path.join(__dirname, "preload.mjs")
preload: path.join(__dirname, "preload.mjs"),
nodeIntegration: false,
contextIsolation: true,
backgroundThrottling: false
}
});
win.setResizable(false);
@@ -34,11 +36,44 @@ function createWindow() {
win == null ? void 0 : win.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString());
});
if (VITE_DEV_SERVER_URL) {
win.loadURL(VITE_DEV_SERVER_URL);
win.loadURL(VITE_DEV_SERVER_URL + "?windowType=hud-overlay");
} else {
win.loadFile(path.join(RENDERER_DIST, "index.html"));
win.loadFile(path.join(RENDERER_DIST, "index.html"), {
query: { windowType: "hud-overlay" }
});
}
}
function createEditorWindow() {
win = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
frame: true,
transparent: false,
resizable: true,
alwaysOnTop: false,
skipTaskbar: false,
webPreferences: {
preload: path.join(__dirname, "preload.mjs"),
nodeIntegration: false,
contextIsolation: true
}
});
win.webContents.on("did-finish-load", () => {
win == null ? void 0 : win.webContents.send("main-process-message", (/* @__PURE__ */ new Date()).toLocaleString());
});
if (VITE_DEV_SERVER_URL) {
win.loadURL(VITE_DEV_SERVER_URL + "?windowType=editor");
} else {
win.loadFile(path.join(RENDERER_DIST, "index.html"), {
query: { windowType: "editor" }
});
}
}
function createWindow() {
createHudOverlayWindow();
}
app.on("window-all-closed", () => {
if (process.platform !== "darwin") {
app.quit();
@@ -53,6 +88,13 @@ app.on("activate", () => {
ipcMain.handle("get-sources", async (_, opts) => {
return await desktopCapturer.getSources(opts);
});
ipcMain.handle("switch-to-editor", () => {
if (win) {
win.close();
win = null;
}
createEditorWindow();
});
app.whenReady().then(createWindow);
export {
MAIN_DIST,
+3
View File
@@ -3,5 +3,8 @@ const electron = require("electron");
electron.contextBridge.exposeInMainWorld("electronAPI", {
getSources: async (opts) => {
return await electron.ipcRenderer.invoke("get-sources", opts);
},
switchToEditor: () => {
return electron.ipcRenderer.invoke("switch-to-editor");
}
});
+53 -8
View File
@@ -26,13 +26,12 @@ process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL ? path.join(process.env.APP_ROOT,
let win: BrowserWindow | null
function createWindow() {
function createHudOverlayWindow() {
win = new BrowserWindow({
icon: path.join(process.env.VITE_PUBLIC, 'electron-vite.svg'),
width: 250,
height: 80,
minWidth: 360,
maxWidth: 360,
minWidth: 250,
maxWidth: 250,
minHeight: 80,
maxHeight: 80,
frame: false,
@@ -43,25 +42,63 @@ function createWindow() {
hasShadow: false,
webPreferences: {
preload: path.join(__dirname, 'preload.mjs'),
nodeIntegration: false,
contextIsolation: true,
backgroundThrottling: false,
},
})
// Absolutely lock the size
win.setResizable(false)
// Test active push message to Renderer-process.
win.webContents.on('did-finish-load', () => {
win?.webContents.send('main-process-message', (new Date).toLocaleString())
})
if (VITE_DEV_SERVER_URL) {
win.loadURL(VITE_DEV_SERVER_URL)
win.loadURL(VITE_DEV_SERVER_URL + '?windowType=hud-overlay')
} else {
// win.loadFile('dist/index.html')
win.loadFile(path.join(RENDERER_DIST, 'index.html'))
win.loadFile(path.join(RENDERER_DIST, 'index.html'), {
query: { windowType: 'hud-overlay' }
})
}
}
function createEditorWindow() {
win = new BrowserWindow({
width: 1200,
height: 800,
minWidth: 800,
minHeight: 600,
frame: true,
transparent: false,
resizable: true,
alwaysOnTop: false,
skipTaskbar: false,
webPreferences: {
preload: path.join(__dirname, 'preload.mjs'),
nodeIntegration: false,
contextIsolation: true,
},
})
win.webContents.on('did-finish-load', () => {
win?.webContents.send('main-process-message', (new Date).toLocaleString())
})
if (VITE_DEV_SERVER_URL) {
win.loadURL(VITE_DEV_SERVER_URL + '?windowType=editor')
} else {
win.loadFile(path.join(RENDERER_DIST, 'index.html'), {
query: { windowType: 'editor' }
})
}
}
function createWindow() {
createHudOverlayWindow()
}
// 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.
@@ -84,4 +121,12 @@ ipcMain.handle('get-sources', async (_, opts) => {
return await desktopCapturer.getSources(opts)
})
ipcMain.handle('switch-to-editor', () => {
if (win) {
win.close()
win = null
}
createEditorWindow()
})
app.whenReady().then(createWindow)
+3
View File
@@ -3,5 +3,8 @@ import { contextBridge, ipcRenderer } from 'electron'
contextBridge.exposeInMainWorld('electronAPI', {
getSources: async (opts: Electron.SourcesOptions) => {
return await ipcRenderer.invoke('get-sources', opts)
},
switchToEditor: () => {
return ipcRenderer.invoke('switch-to-editor')
}
})
+32 -41
View File
@@ -1,48 +1,39 @@
import { useScreenRecorder } from "./hooks/useScreenRecorder";
import { Button } from "@/components/ui/button";
import { BsRecordCircle } from "react-icons/bs";
import { FaRegStopCircle } from "react-icons/fa";
import { MdMonitor } from "react-icons/md";
import { LaunchWindow } from "./components/LaunchWindow";
import { useEffect, useState } from "react";
export default function App() {
const { recording, toggleRecording } = useScreenRecorder();
const [windowType, setWindowType] = useState<string>('');
useEffect(() => {
const urlParams = new URLSearchParams(window.location.search);
const type = urlParams.get('windowType') || 'default';
setWindowType(type);
// Apply transparency only for HUD overlay windows
if (type === 'hud-overlay') {
document.body.style.background = 'transparent';
document.documentElement.style.background = 'transparent';
const root = document.getElementById('root');
if (root) root.style.background = 'transparent';
}
}, []);
if (windowType === 'hud-overlay') {
return <LaunchWindow />;
}
if (windowType === 'editor') {
return (
<div className="w-full h-full bg-background text-foreground p-6">
<h1 className="text-2xl font-bold mb-4">Video Editor</h1>
<p>Recording stopped. Video editor interface coming soon...</p>
</div>
);
}
return (
<div className="w-full h-full flex items-center justify-center bg-transparent">
<div className="flex items-center gap-3 backdrop-blur-lg bg-white/10 rounded-full px-4 py-2 shadow-2xl border border-white/30">
<Button
variant="link"
size="sm"
className="gap-2 text-white bg-transparent hover:bg-transparent px-3"
onClick={() => {
console.log("Source button clicked");
}}
>
<MdMonitor size={16} className="text-white" />
Source
</Button>
<div className="w-px h-5 bg-white/30" />
<Button
variant="link"
size="sm"
onClick={toggleRecording}
className="gap-2 text-white bg-transparent hover:bg-transparent px-3"
>
{recording ? (
<>
<FaRegStopCircle size={16} className="text-white" />
Stop
</>
) : (
<>
<BsRecordCircle size={16} className="text-white" />
Record
</>
)}
</Button>
</div>
<div className="w-full h-full bg-background text-foreground">
<h1>Default Window</h1>
</div>
);
}
+52
View File
@@ -0,0 +1,52 @@
import { useScreenRecorder } from "../hooks/useScreenRecorder";
import { Button } from "@/components/ui/button";
import { BsRecordCircle } from "react-icons/bs";
import { FaRegStopCircle } from "react-icons/fa";
import { MdMonitor } from "react-icons/md";
export function LaunchWindow() {
const { recording, toggleRecording } = useScreenRecorder();
return (
<div className="w-full h-full flex items-center justify-center bg-transparent">
<div className="flex items-center gap-3 backdrop-blur-lg bg-white/10 rounded-full px-4 py-2 shadow-2xl border border-white/30">
<Button
variant="link"
size="sm"
className="gap-2 text-white bg-transparent hover:bg-transparent px-3"
onClick={() => {
console.log("Source button clicked - switching to editor");
// Simulate stopping recording and switching to editor
if (window.electronAPI) {
window.electronAPI.switchToEditor();
}
}}
>
<MdMonitor size={16} className="text-white" />
Source
</Button>
<div className="w-px h-5 bg-white/30" />
<Button
variant="link"
size="sm"
onClick={toggleRecording}
className="gap-2 text-white bg-transparent hover:bg-transparent px-3"
>
{recording ? (
<>
<FaRegStopCircle size={16} className="text-white" />
Stop
</>
) : (
<>
<BsRecordCircle size={16} className="text-white" />
Record
</>
)}
</Button>
</div>
</div>
);
}
-71
View File
@@ -1,78 +1,7 @@
body {
background: transparent !important;
}
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
@layer base {
:root {
--background: 0 0% 100%;
+6
View File
@@ -1 +1,7 @@
/// <reference types="vite/client" />
interface Window {
electronAPI: {
getSources: (opts: Electron.SourcesOptions) => Promise<Electron.DesktopCapturerSource[]>
switchToEditor: () => Promise<void>
}
}