Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions apps/frontend/electron.main.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
const { app, BrowserWindow, ipcMain, safeStorage, shell, powerMonitor } = require("electron")
const path = require("path")
const { fork } = require("child_process")
const { createApplicationMenu } = require("./menu")

let serverProcess
const metricsProcesses = new Map()
Expand Down Expand Up @@ -153,6 +154,7 @@ function createWindow() {
}

app.whenReady().then(() => {
createApplicationMenu()
startServer()
if (serverProcess) {
serverProcess.on("message", (message) => {
Expand Down
46 changes: 46 additions & 0 deletions apps/frontend/menu.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
/* eslint-disable @typescript-eslint/no-require-imports */
const { Menu, BrowserWindow, shell } = require("electron")

function createApplicationMenu() {
const isMac = process.platform === "darwin"

const template = [
...(isMac ? [{ role: "appMenu" }] : []),
{ role: "fileMenu" },
{ role: "editMenu" },
{ role: "viewMenu" },
{
label: "Shortcuts",
submenu: [
{ label: "Connections", accelerator: isMac ? "Cmd+1" : "Ctrl+1", click: () => sendNavigationEvent("connect") },
{ label: "Dashboard", accelerator: isMac ? "Cmd+2" : "Ctrl+2", click: () => sendNavigationEvent("dashboard") },
{ label: "Key Browser", accelerator: isMac ? "Cmd+3" : "Ctrl+3", click: () => sendNavigationEvent("browse") },
{ label: "Monitoring", accelerator: isMac ? "Cmd+4" : "Ctrl+4", click: () => sendNavigationEvent("monitoring") },
{ label: "Send Command", accelerator: isMac ? "Cmd+5" : "Ctrl+5", click: () => sendNavigationEvent("sendcommand") },
{ label: "Cluster Topology", accelerator: isMac ? "Cmd+6" : "Ctrl+6", click: () => sendNavigationEvent("cluster-topology") },
{ label: "Settings", accelerator: isMac ? "Cmd+7" : "Ctrl+7", click: () => sendNavigationEvent("settings") },
{ label: "Learn More", accelerator: isMac ? "Cmd+8" : "Ctrl+8", click: () => sendNavigationEvent("learnmore") },

],
},
{ role: "windowMenu" },
{
role: "help",
submenu: [
{ label: "GitHub Repository", click: async () => { await shell.openExternal("https://github.com/valkey-io/valkey-admin") } },
],
},
]

const menu = Menu.buildFromTemplate(template)
Menu.setApplicationMenu(menu)
}

function sendNavigationEvent(route) {
const win = BrowserWindow.getFocusedWindow() || BrowserWindow.getAllWindows()[0]
if (win) {
win.webContents.send("navigate", route)
}
}

module.exports = { createApplicationMenu }
6 changes: 6 additions & 0 deletions apps/frontend/preload.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,9 @@ contextBridge.exposeInMainWorld("secureStorage", {
encrypt: (password) => ipcRenderer.invoke("secure-storage:encrypt", password),
decrypt: (encrypted) => ipcRenderer.invoke("secure-storage:decrypt", encrypted),
})

contextBridge.exposeInMainWorld("electronNavigation", {
onNavigate: (callback) => {
ipcRenderer.on("navigate", (_event, route) => callback(route))
},
})
2 changes: 2 additions & 0 deletions apps/frontend/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@ import { Toaster } from "./components/ui/sonner"
import { DarkModeProvider } from "./contexts/DarkModeContext"
import { useWebSocketNavigation } from "./hooks/useWebSocketNavigation"
import { useValkeyConnectionNavigation } from "./hooks/useValkeyConnectionNavigation"
import { useShortcutNavigation } from "./hooks/useShortcutNavigation"
import { connectPending } from "@/state/wsconnection/wsConnectionSlice"

function App() {
const dispatch = useDispatch()

useWebSocketNavigation()
useValkeyConnectionNavigation()
useShortcutNavigation()

useEffect(() => {
dispatch(connectPending())
Expand Down
40 changes: 40 additions & 0 deletions apps/frontend/src/hooks/useShortcutNavigation.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
import { useEffect } from "react"
import { useNavigate, useParams } from "react-router"
import useIsConnected from "./useIsConnected"

export const useShortcutNavigation = () => {
const navigate = useNavigate()
const { id, clusterId } = useParams()
const isConnected = useIsConnected()

useEffect(() => {
// only works when running in electron
if (!window.electronNavigation) return

const handleNavigate = (route: string) => {
const routes: Record<string, string> = isConnected
? {
connect: clusterId ? `/${clusterId}/${id}/connect` : `/${id}/connect`,
dashboard: clusterId ? `/${clusterId}/${id}/dashboard` : `/${id}/dashboard`,
browse: clusterId ? `/${clusterId}/${id}/browse` : `/${id}/browse`,
monitoring: clusterId ? `/${clusterId}/${id}/monitoring` : `/${id}/monitoring`,
sendcommand: clusterId ? `/${clusterId}/${id}/sendcommand` : `/${id}/sendcommand`,
"cluster-topology": clusterId ? `/${clusterId}/${id}/cluster-topology` : "",
settings: clusterId ? `/${clusterId}/${id}/settings` : `/${id}/settings`,
learnmore: clusterId ? `/${clusterId}/${id}/learnmore` : `/${id}/learnmore`,
}
: {
connect: "/connect",
settings: "/settings",
learnmore: "/learnmore",
}

const targetRoute = routes[route]
if (targetRoute) {
navigate(targetRoute)
}
}

window.electronNavigation.onNavigate(handleNavigate)
}, [navigate, id, clusterId, isConnected])
}
9 changes: 9 additions & 0 deletions apps/frontend/src/types/electron.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
export interface ElectronNavigation {
onNavigate: (callback: (route: string) => void) => void
}

declare global {
interface Window {
electronNavigation: ElectronNavigation
}
}
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@
"files": [
"apps/frontend/electron.main.js",
"apps/frontend/preload.js",
"apps/frontend/menu.js",
"apps/frontend/dist/**/*",
"package.json"
],
Expand Down
Loading