Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions emain/emain-ipc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import {
incrementTermCommandsRemote,
incrementTermCommandsRun,
incrementTermCommandsWsl,
setWasActive,
} from "./emain-activity";
import { createBuilderWindow, getAllBuilderWindows, getBuilderWindowByWebContentsId } from "./emain-builder";
import { callWithOriginalXdgCurrentDesktopAsync, unamePlatform } from "./emain-platform";
Expand Down Expand Up @@ -317,6 +318,10 @@ export function initIpcHandlers() {
tabView?.setKeyboardChordMode(true);
});

electron.ipcMain.handle("set-is-active", () => {
setWasActive(true);
});

const fac = new FastAverageColor();
electron.ipcMain.on("update-window-controls-overlay", async (event, rect: Dimensions) => {
if (unamePlatform === "darwin") return;
Expand Down
1 change: 1 addition & 0 deletions emain/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ contextBridge.exposeInMainWorld("api", {
setBuilderWindowAppId: (appId: string) => ipcRenderer.send("set-builder-window-appid", appId),
doRefresh: () => ipcRenderer.send("do-refresh"),
saveTextFile: (fileName: string, content: string) => ipcRenderer.invoke("save-text-file", fileName, content),
setIsActive: () => ipcRenderer.invoke("set-is-active"),
});

// Custom event for "new-window"
Expand Down
8 changes: 6 additions & 2 deletions frontend/app/app.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
// tailwindsetup.css should come *after* app.scss (don't remove the newline above otherwise prettier will reorder these imports)
import "../tailwindsetup.css";

const dlog = debug("wave:app");

Check warning on line 37 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'dlog' is assigned a value but never used. Allowed unused vars must match /^_$/u

Check warning on line 37 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'dlog' is assigned a value but never used. Allowed unused vars must match /^_$/u
const focusLog = debug("wave:focus");

const App = ({ onFirstRender }: { onFirstRender: () => void }) => {
Expand Down Expand Up @@ -89,7 +89,7 @@
return null;
}
return url;
} catch (e) {

Check warning on line 92 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'e' is defined but never used

Check warning on line 92 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'e' is defined but never used
return null;
}
}
Expand All @@ -103,7 +103,7 @@
if (!canPaste && !canCopy && !canCut && !clipboardURL) {
return;
}
let menu: ContextMenuItem[] = [];

Check warning on line 106 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'menu' is never reassigned. Use 'const' instead

Check warning on line 106 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'menu' is never reassigned. Use 'const' instead
if (canCut) {
menu.push({ label: "Cut", role: "cut" });
}
Expand Down Expand Up @@ -168,7 +168,7 @@
focusLog("focusout", getElemAsStr(e.target), "=>", getElemAsStr(e.relatedTarget));
}

function appSelectionChange(e: Event) {

Check warning on line 171 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'e' is defined but never used. Allowed unused args must match /^_$/u

Check warning on line 171 in frontend/app/app.tsx

View workflow job for this annotation

GitHub Actions / copilot

'e' is defined but never used. Allowed unused args must match /^_$/u
const selection = document.getSelection();
focusLog("selectionchange", getElemAsStr(selection.anchorNode));
}
Expand Down Expand Up @@ -200,12 +200,16 @@
const AppKeyHandlers = () => {
useEffect(() => {
const staticKeyDownHandler = keyutil.keydownWrapper(appHandleKeyDown);
const staticMouseDownHandler = (e: MouseEvent) => {
keyboardMouseDownHandler(e);
void GlobalModel.getInstance().setIsActive();
};
document.addEventListener("keydown", staticKeyDownHandler);
document.addEventListener("mousedown", keyboardMouseDownHandler);
document.addEventListener("mousedown", staticMouseDownHandler);

return () => {
document.removeEventListener("keydown", staticKeyDownHandler);
document.removeEventListener("mousedown", keyboardMouseDownHandler);
document.removeEventListener("mousedown", staticMouseDownHandler);
};
}, []);
return null;
Expand Down
14 changes: 13 additions & 1 deletion frontend/app/store/global-model.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,17 @@

import * as WOS from "@/app/store/wos";
import { ClientModel } from "@/app/store/client-model";
import { getApi } from "@/store/global";
import { atom, Atom } from "jotai";

class GlobalModel {
private static instance: GlobalModel;
static readonly IsActiveThrottleMs = 5000;

windowId: string;
builderId: string;
platform: NodeJS.Platform;
lastSetIsActiveTs = 0;

windowDataAtom!: Atom<WaveWindow>;
workspaceAtom!: Atom<Workspace>;
Expand Down Expand Up @@ -47,6 +50,15 @@ class GlobalModel {
return WOS.getObjectValue(WOS.makeORef("workspace", windowData.workspaceid), get);
});
}

async setIsActive(): Promise<void> {
const now = Date.now();
if (now - this.lastSetIsActiveTs < GlobalModel.IsActiveThrottleMs) {
return;
}
this.lastSetIsActiveTs = now;
await getApi().setIsActive();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Missing error handling for IPC call

The getApi().setIsActive() call could fail (e.g., if the IPC channel is unavailable). Since this is a non-critical activity tracking feature called in a fire-and-forget manner, consider adding a try-catch to prevent unhandled promise rejections:

async setIsActive(): Promise<void> {
    const now = Date.now();
    if (now - this.lastSetIsActiveTs < GlobalModel.IsActiveThrottleMs) {
        return;
    }
    this.lastSetIsActiveTs = now;
    try {
        await getApi().setIsActive();
    } catch (e) {
        // Silently ignore errors for non-critical activity tracking
    }
}

}
}

export { GlobalModel };
export { GlobalModel };
1 change: 1 addition & 0 deletions frontend/types/custom.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,7 @@ declare global {
setBuilderWindowAppId: (appId: string) => void; // set-builder-window-appid
doRefresh: () => void; // do-refresh
saveTextFile: (fileName: string, content: string) => Promise<boolean>; // save-text-file
setIsActive: () => Promise<void>; // set-is-active
};

type ElectronContextMenuItem = {
Expand Down
Loading