diff --git a/electron/electron-env.d.ts b/electron/electron-env.d.ts index a4972be61..72e73d792 100644 --- a/electron/electron-env.d.ts +++ b/electron/electron-env.d.ts @@ -41,6 +41,10 @@ interface Window { error?: string; }; }>; + openNotes: () => Promise<{ + opened: boolean; + reason?: string; + }>; selectSource: (source: ProcessedDesktopSource) => Promise; getSelectedSource: () => Promise; onSelectedSourceChanged: (callback: (source: ProcessedDesktopSource) => void) => () => void; diff --git a/electron/ipc/handlers.ts b/electron/ipc/handlers.ts index 85d154881..d8a1ee55a 100644 --- a/electron/ipc/handlers.ts +++ b/electron/ipc/handlers.ts @@ -1280,8 +1280,10 @@ export function registerIpcHandlers( createEditorWindow: () => void, createSourceSelectorWindow: () => BrowserWindow, createCountdownOverlayWindow: () => BrowserWindow, + createNotesWindowWrapper: () => BrowserWindow, getMainWindow: () => BrowserWindow | null, getSourceSelectorWindow: () => BrowserWindow | null, + getNotesWindow: () => BrowserWindow | null, getCountdownOverlayWindow?: () => BrowserWindow | null, onRecordingStateChange?: (recording: boolean, sourceName: string) => void, _switchToHud?: () => void, @@ -1479,6 +1481,17 @@ export function registerIpcHandlers( return { opened: true }; }); + ipcMain.handle("open-notes", async () => { + const notesSelectorWin = getNotesWindow(); + if (notesSelectorWin) { + notesSelectorWin.focus(); + return { opened: true }; + } + + createNotesWindowWrapper(); + return { opened: true }; + }); + ipcMain.handle("switch-to-editor", () => { // createEditorWindow already closes the current mainWindow (the HUD) before // opening the editor. Closing it here too double-closes, leaving ghost diff --git a/electron/main.ts b/electron/main.ts index a8e743fc9..fde69aa6f 100644 --- a/electron/main.ts +++ b/electron/main.ts @@ -25,6 +25,7 @@ import { createCountdownOverlayWindow, createEditorWindow, createHudOverlayWindow, + createNotesWindow, createSourceSelectorWindow, } from "./windows"; @@ -84,6 +85,7 @@ process.env.VITE_PUBLIC = VITE_DEV_SERVER_URL let mainWindow: BrowserWindow | null = null; let sourceSelectorWindow: BrowserWindow | null = null; let countdownOverlayWindow: BrowserWindow | null = null; +let notesWindow: BrowserWindow | null = null; let tray: Tray | null = null; let selectedSourceName = ""; const isMac = process.platform === "darwin"; @@ -437,6 +439,19 @@ function createSourceSelectorWindowWrapper() { return sourceSelectorWindow; } +function createNotesWindowWrapper() { + { + notesWindow = createNotesWindow(); + notesWindow.on("closed", () => { + notesWindow = null; + if (mainWindow && !mainWindow.isDestroyed()) { + mainWindow.webContents.send("notes-window-closed"); + } + }); + return notesWindow; + } +} + function createCountdownOverlayWindowWrapper() { if (countdownOverlayWindow && !countdownOverlayWindow.isDestroyed()) { return countdownOverlayWindow; @@ -575,8 +590,10 @@ appReady?.then(async () => { createEditorWindowWrapper, createSourceSelectorWindowWrapper, createCountdownOverlayWindowWrapper, + createNotesWindowWrapper, () => mainWindow, () => sourceSelectorWindow, + () => notesWindow, () => countdownOverlayWindow, (recording: boolean, sourceName: string) => { selectedSourceName = sourceName; diff --git a/electron/preload.ts b/electron/preload.ts index fefcac044..e0d246bda 100644 --- a/electron/preload.ts +++ b/electron/preload.ts @@ -47,6 +47,9 @@ contextBridge.exposeInMainWorld("electronAPI", { openSourceSelector: () => { return ipcRenderer.invoke("open-source-selector"); }, + openNotes: () => { + return ipcRenderer.invoke("open-notes"); + }, selectSource: (source: ProcessedDesktopSource) => { return ipcRenderer.invoke("select-source", source); }, diff --git a/electron/windows.ts b/electron/windows.ts index c3830157f..2f87e6c3d 100644 --- a/electron/windows.ts +++ b/electron/windows.ts @@ -320,3 +320,44 @@ export function createCountdownOverlayWindow(): BrowserWindow { return win; } + +// Frameless Notes Window for taking notes during a recording. +export function createNotesWindow(): BrowserWindow { + const win = new BrowserWindow({ + width: 400, + height: 540, + minWidth: 360, + minHeight: 400, + maxWidth: 640, + maxHeight: 720, + title: "OpenScreen - Notes", + backgroundColor: "#09090b", + resizable: true, + alwaysOnTop: true, + skipTaskbar: false, + show: false, + webPreferences: { + preload: path.join(__dirname, "preload.mjs"), + additionalArguments: [ASSET_BASE_URL_ARG], + nodeIntegration: false, + contextIsolation: true, + backgroundThrottling: false, + }, + }); + + win.setContentProtection(true); + win.once("ready-to-show", () => { + win.setContentProtection(true); + win.show(); + }); + + if (VITE_DEV_SERVER_URL) { + win.loadURL(VITE_DEV_SERVER_URL + "?showNotes=true"); + } else { + win.loadFile(path.join(RENDERER_DIST, "index.html"), { + query: { showNotes: "true" }, + }); + } + + return win; +} diff --git a/package-lock.json b/package-lock.json index 0e8e1661d..e189674bd 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "openscreen", - "version": "1.5.0", + "version": "1.6.0-rc.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "openscreen", - "version": "1.5.0", + "version": "1.6.0-rc.1", "dependencies": { "@fix-webm-duration/fix": "^1.0.1", "@pixi/filter-drop-shadow": "^5.2.0", @@ -22,6 +22,9 @@ "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", + "@tiptap/extension-text-style": "^3.27.1", + "@tiptap/react": "^3.27.1", + "@tiptap/starter-kit": "^3.27.1", "@types/gif.js": "^0.2.5", "@uiw/color-convert": "^2.10.1", "@uiw/react-color-block": "^2.10.1", @@ -3944,6 +3947,448 @@ "@testing-library/dom": ">=7.21.4" } }, + "node_modules/@tiptap/core": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/core/-/core-3.27.1.tgz", + "integrity": "sha512-rV6Qn4wmC6BxfF+4mu6bqGWj9vA4oXXhsrpXaJL2uhjxeHAGofjwcHof2X84VYzeyXgdlsGmqKie4TAppVXZUQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/extension-blockquote": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-blockquote/-/extension-blockquote-3.27.1.tgz", + "integrity": "sha512-VMF7xJx6qEGiX6DTKNiL31NLqypOcd/4sNjFSe8rb41PwejBJh/nOqVIbBvWkiT6NMGFLxMhj7zJ8/zPo1hXeg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-bold": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bold/-/extension-bold-3.27.1.tgz", + "integrity": "sha512-TlC5bsS+pqETTrlz4CZz9RO/cKBYtELGIxwtKeivUn3eNfnOxQbbu4WDsiwIfzRFyd0OMnKl6BPM2KnYEehoEQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-bubble-menu": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bubble-menu/-/extension-bubble-menu-3.27.1.tgz", + "integrity": "sha512-j/j8Qp9Z5nViade2m7zjrO/CYH/Ca80Qj7aqo0eUaei6FZQ5izlF9o4XQU5EFMAutV6mwynsPUp8FVo5sCuYfw==", + "license": "MIT", + "optional": true, + "dependencies": { + "@floating-ui/dom": "^1.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/extension-bullet-list": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-bullet-list/-/extension-bullet-list-3.27.1.tgz", + "integrity": "sha512-faCUHnRP47o9Zh9VZZX6EX/569udw9Vopm2PgEKPWuKLE2qaS5WBuUVU0iItdJmKUqaWiOZkpoW4jvnDmj0dfg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "3.27.1" + } + }, + "node_modules/@tiptap/extension-code": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code/-/extension-code-3.27.1.tgz", + "integrity": "sha512-epOUpFfEmBzjvnqvjv2qHX7NAuLo5dlOGV690lWu+sAYMjibuJBeVvAiKPyFCfRCCTUxdbDB3jbaOA1yEcEJ7w==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-code-block": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-code-block/-/extension-code-block-3.27.1.tgz", + "integrity": "sha512-pHlzmZx2OlHfyQ0yRlT5UL4mGokz947DthZuYefN1OleVqOkHpWBG+2JQwqoNq6bmzMne92zbH32rhcJUEYSjA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/extension-document": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-document/-/extension-document-3.27.1.tgz", + "integrity": "sha512-8FbBTkfnRP4iVaoj+2h3iWa+H0eGDD3yTyVCwrmue/sQTkqUNUoSuAZa3GDG4Sd41xdPwTJxl9nUWGgM1qDCnw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-dropcursor": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-dropcursor/-/extension-dropcursor-3.27.1.tgz", + "integrity": "sha512-blFf9x9RG0Qr7P3FoAH/033ffa+mMLZn34trVs8Vi0Ppk6FmJAg5HpYFOtmYoeREdNDJ5rHJKV7SoACbOHgskQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "3.27.1" + } + }, + "node_modules/@tiptap/extension-floating-menu": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-floating-menu/-/extension-floating-menu-3.27.1.tgz", + "integrity": "sha512-BmJF1VqB7dSJkgAalrpVFj88WLhxKjcWPuWHOqf2ITrUU2832BhKLXKmxjWUy1gqV8PfNNVWtGfIERy7I0y0+Q==", + "license": "MIT", + "optional": true, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@floating-ui/dom": "^1.0.0", + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/extension-gapcursor": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-gapcursor/-/extension-gapcursor-3.27.1.tgz", + "integrity": "sha512-QoezN0wdvXIwLQ4ee2ccWDaX3RG0lzgQpIMpMz55oPDhpUVax1+19ApsS53LkcktpS4EbnPL4xO4DaJk0Vp7PQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extensions": "3.27.1" + } + }, + "node_modules/@tiptap/extension-hard-break": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-hard-break/-/extension-hard-break-3.27.1.tgz", + "integrity": "sha512-iv/m9hzl6jfSj9Q8UEjAxONvCoUDaP7M9SRCPx3PaLNxA230TTD6RE0Ye4zFJ8ze7ZVoJJMAqg9Qpq1iYg2JOQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-heading": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-heading/-/extension-heading-3.27.1.tgz", + "integrity": "sha512-SrC4l1kEIyv9ZXFaI/8LQqU2MyMmjczw7XXsWUQOTN4YXv0JyVgMNR3cI/wz0d2xsTfBdZ1N85Tdng+Ga1t0Sg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-horizontal-rule": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-horizontal-rule/-/extension-horizontal-rule-3.27.1.tgz", + "integrity": "sha512-QlKE7qn5qMnIGVGhXQlvYedvLtNJ9z0dmit5w8vPb8tKzW4Spk6M7N2kruprrDA8GBwHfeR5wmF+njfUm34qxg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/extension-italic": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-italic/-/extension-italic-3.27.1.tgz", + "integrity": "sha512-jGGeyn9uRUnNjSTHpbqhiGsp6KaYTSbV09jDXPJI9cDwfV9hpugLvpaCZd0BMBbhU1B1W6kOfX0BE15qX/HQfA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-link": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-link/-/extension-link-3.27.1.tgz", + "integrity": "sha512-/2jBfsxBZUDGJmpZifqRQPz7f1E5qpS1BckTZ39TADzUJX+feKy7RJ3DtQ02+8y6SSMzvP9loGVjrk6zEMTk4g==", + "license": "MIT", + "dependencies": { + "linkifyjs": "^4.3.3" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/extension-list": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list/-/extension-list-3.27.1.tgz", + "integrity": "sha512-c2Upru7lj0/ZV/Ibww6cNz6sUS8m6Dp/9uygFhYcZOd3X8M0xBIEk42c6m6SQehkPziVA8QOgNJz7sMqsbz1OQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/extension-list-item": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-item/-/extension-list-item-3.27.1.tgz", + "integrity": "sha512-zwRl01ETfCkWUvtvK5fw9bXtAajMPkvlkE3Cq6JvH3LF7XXJwDtNj5Tj7exacMpCaSZmlNc43vFb2rAYnrnwMA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "3.27.1" + } + }, + "node_modules/@tiptap/extension-list-keymap": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-list-keymap/-/extension-list-keymap-3.27.1.tgz", + "integrity": "sha512-OIMZNlzPSO8WRd4ic73Fxckzl4N1tesjjLL2XApaNA/uMpO0LoF6WSRPAWv+Z24Wp92ARRJAnRP7iZoI5+Jxig==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "3.27.1" + } + }, + "node_modules/@tiptap/extension-ordered-list": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-ordered-list/-/extension-ordered-list-3.27.1.tgz", + "integrity": "sha512-GYrKqD//9nHJ2r80uXqbDMzRnFpGzbaEQRTSGaO/SH7DvXWFMow8evkOdjQ7PCQO07jNjJo75+A85Jwu3Ov3AA==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/extension-list": "3.27.1" + } + }, + "node_modules/@tiptap/extension-paragraph": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-paragraph/-/extension-paragraph-3.27.1.tgz", + "integrity": "sha512-7K7eo1gruOgAsnbK+GCV23AUVUI0cL1bTig8HaPneoFMVbig7vddk8jNLKBWO8TXVbG7TuHdnDN4F98vdtwh5Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-strike": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-strike/-/extension-strike-3.27.1.tgz", + "integrity": "sha512-Y3DW1jlSlCNCyMGHP3+3qBNNPS83wuFz4RTYGjZtvRRTCRh7apZme9XRWMq1rN5mJ2Cr7fKocA2/5Bs13KgN6Q==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-text": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text/-/extension-text-3.27.1.tgz", + "integrity": "sha512-6ZwaZwSrDh+KFFv6V1J79oO37yPs7y1bFxvk1/9Ih2rn3Xr5AWz+eMS+n8RpH3djBVVAQpdIAeYQgcn+VCSsTg==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-text-style": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-text-style/-/extension-text-style-3.27.1.tgz", + "integrity": "sha512-J48WIl+6YDYTFPhWXUBQk+u7+AKVUqTdvrZOQyPYCGuQMgHrYzgWrI5+HeEifUgXJ5rMIWWP3qytp7KhVVqpDQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extension-underline": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extension-underline/-/extension-underline-3.27.1.tgz", + "integrity": "sha512-N889J4nXN/TPfVt8uF9N1A0SY82E90zwc1y26lqOcw6KWNLmQrlhMh/9OD4ikLDbekmFpOBq/UicpHf/6S8hbQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1" + } + }, + "node_modules/@tiptap/extensions": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/extensions/-/extensions-3.27.1.tgz", + "integrity": "sha512-1Tdx9faw8k0/83V6X+xCDVhV8yElGt95JxeW3YMkKQJI56QdlPz0xOdJPlMiSGJKinPyVier+x9LJD/YZUZIaw==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1" + } + }, + "node_modules/@tiptap/pm": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/pm/-/pm-3.27.1.tgz", + "integrity": "sha512-Ffjx+vimmBU7zH/KrpXzJid3+pziCe/VL2aexSTP63cyQwKQ65LkFkCKaIsSpFdQQuakVZBGWjCA5RoBV852pw==", + "license": "MIT", + "dependencies": { + "prosemirror-changeset": "^2.3.0", + "prosemirror-commands": "^1.6.2", + "prosemirror-dropcursor": "^1.8.1", + "prosemirror-gapcursor": "^1.3.2", + "prosemirror-history": "^1.4.1", + "prosemirror-inputrules": "^1.4.0", + "prosemirror-keymap": "^1.2.3", + "prosemirror-model": "^1.25.7", + "prosemirror-schema-list": "^1.5.0", + "prosemirror-state": "^1.4.4", + "prosemirror-tables": "^1.8.0", + "prosemirror-transform": "^1.12.0", + "prosemirror-view": "^1.41.8" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, + "node_modules/@tiptap/react": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/react/-/react-3.27.1.tgz", + "integrity": "sha512-/Wn2fc9zMtX08MXYScDFsm4wJ8lzfhfPEdbtls7WCDlbtrop48PWlkHDBBJrywARfAQTB2mFs9KiFy9yrQm5Lg==", + "license": "MIT", + "dependencies": { + "@types/use-sync-external-store": "^0.0.6", + "fast-equals": "^5.3.3", + "use-sync-external-store": "^1.4.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + }, + "optionalDependencies": { + "@tiptap/extension-bubble-menu": "^3.27.1", + "@tiptap/extension-floating-menu": "^3.27.1" + }, + "peerDependencies": { + "@tiptap/core": "3.27.1", + "@tiptap/pm": "3.27.1", + "@types/react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "@types/react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, + "node_modules/@tiptap/starter-kit": { + "version": "3.27.1", + "resolved": "https://registry.npmjs.org/@tiptap/starter-kit/-/starter-kit-3.27.1.tgz", + "integrity": "sha512-vfxRsqW8rCc0k4pzo0ilU3wobVi2wqVj88VZI2SlgZlNnUAkrDGDIAph7CTa9k9fshV+O1ivpEgPC5yC046jow==", + "license": "MIT", + "dependencies": { + "@tiptap/core": "^3.27.1", + "@tiptap/extension-blockquote": "^3.27.1", + "@tiptap/extension-bold": "^3.27.1", + "@tiptap/extension-bullet-list": "^3.27.1", + "@tiptap/extension-code": "^3.27.1", + "@tiptap/extension-code-block": "^3.27.1", + "@tiptap/extension-document": "^3.27.1", + "@tiptap/extension-dropcursor": "^3.27.1", + "@tiptap/extension-gapcursor": "^3.27.1", + "@tiptap/extension-hard-break": "^3.27.1", + "@tiptap/extension-heading": "^3.27.1", + "@tiptap/extension-horizontal-rule": "^3.27.1", + "@tiptap/extension-italic": "^3.27.1", + "@tiptap/extension-link": "^3.27.1", + "@tiptap/extension-list": "^3.27.1", + "@tiptap/extension-list-item": "^3.27.1", + "@tiptap/extension-list-keymap": "^3.27.1", + "@tiptap/extension-ordered-list": "^3.27.1", + "@tiptap/extension-paragraph": "^3.27.1", + "@tiptap/extension-strike": "^3.27.1", + "@tiptap/extension-text": "^3.27.1", + "@tiptap/extension-underline": "^3.27.1", + "@tiptap/extensions": "^3.27.1", + "@tiptap/pm": "^3.27.1" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/ueberdosis" + } + }, "node_modules/@types/aria-query": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz", @@ -4160,14 +4605,12 @@ "version": "15.7.15", "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.15.tgz", "integrity": "sha512-F6bEyamV9jKGAFBEmlQnesRPGOQqS2+Uwi0Em15xenOxHaf2hv6L8YCVn3rPdPJOiJfPiCnLIRyvwVaqMY3MIw==", - "devOptional": true, "license": "MIT" }, "node_modules/@types/react": { "version": "18.3.28", "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.28.tgz", "integrity": "sha512-z9VXpC7MWrhfWipitjNdgCauoMLRdIILQsAEV+ZesIzBq/oUlxk0m3ApZuMFCXdnS4U7KrI+l3WRUEGQ8K1QKw==", - "devOptional": true, "license": "MIT", "dependencies": { "@types/prop-types": "*", @@ -4178,7 +4621,6 @@ "version": "18.3.7", "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.7.tgz", "integrity": "sha512-MEe3UeoENYVFXzoXEWsvcpg6ZvlrFNlOQ7EOsvhI3CfAXwzPfO8Qwuxd40nepsYKqyyVQnTdEfv68q91yLcKrQ==", - "devOptional": true, "license": "MIT", "peerDependencies": { "@types/react": "^18.0.0" @@ -4194,6 +4636,12 @@ "@types/node": "*" } }, + "node_modules/@types/use-sync-external-store": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.6.tgz", + "integrity": "sha512-zFDAD+tlpf2r4asuHEj0XH6pY6i0g5NeAHPn+15wk3BV6JA69eERFXC1gyGThDkVa1zCyKr5jox1+2LbV/AMLg==", + "license": "MIT" + }, "node_modules/@types/verror": { "version": "1.10.11", "resolved": "https://registry.npmjs.org/@types/verror/-/verror-1.10.11.tgz", @@ -5943,7 +6391,6 @@ "version": "3.2.3", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz", "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==", - "devOptional": true, "license": "MIT" }, "node_modules/data-urls": { @@ -6861,6 +7308,15 @@ "dev": true, "license": "MIT" }, + "node_modules/fast-equals": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.4.0.tgz", + "integrity": "sha512-jt2DW/aNFNwke7AUd+Z+e6pz39KO5rzdbbFCg2sGafS4mk13MI7Z8O5z9cADNn5lhGODIgLwug6TZO2ctf7kcw==", + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, "node_modules/fast-fifo": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/fast-fifo/-/fast-fifo-1.3.2.tgz", @@ -7979,6 +8435,12 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "license": "MIT" }, + "node_modules/linkifyjs": { + "version": "4.3.3", + "resolved": "https://registry.npmjs.org/linkifyjs/-/linkifyjs-4.3.3.tgz", + "integrity": "sha512-P8aEP5U/D1/IlTY2OeYsErdwh9bGuLE30NcXtKEjgdHcahveQoQwM2yZNsioQHsWFz0P7KKudisbrzCgR0sDHg==", + "license": "MIT" + }, "node_modules/lint-staged": { "version": "16.4.0", "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.4.0.tgz", @@ -8877,6 +9339,12 @@ "platform": "^1.3.6" } }, + "node_modules/orderedmap": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/orderedmap/-/orderedmap-2.1.1.tgz", + "integrity": "sha512-TvAWxi0nDe1j/rtMcWcIj94+Ffe6n7zhow33h40SKxmsmozs6dz/e+EajymfoFcHd7sxNn8yHM8839uixMOV6g==", + "license": "MIT" + }, "node_modules/p-cancelable": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-2.1.1.tgz", @@ -9496,6 +9964,145 @@ "signal-exit": "^3.0.2" } }, + "node_modules/prosemirror-changeset": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-changeset/-/prosemirror-changeset-2.4.1.tgz", + "integrity": "sha512-96WBLhOaYhJ+kPhLg3uW359Tz6I/MfcrQfL4EGv4SrcqKEMC1gmoGrXHecPE8eOwTVCJ4IwgfzM8fFad25wNfw==", + "license": "MIT", + "dependencies": { + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-commands": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/prosemirror-commands/-/prosemirror-commands-1.7.1.tgz", + "integrity": "sha512-rT7qZnQtx5c0/y/KlYaGvtG411S97UaL6gdp6RIZ23DLHanMYLyfGBV5DtSnZdthQql7W+lEVbpSfwtO8T+L2w==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.10.2" + } + }, + "node_modules/prosemirror-dropcursor": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/prosemirror-dropcursor/-/prosemirror-dropcursor-1.8.2.tgz", + "integrity": "sha512-CCk6Gyx9+Tt2sbYk5NK0nB1ukHi2ryaRgadV/LvyNuO3ena1payM2z6Cg0vO1ebK8cxbzo41ku2DE5Axj1Zuiw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0", + "prosemirror-view": "^1.1.0" + } + }, + "node_modules/prosemirror-gapcursor": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/prosemirror-gapcursor/-/prosemirror-gapcursor-1.4.1.tgz", + "integrity": "sha512-pMdYaEnjNMSwl11yjEGtgTmLkR08m/Vl+Jj443167p9eB3HVQKhYCc4gmHVDsLPODfZfjr/MmirsdyZziXbQKw==", + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.0.0", + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-view": "^1.0.0" + } + }, + "node_modules/prosemirror-history": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/prosemirror-history/-/prosemirror-history-1.5.0.tgz", + "integrity": "sha512-zlzTiH01eKA55UAf1MEjtssJeHnGxO0j4K4Dpx+gnmX9n+SHNlDqI2oO1Kv1iPN5B1dm5fsljCfqKF9nFL6HRg==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.2.2", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.31.0", + "rope-sequence": "^1.3.0" + } + }, + "node_modules/prosemirror-inputrules": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-inputrules/-/prosemirror-inputrules-1.5.1.tgz", + "integrity": "sha512-7wj4uMjKaXWAQ1CDgxNzNtR9AlsuwzHfdFH1ygEHA2KHF2DOEaXl1CJfNPAKCg9qNEh4rum975QLaCiQPyY6Fw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.0.0" + } + }, + "node_modules/prosemirror-keymap": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/prosemirror-keymap/-/prosemirror-keymap-1.2.3.tgz", + "integrity": "sha512-4HucRlpiLd1IPQQXNqeo81BGtkY8Ai5smHhKW9jjPKRc2wQIxksg7Hl1tTI2IfT2B/LgX6bfYvXxEpJl7aKYKw==", + "license": "MIT", + "dependencies": { + "prosemirror-state": "^1.0.0", + "w3c-keyname": "^2.2.0" + } + }, + "node_modules/prosemirror-model": { + "version": "1.25.9", + "resolved": "https://registry.npmjs.org/prosemirror-model/-/prosemirror-model-1.25.9.tgz", + "integrity": "sha512-pRTklkDDMMRopyoAcrr9wV/8g/RYgrLHBuJAb5hlEuYZRdm5yqmPjWId83fpBwPpSFqEdja0H7Dfd7z1X/npcA==", + "license": "MIT", + "dependencies": { + "orderedmap": "^2.0.0" + } + }, + "node_modules/prosemirror-schema-list": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/prosemirror-schema-list/-/prosemirror-schema-list-1.5.1.tgz", + "integrity": "sha512-927lFx/uwyQaGwJxLWCZRkjXG0p48KpMj6ueoYiu4JX05GGuGcgzAy62dfiV8eFZftgyBUvLx76RsMe20fJl+Q==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.7.3" + } + }, + "node_modules/prosemirror-state": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/prosemirror-state/-/prosemirror-state-1.4.4.tgz", + "integrity": "sha512-6jiYHH2CIGbCfnxdHbXZ12gySFY/fz/ulZE333G6bPqIZ4F+TXo9ifiR86nAHpWnfoNjOb3o5ESi7J8Uz1jXHw==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.0.0", + "prosemirror-transform": "^1.0.0", + "prosemirror-view": "^1.27.0" + } + }, + "node_modules/prosemirror-tables": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/prosemirror-tables/-/prosemirror-tables-1.8.5.tgz", + "integrity": "sha512-V/0cDCsHKHe/tfWkeCmthNUcEp1IVO3p6vwN8XtwE9PZQLAZJigbw3QoraAdfJPir4NKJtNvOB8oYGKRl+t0Dw==", + "license": "MIT", + "dependencies": { + "prosemirror-keymap": "^1.2.3", + "prosemirror-model": "^1.25.4", + "prosemirror-state": "^1.4.4", + "prosemirror-transform": "^1.10.5", + "prosemirror-view": "^1.41.4" + } + }, + "node_modules/prosemirror-transform": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/prosemirror-transform/-/prosemirror-transform-1.12.0.tgz", + "integrity": "sha512-GxboyN4AMIsoHNtz5uf2r2Ru551i5hWeCMD6E2Ib4Eogqoub0NflniaBPVQ4MrGE5yZ8JV9tUHg9qcZTTrcN4w==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.21.0" + } + }, + "node_modules/prosemirror-view": { + "version": "1.42.0", + "resolved": "https://registry.npmjs.org/prosemirror-view/-/prosemirror-view-1.42.0.tgz", + "integrity": "sha512-N54DF3OXNWDuP81G1kbfCys8ZzIjuL1VnvJ2mk5STSu/fNxWIcX/EutQLA3s9KR/2wVhgDi4hzBB/1fINVxk0A==", + "license": "MIT", + "dependencies": { + "prosemirror-model": "^1.25.8", + "prosemirror-state": "^1.0.0", + "prosemirror-transform": "^1.1.0" + } + }, "node_modules/protobufjs": { "version": "6.11.6", "resolved": "https://registry.npmjs.org/protobufjs/-/protobufjs-6.11.6.tgz", @@ -10094,6 +10701,12 @@ "fsevents": "~2.3.2" } }, + "node_modules/rope-sequence": { + "version": "1.3.4", + "resolved": "https://registry.npmjs.org/rope-sequence/-/rope-sequence-1.3.4.tgz", + "integrity": "sha512-UT5EDe2cu2E/6O4igUr5PSFs23nvvukicWHx6GnOPlHAiiYbzNuCRQCuiUdHJQcqKalLKlrYJnjY0ySGsXNQXQ==", + "license": "MIT" + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -11400,6 +12013,15 @@ } } }, + "node_modules/use-sync-external-store": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.6.0.tgz", + "integrity": "sha512-Pp6GSwGP/NrPIrxVFAIkOQeyw8lFenOHijQWkUTrDvrF4ALqylP2C/KCkeS9dpUM3KvYRQhna5vt7IL95+ZQ9w==", + "license": "MIT", + "peerDependencies": { + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/utf8-byte-length": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/utf8-byte-length/-/utf8-byte-length-1.0.5.tgz", @@ -11644,6 +12266,12 @@ } } }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==", + "license": "MIT" + }, "node_modules/w3c-xmlserializer": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/w3c-xmlserializer/-/w3c-xmlserializer-5.0.0.tgz", diff --git a/package.json b/package.json index 04ca1b839..a0c036f8c 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,9 @@ "@radix-ui/react-toggle": "^1.1.10", "@radix-ui/react-toggle-group": "^1.1.11", "@radix-ui/react-tooltip": "^1.2.8", + "@tiptap/extension-text-style": "^3.27.1", + "@tiptap/react": "^3.27.1", + "@tiptap/starter-kit": "^3.27.1", "@types/gif.js": "^0.2.5", "@uiw/color-convert": "^2.10.1", "@uiw/react-color-block": "^2.10.1", diff --git a/src/App.tsx b/src/App.tsx index 0c8875d04..35749408c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -1,6 +1,7 @@ import { lazy, Suspense, useEffect, useState } from "react"; import { CountdownOverlay } from "./components/launch/CountdownOverlay.tsx"; import { LaunchWindow } from "./components/launch/LaunchWindow"; +import { NotesWindow } from "./components/launch/NotesWindow.tsx"; import { SourceSelector } from "./components/launch/SourceSelector"; import { Toaster } from "./components/ui/sonner"; import { TooltipProvider } from "./components/ui/tooltip"; @@ -19,6 +20,8 @@ export default function App() { const [windowType, setWindowType] = useState( () => new URLSearchParams(window.location.search).get("windowType") || "", ); + const showNotes = new URLSearchParams(window.location.search).get("showNotes") === "true"; + const tEditor = useScopedT("editor"); useEffect(() => { @@ -102,8 +105,10 @@ export default function App() { ); default: return ( -
-

Openscreen

+
+
+

Openscreen

+
); } @@ -111,7 +116,7 @@ export default function App() { return ( - {content} + {showNotes ? : content} ); diff --git a/src/components/launch/LaunchWindow.tsx b/src/components/launch/LaunchWindow.tsx index 24d273b49..bf7d7298e 100644 --- a/src/components/launch/LaunchWindow.tsx +++ b/src/components/launch/LaunchWindow.tsx @@ -1,4 +1,12 @@ -import { Check, ChevronDown, Clapperboard, Columns3, Languages, Rows3 } from "lucide-react"; +import { + Check, + ChevronDown, + Clapperboard, + Columns3, + Languages, + NotepadText, + Rows3, +} from "lucide-react"; import { useCallback, useEffect, useRef, useState } from "react"; import { createPortal } from "react-dom"; import { BsPauseCircle, BsPlayCircle, BsRecordCircle } from "react-icons/bs"; @@ -697,7 +705,10 @@ export function LaunchWindow() { onMouseLeave={() => setIsMicHovered(false)} onFocus={() => setIsMicFocused(true)} onBlur={() => setIsMicFocused(false)} - style={{ width: micExpanded ? "240px" : "140px", transition: "width 300ms ease" }} + style={{ + width: micExpanded ? "240px" : "140px", + transition: "width 300ms ease", + }} >
{!micExpanded && ( @@ -743,7 +754,10 @@ export function LaunchWindow() { onMouseLeave={() => setIsWebcamHovered(false)} onFocus={() => setIsWebcamFocused(true)} onBlur={() => setIsWebcamFocused(false)} - style={{ width: webcamExpanded ? "240px" : "140px", transition: "width 300ms ease" }} + style={{ + width: webcamExpanded ? "240px" : "140px", + transition: "width 300ms ease", + }} >
{!webcamExpanded && ( @@ -1031,6 +1045,19 @@ export function LaunchWindow() {
)} + {!isLinuxHud && ( + + + + )} + {!recording && ( + + ); +} + +function useEditorRevision(editor: Editor | null): void { + const [, bumpRevision] = useReducer((revision: number) => revision + 1, 0); + + useEffect(() => { + if (!editor) { + return; + } + + const handleUpdate = () => { + bumpRevision(); + }; + + editor.on("selectionUpdate", handleUpdate); + editor.on("transaction", handleUpdate); + + return () => { + editor.off("selectionUpdate", handleUpdate); + editor.off("transaction", handleUpdate); + }; + }, [editor]); +} + +export function NotesToolbar({ editor }: NotesToolbarProps) { + useEditorRevision(editor); + const t = useScopedT("launch"); + + return ( +
+
+ editor?.chain().focus().toggleBold().run()} + > + + + editor?.chain().focus().toggleItalic().run()} + > + + + editor?.chain().focus().toggleStrike().run()} + > + + +
+
+
+
+ editor?.chain().focus().toggleBulletList().run()} + > + + + editor?.chain().focus().toggleOrderedList().run()} + > + + +
+
+
+
+ editor?.chain().focus().toggleBlockquote().run()} + > + + + editor?.chain().focus().toggleCodeBlock().run()} + > + + +
+
+ ); +} diff --git a/src/components/launch/NotesWindow.module.css b/src/components/launch/NotesWindow.module.css new file mode 100644 index 000000000..b0b0cf38a --- /dev/null +++ b/src/components/launch/NotesWindow.module.css @@ -0,0 +1,120 @@ +/* Tiptap sets class="tiptap" on the ProseMirror root — must be :global to escape CSS modules. */ +:global(.tiptap) { + height: 100%; + width: 100%; + outline: none; + overflow-y: auto; + color: #111827; + caret-color: #111827; +} + +:global(.tiptap) :first-child { + margin-top: 0; +} + +:global(.tiptap) p { + min-height: 1.5rem; + line-height: 1.5; + margin-top: 0.75rem; + margin-bottom: 0.75rem; +} + +:global(.tiptap) p:first-child { + margin-top: 0; +} + +/* Tailwind preflight strips list markers — restore them for markdown-style input rules. */ +:global(.tiptap) ul, +:global(.tiptap) ol { + padding-left: 1.5rem; + margin: 1rem 0; +} + +:global(.tiptap) ul { + list-style-type: disc; +} + +:global(.tiptap) ol { + list-style-type: decimal; +} + +:global(.tiptap) li { + display: list-item; +} + +:global(.tiptap) ul li p, +:global(.tiptap) ol li p { + margin-top: 0.25em; + margin-bottom: 0.25em; +} + +:global(.tiptap) h1, +:global(.tiptap) h2, +:global(.tiptap) h3, +:global(.tiptap) h4, +:global(.tiptap) h5, +:global(.tiptap) h6 { + line-height: 1.1; + margin-top: 2.5rem; + text-wrap: pretty; +} + +:global(.tiptap) h1, +:global(.tiptap) h2 { + margin-top: 3.5rem; + margin-bottom: 1.5rem; +} + +:global(.tiptap) h1 { + font-size: 1.4rem; +} + +:global(.tiptap) h2 { + font-size: 1.2rem; +} + +:global(.tiptap) h3 { + font-size: 1.1rem; +} + +:global(.tiptap) h4, +:global(.tiptap) h5, +:global(.tiptap) h6 { + font-size: 1rem; +} + +:global(.tiptap) code { + background-color: #ede9fe; + border-radius: 0.4rem; + color: #111827; + font-size: 0.85rem; + padding: 0.25em 0.3em; +} + +:global(.tiptap) pre { + background: #111827; + border-radius: 0.5rem; + color: #ffffff; + font-family: "JetBrainsMono", monospace; + margin: 1.5rem 0; + padding: 0.75rem 1rem; +} + +:global(.tiptap) pre code { + background: none; + color: inherit; + font-size: 0.8rem; + padding: 0; +} + +:global(.tiptap) blockquote { + border-left: 3px solid #d1d5db; + margin: 1.5rem 0; + padding-left: 1rem; +} + +:global(.tiptap) hr { + border: none; + border-top: 1px solid #e5e7eb; + margin: 2rem 0; +} diff --git a/src/components/launch/NotesWindow.tsx b/src/components/launch/NotesWindow.tsx new file mode 100644 index 000000000..2fb9e29ed --- /dev/null +++ b/src/components/launch/NotesWindow.tsx @@ -0,0 +1,45 @@ +import { EditorContent, useEditor } from "@tiptap/react"; +import StarterKit from "@tiptap/starter-kit"; +import { NotesToolbar } from "./NotesToolbar"; +import "./NotesWindow.module.css"; + +function getInitialNotesContent(): string { + const stored = localStorage.getItem("notes"); + if (!stored) { + return ""; + } + + // Notes saved before Tiptap were plain text; wrap so StarterKit can parse them. + if (!stored.trim().startsWith("<")) { + const escaped = stored.replace(/&/g, "&").replace(//g, ">"); + return `

${escaped.replace(/\n/g, "

")}

`; + } + + return stored; +} + +export function NotesWindow() { + const editor = useEditor({ + extensions: [StarterKit], + content: getInitialNotesContent(), + autofocus: "end", + editorProps: { + attributes: { + class: "tiptap", + }, + }, + onUpdate: ({ editor: nextEditor }) => { + localStorage.setItem("notes", nextEditor.getHTML()); + }, + }); + + return ( +
+
+ +
+ + +
+ ); +} diff --git a/src/i18n/locales/ar/launch.json b/src/i18n/locales/ar/launch.json index ef000a875..f902e8127 100644 --- a/src/i18n/locales/ar/launch.json +++ b/src/i18n/locales/ar/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "فتح ملف فيديو", "openProject": "فتح مشروع", "useVerticalTray": "استخدام الشريط العمودي", - "useHorizontalTray": "استخدام الشريط الأفقي" + "useHorizontalTray": "استخدام الشريط الأفقي", + "openNotes": "فتح الملاحظات", + "openNotesPlaceholder": "اكتب ملاحظاتك هنا...", + "notesToolbar": { + "bold": "غامق", + "italic": "مائل", + "strikethrough": "يتوسطه خط", + "bulletList": "قائمة نقطية", + "numberedList": "قائمة مرقمة", + "blockquote": "اقتباس", + "codeBlock": "كتلة تعليمات برمجية" + } }, "audio": { "enableSystemAudio": "تفعيل صوت النظام", diff --git a/src/i18n/locales/en/launch.json b/src/i18n/locales/en/launch.json index 0509752ee..0bdb21d64 100644 --- a/src/i18n/locales/en/launch.json +++ b/src/i18n/locales/en/launch.json @@ -10,7 +10,18 @@ "openProject": "Open project", "useVerticalTray": "Use vertical tray", "useHorizontalTray": "Use horizontal tray", - "openStudio": "Open Studio" + "openStudio": "Open Studio", + "openNotes": "Open Notes", + "openNotesPlaceholder": "Take notes here...", + "notesToolbar": { + "bold": "Bold", + "italic": "Italic", + "strikethrough": "Strikethrough", + "bulletList": "Bullet list", + "numberedList": "Numbered list", + "blockquote": "Blockquote", + "codeBlock": "Code block" + } }, "audio": { "enableSystemAudio": "Enable system audio", diff --git a/src/i18n/locales/es/launch.json b/src/i18n/locales/es/launch.json index bc6ba52a8..1d78246f6 100644 --- a/src/i18n/locales/es/launch.json +++ b/src/i18n/locales/es/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "Abrir archivo de video", "openProject": "Abrir proyecto", "useVerticalTray": "Usar bandeja vertical", - "useHorizontalTray": "Usar bandeja horizontal" + "useHorizontalTray": "Usar bandeja horizontal", + "openNotes": "Abrir notas", + "openNotesPlaceholder": "Escribe tus notas aquí...", + "notesToolbar": { + "bold": "Negrita", + "italic": "Cursiva", + "strikethrough": "Tachado", + "bulletList": "Lista con viñetas", + "numberedList": "Lista numerada", + "blockquote": "Cita", + "codeBlock": "Bloque de código" + } }, "audio": { "enableSystemAudio": "Activar audio del sistema", diff --git a/src/i18n/locales/fr/launch.json b/src/i18n/locales/fr/launch.json index 0a89376c2..36b4fdc65 100644 --- a/src/i18n/locales/fr/launch.json +++ b/src/i18n/locales/fr/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "Ouvrir un fichier vidéo", "openProject": "Ouvrir un projet", "useVerticalTray": "Utiliser la barre verticale", - "useHorizontalTray": "Utiliser la barre horizontale" + "useHorizontalTray": "Utiliser la barre horizontale", + "openNotes": "Ouvrir les notes", + "openNotesPlaceholder": "Prenez des notes ici...", + "notesToolbar": { + "bold": "Gras", + "italic": "Italique", + "strikethrough": "Barré", + "bulletList": "Liste à puces", + "numberedList": "Liste numérotée", + "blockquote": "Citation", + "codeBlock": "Bloc de code" + } }, "audio": { "enableSystemAudio": "Activer l'audio système", diff --git a/src/i18n/locales/it/launch.json b/src/i18n/locales/it/launch.json index 66c18bc9d..4d89c40dd 100644 --- a/src/i18n/locales/it/launch.json +++ b/src/i18n/locales/it/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "Apri file video", "openProject": "Apri progetto", "useVerticalTray": "Usa barra verticale", - "useHorizontalTray": "Usa barra orizzontale" + "useHorizontalTray": "Usa barra orizzontale", + "openNotes": "Apri note", + "openNotesPlaceholder": "Scrivi le tue note qui...", + "notesToolbar": { + "bold": "Grassetto", + "italic": "Corsivo", + "strikethrough": "Barrato", + "bulletList": "Elenco puntato", + "numberedList": "Elenco numerato", + "blockquote": "Citazione", + "codeBlock": "Blocco di codice" + } }, "audio": { "enableSystemAudio": "Abilita audio di sistema", diff --git a/src/i18n/locales/ja-JP/launch.json b/src/i18n/locales/ja-JP/launch.json index 66fd8ee6b..1010f1676 100644 --- a/src/i18n/locales/ja-JP/launch.json +++ b/src/i18n/locales/ja-JP/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "動画ファイルを開く", "openProject": "プロジェクトを開く", "useVerticalTray": "縦型トレイを使用", - "useHorizontalTray": "横型トレイを使用" + "useHorizontalTray": "横型トレイを使用", + "openNotes": "ノートを開く", + "openNotesPlaceholder": "ここにメモを入力...", + "notesToolbar": { + "bold": "太字", + "italic": "斜体", + "strikethrough": "取り消し線", + "bulletList": "箇条書きリスト", + "numberedList": "番号付きリスト", + "blockquote": "引用", + "codeBlock": "コードブロック" + } }, "audio": { "enableSystemAudio": "システム音声を有効にする", diff --git a/src/i18n/locales/ko-KR/launch.json b/src/i18n/locales/ko-KR/launch.json index 361ce8657..28a27a7cc 100644 --- a/src/i18n/locales/ko-KR/launch.json +++ b/src/i18n/locales/ko-KR/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "비디오 파일 열기", "openProject": "프로젝트 열기", "useVerticalTray": "세로 트레이 사용", - "useHorizontalTray": "가로 트레이 사용" + "useHorizontalTray": "가로 트레이 사용", + "openNotes": "노트 열기", + "openNotesPlaceholder": "여기에 메모를 입력하세요...", + "notesToolbar": { + "bold": "굵게", + "italic": "기울임꼴", + "strikethrough": "취소선", + "bulletList": "글머리 기호 목록", + "numberedList": "번호 매기기 목록", + "blockquote": "인용문", + "codeBlock": "코드 블록" + } }, "audio": { "enableSystemAudio": "시스템 오디오 활성화", diff --git a/src/i18n/locales/pt-BR/launch.json b/src/i18n/locales/pt-BR/launch.json index 185380920..4f865d452 100644 --- a/src/i18n/locales/pt-BR/launch.json +++ b/src/i18n/locales/pt-BR/launch.json @@ -7,7 +7,18 @@ "pauseRecording": "Pausar gravação", "resumeRecording": "Retomar gravação", "openVideoFile": "Abrir arquivo de vídeo", - "openProject": "Abrir projeto" + "openProject": "Abrir projeto", + "openNotes": "Abrir notas", + "openNotesPlaceholder": "Escreva suas notas aqui...", + "notesToolbar": { + "bold": "Negrito", + "italic": "Itálico", + "strikethrough": "Tachado", + "bulletList": "Lista com marcadores", + "numberedList": "Lista numerada", + "blockquote": "Citação", + "codeBlock": "Bloco de código" + } }, "audio": { "enableSystemAudio": "Ativar áudio do sistema", diff --git a/src/i18n/locales/ru/launch.json b/src/i18n/locales/ru/launch.json index 9b3361296..5f9b68d68 100644 --- a/src/i18n/locales/ru/launch.json +++ b/src/i18n/locales/ru/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "Открыть видеофайл", "openProject": "Открыть проект", "useVerticalTray": "Использовать вертикальную панель", - "useHorizontalTray": "Использовать горизонтальную панель" + "useHorizontalTray": "Использовать горизонтальную панель", + "openNotes": "Открыть заметки", + "openNotesPlaceholder": "Пишите заметки здесь...", + "notesToolbar": { + "bold": "Жирный", + "italic": "Курсив", + "strikethrough": "Зачеркнутый", + "bulletList": "Маркированный список", + "numberedList": "Нумерованный список", + "blockquote": "Цитата", + "codeBlock": "Блок кода" + } }, "audio": { "enableSystemAudio": "Включить системное аудио", diff --git a/src/i18n/locales/tr/launch.json b/src/i18n/locales/tr/launch.json index 921a52634..4fb7e98f3 100644 --- a/src/i18n/locales/tr/launch.json +++ b/src/i18n/locales/tr/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "Video dosyası aç", "openProject": "Proje aç", "useVerticalTray": "Dikey araç çubuğunu kullan", - "useHorizontalTray": "Yatay araç çubuğunu kullan" + "useHorizontalTray": "Yatay araç çubuğunu kullan", + "openNotes": "Notları aç", + "openNotesPlaceholder": "Notlarınızı buraya yazın...", + "notesToolbar": { + "bold": "Kalın", + "italic": "İtalik", + "strikethrough": "Üstü çizili", + "bulletList": "Madde işaretli liste", + "numberedList": "Numaralı liste", + "blockquote": "Alıntı", + "codeBlock": "Kod bloğu" + } }, "audio": { "enableSystemAudio": "Sistem sesini etkinleştir", diff --git a/src/i18n/locales/vi/launch.json b/src/i18n/locales/vi/launch.json index efbaad5d4..0a237bb6a 100644 --- a/src/i18n/locales/vi/launch.json +++ b/src/i18n/locales/vi/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "Mở tệp video", "openProject": "Mở dự án", "useVerticalTray": "Dùng khay dọc", - "useHorizontalTray": "Dùng khay ngang" + "useHorizontalTray": "Dùng khay ngang", + "openNotes": "Mở ghi chú", + "openNotesPlaceholder": "Ghi chú của bạn tại đây...", + "notesToolbar": { + "bold": "In đậm", + "italic": "In nghiêng", + "strikethrough": "Gạch ngang", + "bulletList": "Danh sách dấu đầu dòng", + "numberedList": "Danh sách đánh số", + "blockquote": "Trích dẫn", + "codeBlock": "Khối mã" + } }, "audio": { "enableSystemAudio": "Bật âm thanh hệ thống", diff --git a/src/i18n/locales/zh-CN/launch.json b/src/i18n/locales/zh-CN/launch.json index c08996585..0e7d66a8a 100644 --- a/src/i18n/locales/zh-CN/launch.json +++ b/src/i18n/locales/zh-CN/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "打开视频文件", "openProject": "打开项目", "useVerticalTray": "使用竖向托盘", - "useHorizontalTray": "使用横向托盘" + "useHorizontalTray": "使用横向托盘", + "openNotes": "打开笔记", + "openNotesPlaceholder": "在此输入笔记...", + "notesToolbar": { + "bold": "加粗", + "italic": "斜体", + "strikethrough": "删除线", + "bulletList": "无序列表", + "numberedList": "有序列表", + "blockquote": "引用", + "codeBlock": "代码块" + } }, "audio": { "enableSystemAudio": "启用系统音频", diff --git a/src/i18n/locales/zh-TW/launch.json b/src/i18n/locales/zh-TW/launch.json index d0b529ebe..ca64e3299 100644 --- a/src/i18n/locales/zh-TW/launch.json +++ b/src/i18n/locales/zh-TW/launch.json @@ -9,7 +9,18 @@ "openVideoFile": "開啟影片檔案", "openProject": "開啟專案", "useVerticalTray": "使用直向托盤", - "useHorizontalTray": "使用橫向托盤" + "useHorizontalTray": "使用橫向托盤", + "openNotes": "開啟筆記", + "openNotesPlaceholder": "在此輸入筆記...", + "notesToolbar": { + "bold": "粗體", + "italic": "斜體", + "strikethrough": "刪除線", + "bulletList": "項目符號清單", + "numberedList": "編號清單", + "blockquote": "引言", + "codeBlock": "程式碼區塊" + } }, "audio": { "enableSystemAudio": "啟用系統音訊", diff --git a/src/index.css b/src/index.css index 61621c750..eb7cb8384 100644 --- a/src/index.css +++ b/src/index.css @@ -80,7 +80,11 @@ flex-direction: column; padding: 14px; background: - radial-gradient(circle at 18% 0%, rgba(52, 178, 123, 0.08), transparent 30%), + radial-gradient( + circle at 18% 0%, + rgba(52, 178, 123, 0.08), + transparent 30% + ), linear-gradient(180deg, #08090b 0%, #050606 100%); } @@ -101,7 +105,11 @@ .editor-timeline-panel, .editor-inspector-shell { background: - linear-gradient(180deg, rgba(255, 255, 255, 0.035), rgba(255, 255, 255, 0.012)), + linear-gradient( + 180deg, + rgba(255, 255, 255, 0.035), + rgba(255, 255, 255, 0.012) + ), #090a0c; border: 1px solid rgba(255, 255, 255, 0.075); border-radius: 18px; @@ -305,4 +313,19 @@ input[type="range"]::-moz-range-thumb:active { transform: scale(1.25); } + + /* Hide scrollbar in Chrome, Safari, and Opera */ + .no-scrollbar::-webkit-scrollbar { + display: none; + } + + /* Hide scrollbar in Firefox */ + .no-scrollbar { + scrollbar-width: none; + } + + /* Hide scrollbar in IE and Edge */ + .no-scrollbar { + -ms-overflow-style: none; + } } diff --git a/src/main.tsx b/src/main.tsx index 365bdc7b2..ef7497386 100644 --- a/src/main.tsx +++ b/src/main.tsx @@ -5,7 +5,9 @@ import { I18nProvider } from "./contexts/I18nContext"; import "./index.css"; const windowType = new URLSearchParams(window.location.search).get("windowType") || ""; +const showNotes = new URLSearchParams(window.location.search).get("showNotes") === "true"; if ( + showNotes || windowType === "hud-overlay" || windowType === "source-selector" || windowType === "countdown-overlay"