Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
1,064 changes: 1,064 additions & 0 deletions apps/electron-app/src/main/browser/dialog-manager.ts

Large diffs are not rendered by default.

1,724 changes: 1,724 additions & 0 deletions apps/electron-app/src/main/browser/templates/settings-dialog.html

Large diffs are not rendered by default.

180 changes: 180 additions & 0 deletions apps/electron-app/src/main/hotkey-manager.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,180 @@
import { globalShortcut } from "electron";
import { createLogger } from "@vibe/shared-types";
import { useUserProfileStore } from "@/store/user-profile-store";

const logger = createLogger("hotkey-manager");

// Default hotkey for password paste
const DEFAULT_PASSWORD_PASTE_HOTKEY = "CommandOrControl+Shift+P";

// Currently registered hotkeys
const registeredHotkeys = new Map<string, string>();

/**
* Register a global hotkey
*/
export function registerHotkey(hotkey: string, action: () => void): boolean {
try {
// Unregister existing hotkey if it exists
if (registeredHotkeys.has(hotkey)) {
globalShortcut.unregister(hotkey);
registeredHotkeys.delete(hotkey);
}

// Register new hotkey
const success = globalShortcut.register(hotkey, action);
if (success) {
registeredHotkeys.set(hotkey, action.name);
logger.info(`Registered hotkey: ${hotkey}`);
} else {
logger.error(`Failed to register hotkey: ${hotkey}`);
}
return success;
} catch (error) {
logger.error(`Error registering hotkey ${hotkey}:`, error);
return false;
}
}

/**
* Unregister a global hotkey
*/
export function unregisterHotkey(hotkey: string): boolean {
try {
globalShortcut.unregister(hotkey);
registeredHotkeys.delete(hotkey);
logger.info(`Unregistered hotkey: ${hotkey}`);
return true;
} catch (error) {
logger.error(`Error unregistering hotkey ${hotkey}:`, error);
return false;
}
}

/**
* Get the current password paste hotkey from settings
*/
export function getPasswordPasteHotkey(): string {
try {
const userProfileStore = useUserProfileStore.getState();
const activeProfile = userProfileStore.getActiveProfile();
return (
activeProfile?.settings?.hotkeys?.passwordPaste ||
DEFAULT_PASSWORD_PASTE_HOTKEY
);
} catch (error) {
logger.error("Failed to get password paste hotkey from settings:", error);
return DEFAULT_PASSWORD_PASTE_HOTKEY;
}
}

/**
* Set the password paste hotkey in settings
*/
export function setPasswordPasteHotkey(hotkey: string): boolean {
try {
const userProfileStore = useUserProfileStore.getState();
const activeProfile = userProfileStore.getActiveProfile();

if (!activeProfile) {
logger.error("No active profile found");
return false;
}

// Update profile settings
const updatedSettings = {
...activeProfile.settings,
hotkeys: {
...activeProfile.settings?.hotkeys,
passwordPaste: hotkey,
},
};

userProfileStore.updateProfile(activeProfile.id, {
settings: updatedSettings,
});

logger.info(`Password paste hotkey updated to: ${hotkey}`);
return true;
} catch (error) {
logger.error("Failed to set password paste hotkey:", error);
return false;
}
}

/**
* Initialize password paste hotkey
*/
export function initializePasswordPasteHotkey(): boolean {
try {
const hotkey = getPasswordPasteHotkey();

const action = async () => {
try {
// Import the password paste function directly
const { pastePasswordForActiveTab } = await import(
"./password-paste-handler"
);
const result = await pastePasswordForActiveTab();
if (result.success) {
logger.info("Password pasted successfully via hotkey");
} else {
logger.warn("Failed to paste password via hotkey:", result.error);
}
} catch (error) {
logger.error("Error in password paste hotkey action:", error);
}
};

return registerHotkey(hotkey, action);
} catch (error) {
logger.error("Failed to initialize password paste hotkey:", error);
return false;
}
}

/**
* Update password paste hotkey
*/
export function updatePasswordPasteHotkey(newHotkey: string): boolean {
try {
const oldHotkey = getPasswordPasteHotkey();

// Unregister old hotkey
unregisterHotkey(oldHotkey);

// Set new hotkey in settings
const success = setPasswordPasteHotkey(newHotkey);
if (!success) {
return false;
}

// Register new hotkey
return initializePasswordPasteHotkey();
} catch (error) {
logger.error("Failed to update password paste hotkey:", error);
return false;
}
}

/**
* Get all registered hotkeys
*/
export function getRegisteredHotkeys(): Map<string, string> {
return new Map(registeredHotkeys);
}

/**
* Cleanup all registered hotkeys
*/
export function cleanupHotkeys(): void {
try {
registeredHotkeys.forEach((_actionName, hotkey) => {
globalShortcut.unregister(hotkey);
logger.info(`Cleaned up hotkey: ${hotkey}`);
});
registeredHotkeys.clear();
} catch (error) {
logger.error("Error cleaning up hotkeys:", error);
}
}
43 changes: 43 additions & 0 deletions apps/electron-app/src/main/ipc/app/hotkey-control.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import { ipcMain } from "electron";
import { createLogger } from "@vibe/shared-types";
import {
getPasswordPasteHotkey,
updatePasswordPasteHotkey,
getRegisteredHotkeys,
} from "@/hotkey-manager";

const logger = createLogger("hotkey-control");

/**
* Hotkey management IPC handlers
*/

ipcMain.handle("hotkeys:get-password-paste", async () => {
try {
const hotkey = getPasswordPasteHotkey();
return { success: true, hotkey };
} catch (error) {
logger.error("Failed to get password paste hotkey:", error);
return { success: false, error: "Failed to get hotkey" };
}
});

ipcMain.handle("hotkeys:set-password-paste", async (_event, hotkey: string) => {
try {
const success = updatePasswordPasteHotkey(hotkey);
return { success };
} catch (error) {
logger.error("Failed to set password paste hotkey:", error);
return { success: false, error: "Failed to set hotkey" };
}
});

ipcMain.handle("hotkeys:get-registered", async () => {
try {
const hotkeys = getRegisteredHotkeys();
return { success: true, hotkeys: Object.fromEntries(hotkeys) };
} catch (error) {
logger.error("Failed to get registered hotkeys:", error);
return { success: false, error: "Failed to get hotkeys" };
}
});
30 changes: 30 additions & 0 deletions apps/electron-app/src/main/ipc/app/modals.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/**
* Modal IPC handlers
* Handles modal-related IPC events that are not handled by DialogManager
*/

import { ipcMain } from "electron";
import { createLogger } from "@vibe/shared-types";

const logger = createLogger("ipc-modals");

// Note: dialog:show-settings is handled by DialogManager directly
// We only handle the modal closed events here

// Handle settings modal closed event
ipcMain.on("app:settings-modal-closed", () => {
logger.debug("Settings modal closed");

// Optional: You could add any cleanup logic here
// For now, just acknowledge the event
});

// Handle downloads modal closed event
ipcMain.on("app:downloads-modal-closed", () => {
logger.debug("Downloads modal closed");

// Optional: You could add any cleanup logic here
// For now, just acknowledge the event
});

logger.info("Modal IPC handlers registered");
17 changes: 17 additions & 0 deletions apps/electron-app/src/main/ipc/app/password-paste.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { ipcMain } from "electron";
import {
pastePasswordForDomain,
pastePasswordForActiveTab,
} from "@/password-paste-handler";

/**
* Password paste IPC handlers
*/

ipcMain.handle("password:paste-for-domain", async (_event, domain: string) => {
return await pastePasswordForDomain(domain);
});

ipcMain.handle("password:paste-for-active-tab", async _event => {
return await pastePasswordForActiveTab();
});
Loading
Loading