175 lines
4.5 KiB
JavaScript
175 lines
4.5 KiB
JavaScript
import { createContext, useEffect, useState } from 'react'
|
|
import PropTypes from 'prop-types'
|
|
import { useNavigate } from 'react-router-dom'
|
|
|
|
// Only available in Electron renderer
|
|
const electron = window.require ? window.require('electron') : null
|
|
const ipcRenderer = electron ? electron.ipcRenderer : null
|
|
|
|
// Utility to check if running in Electron
|
|
export function isElectron() {
|
|
// Renderer process
|
|
|
|
if (
|
|
typeof window !== 'undefined' &&
|
|
window.process &&
|
|
window.process.type === 'renderer'
|
|
) {
|
|
return true
|
|
}
|
|
|
|
// User agent
|
|
if (
|
|
typeof navigator === 'object' &&
|
|
typeof navigator.userAgent === 'string' &&
|
|
navigator.userAgent.indexOf('Electron') >= 0
|
|
) {
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
const ElectronContext = createContext()
|
|
|
|
const ElectronProvider = ({ children }) => {
|
|
const [platform, setPlatform] = useState('unknown')
|
|
const [isMaximized, setIsMaximized] = useState(false)
|
|
const [isFullScreen, setIsFullScreen] = useState(false)
|
|
const [electronAvailable] = useState(isElectron())
|
|
const navigate = useNavigate()
|
|
|
|
// Function to open external URL via Electron
|
|
const openExternalUrl = (url) => {
|
|
if (electronAvailable && ipcRenderer) {
|
|
ipcRenderer.invoke('open-external-url', url)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
// Function to open internal URL via Electron
|
|
const openInternalUrl = (url) => {
|
|
if (electronAvailable && ipcRenderer) {
|
|
ipcRenderer.invoke('open-internal-url', url)
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (!ipcRenderer) return
|
|
|
|
// Get initial platform
|
|
ipcRenderer.invoke('os-info').then((info) => {
|
|
if (info && info.platform) setPlatform(info.platform)
|
|
})
|
|
|
|
// Get initial window state
|
|
ipcRenderer.invoke('window-state').then((state) => {
|
|
if (state && typeof state.isMaximized === 'boolean') {
|
|
setIsMaximized(state.isMaximized)
|
|
}
|
|
if (state && typeof state.isFullScreen === 'boolean') {
|
|
setIsFullScreen(state.isFullScreen)
|
|
}
|
|
})
|
|
|
|
// Listen for window state changes
|
|
const windowStateHandler = (event, state) => {
|
|
if (state && typeof state.isMaximized === 'boolean') {
|
|
setIsMaximized(state.isMaximized)
|
|
}
|
|
if (state && typeof state.isFullScreen === 'boolean') {
|
|
setIsFullScreen(state.isFullScreen)
|
|
}
|
|
}
|
|
ipcRenderer.on('window-state', windowStateHandler)
|
|
|
|
// Listen for navigate
|
|
const navigateHandler = (event, url) => {
|
|
console.log('Navigating to:', url)
|
|
navigate(url)
|
|
}
|
|
ipcRenderer.on('navigate', navigateHandler)
|
|
|
|
return () => {
|
|
ipcRenderer.removeListener('navigate', navigateHandler)
|
|
ipcRenderer.removeListener('window-state', windowStateHandler)
|
|
}
|
|
}, [])
|
|
|
|
// Window control handler
|
|
const handleWindowControl = (action) => {
|
|
if (electronAvailable && ipcRenderer) {
|
|
ipcRenderer.send('window-control', action)
|
|
}
|
|
}
|
|
|
|
const getAuthSession = async () => {
|
|
if (!electronAvailable || !ipcRenderer) return null
|
|
return await ipcRenderer.invoke('auth-session-get')
|
|
}
|
|
|
|
const setAuthSession = async (session) => {
|
|
if (!electronAvailable || !ipcRenderer) return false
|
|
return await ipcRenderer.invoke('auth-session-set', session)
|
|
}
|
|
|
|
const clearAuthSession = async () => {
|
|
if (!electronAvailable || !ipcRenderer) return false
|
|
return await ipcRenderer.invoke('auth-session-clear')
|
|
}
|
|
|
|
// Backwards-compatible helpers
|
|
const getToken = async () => {
|
|
const session = await getAuthSession()
|
|
return session?.token || null
|
|
}
|
|
|
|
const setToken = async (token) => {
|
|
const session = (await getAuthSession()) || {}
|
|
return await setAuthSession({ ...session, token })
|
|
}
|
|
|
|
const resizeSpotlightWindow = async (height) => {
|
|
if (!electronAvailable || !ipcRenderer) return false
|
|
try {
|
|
return await ipcRenderer.invoke('spotlight-window-resize', height)
|
|
} catch (error) {
|
|
console.warn(
|
|
'[ElectronContext] Failed to resize spotlight window:',
|
|
error
|
|
)
|
|
return false
|
|
}
|
|
}
|
|
|
|
return (
|
|
<ElectronContext.Provider
|
|
value={{
|
|
platform,
|
|
isMaximized,
|
|
isFullScreen,
|
|
isElectron: electronAvailable,
|
|
handleWindowControl,
|
|
openExternalUrl,
|
|
openInternalUrl,
|
|
getAuthSession,
|
|
setAuthSession,
|
|
clearAuthSession,
|
|
getToken,
|
|
setToken,
|
|
resizeSpotlightWindow
|
|
}}
|
|
>
|
|
{children}
|
|
</ElectronContext.Provider>
|
|
)
|
|
}
|
|
|
|
ElectronProvider.propTypes = {
|
|
children: PropTypes.node.isRequired
|
|
}
|
|
|
|
export { ElectronContext, ElectronProvider }
|