apply transparent bg dynamically
This commit is contained in:
+49
-7
@@ -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,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
@@ -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,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
@@ -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>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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%;
|
||||
|
||||
Vendored
+6
@@ -1 +1,7 @@
|
||||
/// <reference types="vite/client" />
|
||||
interface Window {
|
||||
electronAPI: {
|
||||
getSources: (opts: Electron.SourcesOptions) => Promise<Electron.DesktopCapturerSource[]>
|
||||
switchToEditor: () => Promise<void>
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user