Skip to content

Commit

Permalink
electron: Add support for filesystem storage through the IPC
Browse files Browse the repository at this point in the history
  • Loading branch information
rafaellehmkuhl authored and ArturoManzoli committed Dec 17, 2024
1 parent e221da8 commit c9db525
Show file tree
Hide file tree
Showing 7 changed files with 114 additions and 6 deletions.
2 changes: 2 additions & 0 deletions electron/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { join } from 'path'
import { setupAutoUpdater } from './services/auto-update'
import store from './services/config-store'
import { setupNetworkService } from './services/network'
import { setupFilesystemStorage } from './services/storage'

// If the app is packaged, push logs to the system instead of the console
if (app.isPackaged) {
Expand Down Expand Up @@ -71,6 +72,7 @@ protocol.registerSchemesAsPrivileged([
},
])

setupFilesystemStorage()
setupNetworkService()

app.whenReady().then(async () => {
Expand Down
17 changes: 17 additions & 0 deletions electron/preload.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,21 @@ contextBridge.exposeInMainWorld('electronAPI', {
downloadUpdate: () => ipcRenderer.send('download-update'),
installUpdate: () => ipcRenderer.send('install-update'),
cancelUpdate: () => ipcRenderer.send('cancel-update'),
setItem: async (key: string, value: Blob, subFolders?: string[]) => {
const arrayBuffer = await value.arrayBuffer()
await ipcRenderer.invoke('setItem', { key, value: new Uint8Array(arrayBuffer), subFolders })
},
getItem: async (key: string, subFolders?: string[]) => {
const arrayBuffer = await ipcRenderer.invoke('getItem', { key, subFolders })
return arrayBuffer ? new Blob([arrayBuffer]) : null
},
removeItem: async (key: string, subFolders?: string[]) => {
await ipcRenderer.invoke('removeItem', { key, subFolders })
},
clear: async (subFolders?: string[]) => {
await ipcRenderer.invoke('clear', { subFolders })
},
keys: async (subFolders?: string[]) => {
return await ipcRenderer.invoke('keys', { subFolders })
},
})
61 changes: 61 additions & 0 deletions electron/services/storage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
import { ipcMain } from 'electron'
import { app } from 'electron'
import * as fs from 'fs/promises'
import { dirname, join } from 'path'

// Create a new storage interface for filesystem
const cockpitFolderPath = join(app.getPath('home'), 'Cockpit')
fs.mkdir(cockpitFolderPath, { recursive: true })

export const filesystemStorage = {
async setItem(key: string, value: ArrayBuffer, subFolders?: string[]): Promise<void> {
const buffer = Buffer.from(value)
const filePath = join(cockpitFolderPath, ...(subFolders ?? []), key)
await fs.mkdir(dirname(filePath), { recursive: true })
await fs.writeFile(filePath, buffer)
},
async getItem(key: string, subFolders?: string[]): Promise<ArrayBuffer | null> {
const filePath = join(cockpitFolderPath, ...(subFolders ?? []), key)
try {
return await fs.readFile(filePath)
} catch (error) {
if (error.code === 'ENOENT') return null
throw error
}
},
async removeItem(key: string, subFolders?: string[]): Promise<void> {
const filePath = join(cockpitFolderPath, ...(subFolders ?? []), key)
await fs.unlink(filePath)
},
async clear(subFolders?: string[]): Promise<void> {
const dirPath = join(cockpitFolderPath, ...(subFolders ?? []))
await fs.rm(dirPath, { recursive: true })
},
async keys(subFolders?: string[]): Promise<string[]> {
const dirPath = join(cockpitFolderPath, ...(subFolders ?? []))
try {
return await fs.readdir(dirPath)
} catch (error) {
if (error.code === 'ENOENT') return []
throw error
}
},
}

export const setupFilesystemStorage = (): void => {
ipcMain.handle('setItem', async (_, data) => {
await filesystemStorage.setItem(data.key, data.value, data.subFolders)
})
ipcMain.handle('getItem', async (_, data) => {
return await filesystemStorage.getItem(data.key, data.subFolders)
})
ipcMain.handle('removeItem', async (_, data) => {
await filesystemStorage.removeItem(data.key, data.subFolders)
})
ipcMain.handle('clear', async (_, data) => {
await filesystemStorage.clear(data.subFolders)
})
ipcMain.handle('keys', async (_, data) => {
return await filesystemStorage.keys(data.subFolders)
})
}
3 changes: 2 additions & 1 deletion src/libs/cosmos.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { isBrowser } from 'browser-or-node'

import { ElectronStorageDB } from '@/types/general'
import { NetworkInfo } from '@/types/network'

import {
Expand Down Expand Up @@ -185,7 +186,7 @@ declare global {
/**
* Electron API exposed through preload script
*/
electronAPI?: {
electronAPI?: ElectronStorageDB & {
/**
* Get network information from the main process
* @returns Promise containing subnet information
Expand Down
2 changes: 1 addition & 1 deletion src/stores/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,10 +21,10 @@ import { isEqual, sleep } from '@/libs/utils'
import { useMainVehicleStore } from '@/stores/mainVehicle'
import { useMissionStore } from '@/stores/mission'
import { Alert, AlertLevel } from '@/types/alert'
import { StorageDB } from '@/types/general'
import {
type DownloadProgressCallback,
type FileDescriptor,
type StorageDB,
type StreamData,
type UnprocessedVideoInfo,
type VideoProcessingDetails,
Expand Down
31 changes: 31 additions & 0 deletions src/types/general.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,34 @@ export interface DialogActions {
}

export type ConfigComponent = DefineComponent<Record<string, never>, Record<string, never>, unknown> | null

export interface StorageDB {
getItem: (key: string) => Promise<Blob | null | undefined>
setItem: (key: string, value: Blob) => Promise<void>
removeItem: (key: string) => Promise<void>
clear: () => Promise<void>
keys: () => Promise<string[]>
}

export interface ElectronStorageDB {
/**
* Set an item in the filesystem storage
*/
setItem: (key: string, value: Blob, subFolders?: string[]) => Promise<void>
/**
* Get an item from the filesystem storage
*/
getItem: (key: string, subFolders?: string[]) => Promise<Blob | null | undefined>
/**
* Remove an item from the filesystem storage
*/
removeItem: (key: string, subFolders?: string[]) => Promise<void>
/**
* Clear the filesystem storage
*/
clear: (subFolders?: string[]) => Promise<void>
/**
* Get all keys from the filesystem storage
*/
keys: (subFolders?: string[]) => Promise<string[]>
}
4 changes: 0 additions & 4 deletions src/types/video.ts
Original file line number Diff line number Diff line change
Expand Up @@ -108,10 +108,6 @@ export interface FileDescriptor {
filename: string
}

export interface StorageDB {
getItem: (key: string) => Promise<Blob | null | undefined>
}

export type DownloadProgressCallback = (progress: number, total: number) => Promise<void>

export enum VideoExtensionContainer {
Expand Down

0 comments on commit c9db525

Please sign in to comment.