'
@@ -14,7 +14,7 @@ let callBackPort: number
function handleCallback(req: http.IncomingMessage, res: http.ServerResponse): void {
const parsedUrl = url.parse(req.url || '', true)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`AUTH: Received callback request for ${parsedUrl.pathname}`
)
@@ -29,7 +29,6 @@ function handleCallback(req: http.IncomingMessage, res: http.ServerResponse): vo
const appName = urlParts[1] // The app name should be the third part after '/callback/'
const config = getAppData() // Assuming getConfig() returns an object with active apps
- console.log('AUTH DATA: ', config)
if (!config.apps || !config.apps.some((app) => app.name === appName && app.enabled)) {
res.writeHead(404, { 'Content-Type': 'text/html' })
res.end(`
App Not Found
App '${appName}' not found or not active.
`)
@@ -37,7 +36,6 @@ function handleCallback(req: http.IncomingMessage, res: http.ServerResponse): vo
}
const code = parsedUrl.query.code as string
- console.log('AUTH CODE: ', code)
sendMessageToApp(appName, { type: 'callback-data', payload: code })
res.writeHead(200, { 'Content-Type': 'text/html' })
@@ -47,11 +45,10 @@ function handleCallback(req: http.IncomingMessage, res: http.ServerResponse): vo
const startServer = async (): Promise => {
if (server) {
await server.close(() => {
- console.log('CALLBACK: Previous server closed.')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'CALLBACK: Shutting down the server...')
})
}
- console.log('CALLBACK: Starting server...')
server = http.createServer((req, res) => {
const parsedUrl = new URL(`http://${req.headers.host}${req.url}`)
const pathname = parsedUrl.pathname
@@ -63,9 +60,8 @@ const startServer = async (): Promise => {
}
})
- console.log('CALLBACK: Listening...')
server.listen(callBackPort, () => {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.MESSAGE,
`CALLBACK: running at http://localhost:${callBackPort}/`
)
@@ -82,16 +78,18 @@ const initializeServer = async (): Promise => {
}
}
-dataListener.on(MESSAGE_TYPES.SETTINGS, (newSettings) => {
+settingsStore.addListener((newSettings) => {
try {
if (newSettings.callbackPort != callBackPort) {
callBackPort = newSettings.callbackPort
startServer()
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'CALLBACK: Not starting - port is not changed')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'CALLBACK: Not starting - port is not changed')
}
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'CALLBACK: Error updating with settings', error)
+ if (error instanceof Error) {
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'CALLBACK: Error updating with settings' + error)
+ }
}
})
diff --git a/DeskThingServer/src/main/handlers/clientHandler.ts b/DeskThingServer/src/main/handlers/clientHandler.ts
index 88548ee..8d527b4 100644
--- a/DeskThingServer/src/main/handlers/clientHandler.ts
+++ b/DeskThingServer/src/main/handlers/clientHandler.ts
@@ -1,5 +1,5 @@
-import { ClientIPCData, ReplyFn } from '@shared/types/ipcTypes'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import { ClientIPCData, ClientManifest, SocketData, ReplyFn, MESSAGE_TYPES } from '@shared/types'
+import loggingStore from '../stores/loggingStore'
import { handleAdbCommands } from './adbHandler'
import {
configureDevice,
@@ -9,7 +9,6 @@ import {
HandleWebappZipFromUrl,
SetupProxy
} from './deviceHandler'
-import { ClientManifest, SocketData } from '@shared/types'
import { sendMessageToClient, sendMessageToClients } from '../services/client/clientCom'
export const clientHandler: Record<
@@ -28,7 +27,11 @@ export const clientHandler: Record<
return `Pinging ${data.payload}...`
} catch (error) {
console.error('Error pinging client:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, error)
+ if (error instanceof Error) {
+ loggingStore.log(MESSAGE_TYPES.ERROR, error.message)
+ } else {
+ loggingStore.log(MESSAGE_TYPES.ERROR, String(error))
+ }
return 'Error pinging' + data.payload
}
},
@@ -45,7 +48,6 @@ export const clientHandler: Record<
return handleUrl(data, replyFn)
},
adb: async (data, replyFn) => {
- console.log('Running ADB command:', data.payload)
replyFn('logging', { status: true, data: 'Working', final: false })
const response = await handleAdbCommands(data.payload, replyFn)
@@ -70,7 +72,7 @@ export const clientHandler: Record<
},
'push-staged': async (data, replyFn) => {
try {
- console.log('Pushing staged webapp...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Pushing staged app...')
HandlePushWebApp(data.payload, replyFn)
} catch (error) {
replyFn('logging', {
@@ -79,13 +81,16 @@ export const clientHandler: Record<
error: 'Failed to push staged app!',
final: true
})
- console.error('Error extracting zip file:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, error)
+ if (error instanceof Error) {
+ loggingStore.log(MESSAGE_TYPES.ERROR, error.message)
+ } else {
+ loggingStore.log(MESSAGE_TYPES.ERROR, String(error))
+ }
}
},
'push-proxy-script': async (data, replyFn) => {
try {
- console.log('Pushing proxy script...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Pushing proxy script...')
SetupProxy(replyFn, data.payload)
replyFn('logging', {
status: true,
@@ -100,7 +105,11 @@ export const clientHandler: Record<
final: true
})
console.error('Error pushing proxy script:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, error)
+ if (error instanceof Error) {
+ loggingStore.log(MESSAGE_TYPES.ERROR, error.message)
+ } else {
+ loggingStore.log(MESSAGE_TYPES.ERROR, String(error))
+ }
}
},
'run-device-command': async (data, replyFn) => {
@@ -112,7 +121,6 @@ export const clientHandler: Record<
request: data.payload.request,
payload: !payload.includes('{') ? data.payload.payload : JSON.parse(data.payload.payload)
}
- console.log('Sending data', data)
replyFn('logging', { status: true, data: 'Finished', final: true })
return await sendMessageToClients(message)
}
diff --git a/DeskThingServer/src/main/handlers/configHandler.ts b/DeskThingServer/src/main/handlers/configHandler.ts
index c7ea00f..bbc5480 100644
--- a/DeskThingServer/src/main/handlers/configHandler.ts
+++ b/DeskThingServer/src/main/handlers/configHandler.ts
@@ -1,6 +1,6 @@
import { sendIpcData } from '..'
-import { AppData, App, Manifest, ButtonMapping } from '@shared/types'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import { AppData, App, MESSAGE_TYPES, Manifest, ButtonMapping } from '@shared/types'
+import loggingStore from '../stores/loggingStore'
import { readFromFile, writeToFile } from '../utils/fileHandler'
const defaultData: AppData = {
@@ -17,7 +17,6 @@ const readData = (): AppData => {
const data = readFromFile(dataFilePath)
if (!data) {
// File does not exist, create it with default data
- console.log('File does not exist, creating it with default data')
writeToFile(defaultData, dataFilePath)
return defaultData
}
@@ -34,11 +33,11 @@ const writeData = (data: AppData): void => {
try {
const result = writeToFile(data, 'apps.json')
if (!result) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'Error writing data')
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'Error writing data')
}
sendIpcData('app-data', data) // Send data to the web UI
} catch (err) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'Error writing data' + err)
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'Error writing data' + err)
console.error('Error writing data:', err)
}
}
@@ -104,12 +103,11 @@ const addConfig = (configName: string, config: string | Array, data = re
} else {
data.config[configName] = config
}
- console.log('THIS IS THE FIRST TIME THIS IS BEING EMITTED - TRY AND TRACK IT')
- dataListener.asyncEmit(MESSAGE_TYPES.CONFIG, {
- app: 'server',
- type: 'config',
- payload: data.config
- })
+ // loggingStore.log(MESSAGE_TYPES.CONFIG, {
+ // app: 'server',
+ // type: 'config',
+ // payload: data.config
+ // })
writeData(data)
}
const getConfig = (
@@ -150,7 +148,7 @@ const getAppByIndex = (index: number): App | undefined => {
}
const purgeAppConfig = async (appName: string): Promise => {
- console.log('SERVER: Deleting App From Config...', appName)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `Purging app: ${appName}`)
const data = readData()
// Filter out the app to be purged
@@ -158,11 +156,11 @@ const purgeAppConfig = async (appName: string): Promise => {
data.apps = filteredApps
writeData(data)
- dataListener.asyncEmit(MESSAGE_TYPES.CONFIG, {
- app: 'server',
- type: 'config',
- payload: data.config
- })
+ // loggingStore.log(MESSAGE_TYPES.CONFIG, {
+ // app: 'server',
+ // type: 'config',
+ // payload: data.config
+ // })
}
export {
diff --git a/DeskThingServer/src/main/handlers/dataHandler.ts b/DeskThingServer/src/main/handlers/dataHandler.ts
index ff8fec1..b11a294 100644
--- a/DeskThingServer/src/main/handlers/dataHandler.ts
+++ b/DeskThingServer/src/main/handlers/dataHandler.ts
@@ -62,7 +62,6 @@ const getData = (app: string): AppDataInterface => {
}
const purgeAppData = async (appName: string): Promise => {
- console.log('SERVER: Deleting app data...')
const data = readData()
delete data[appName]
writeData(data)
diff --git a/DeskThingServer/src/main/handlers/deviceHandler.ts b/DeskThingServer/src/main/handlers/deviceHandler.ts
index 8155f5c..5442ddf 100644
--- a/DeskThingServer/src/main/handlers/deviceHandler.ts
+++ b/DeskThingServer/src/main/handlers/deviceHandler.ts
@@ -1,10 +1,10 @@
import { sendIpcData } from '..'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import loggingStore from '../stores/loggingStore'
import { join } from 'path'
import * as fs from 'fs'
import { app, net } from 'electron'
import { handleAdbCommands } from './adbHandler'
-import { Client, ClientManifest, ReplyData, ReplyFn } from '@shared/types'
+import { Client, ClientManifest, MESSAGE_TYPES, ReplyData, ReplyFn } from '@shared/types'
import settingsStore from '../stores/settingsStore'
import { getLatestRelease } from './githubHandler'
@@ -17,14 +17,11 @@ export const HandleDeviceData = async (data: string): Promise => {
sendIpcData('version-status', deviceData)
break
default:
- console.log('Unhandled response', deviceData)
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'HandleDeviceData Unable to find device version')
break
}
} catch (Exception) {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- 'HandleDeviceData encountered the error ' + Exception
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'HandleDeviceData encountered the error ' + Exception)
}
}
@@ -34,7 +31,6 @@ export const getDeviceManifestVersion = async (deviceId: string): Promise {
@@ -254,7 +247,7 @@ export const HandlePushWebApp = async (
error: 'Client not found!',
final: false
})
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
'[HandlePushWebApp] Client Not Found! Ensure it is downloaded'
)
@@ -262,7 +255,6 @@ export const HandlePushWebApp = async (
}
let response
- console.log('Remounting...')
reply && reply('logging', { status: true, data: 'Remounting...', final: false })
response = await handleAdbCommands(`-s ${deviceId} shell mount -o remount,rw /`)
reply && reply('logging', { status: true, data: response || 'Writing to tmp...', final: false })
@@ -344,10 +336,7 @@ export const HandlePushWebApp = async (
error: `${Exception}`
})
}
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- 'HandlePushWebApp encountered the error ' + Exception
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'HandlePushWebApp encountered the error ' + Exception)
}
}
@@ -391,9 +380,7 @@ export const HandleWebappZipFromUrl = async (
// Optionally remove the temporary zip file
fs.unlinkSync(tempZipPath)
-
- console.log(`Successfully extracted ${zipFileUrl} to ${extractDir}`)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`Successfully extracted ${zipFileUrl} to ${extractDir}`
)
@@ -402,7 +389,7 @@ export const HandleWebappZipFromUrl = async (
reply && reply('logging', { status: true, data: 'Success!', final: false })
} catch (error) {
console.error('Error extracting zip file:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error extracting zip file: ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error extracting zip file: ${error}`)
// Notify failure to the frontend
reply &&
@@ -416,7 +403,7 @@ export const HandleWebappZipFromUrl = async (
})
response.on('error', (error) => {
console.error('Error downloading zip file:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error downloading zip file: ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error downloading zip file: ${error}`)
// Notify failure to the frontend
reply &&
@@ -430,7 +417,7 @@ export const HandleWebappZipFromUrl = async (
} else {
const errorMessage = `Failed to download zip file: ${response.statusCode}`
console.error(errorMessage)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, errorMessage)
+ loggingStore.log(MESSAGE_TYPES.ERROR, errorMessage)
// Notify failure to the frontend
reply &&
@@ -445,7 +432,7 @@ export const HandleWebappZipFromUrl = async (
request.on('error', (error) => {
console.error('Error sending request:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error sending request: ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error sending request: ${error}`)
// Notify failure to the frontend
reply &&
@@ -487,18 +474,12 @@ export const handleClientManifestUpdate = async (
// Write the updated manifest to the file
await fs.promises.writeFile(manifestPath, manifestContent, 'utf8')
- console.log('Manifest file updated successfully')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Manifest file updated successfully')
reply && reply('logging', { status: true, data: 'Manifest Updated!', final: false })
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- 'DEVICE HANDLER: Manifest file updated successfully'
- )
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'DEVICE HANDLER: Manifest file updated successfully')
} catch (error) {
console.error('Error updating manifest file:', error)
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- 'DEVICE HANDLER: Error updating manifest file: ' + error
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'DEVICE HANDLER: Error updating manifest file: ' + error)
}
}
@@ -512,14 +493,14 @@ export const checkForClient = async (
const manifestExists = fs.existsSync(manifestPath)
if (!manifestExists) {
- console.log('Manifest file not found')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Manifest file not found')
reply &&
reply('logging', {
status: false,
data: 'Manifest file not found',
final: false
})
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'DEVICE HANDLER: Manifest file not found')
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'DEVICE HANDLER: Manifest file not found')
}
return manifestExists
}
@@ -527,12 +508,12 @@ export const checkForClient = async (
export const getClientManifest = async (
reply?: (channel: string, data: ReplyData) => void
): Promise => {
- console.log('Getting manifest...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Getting manifest...')
const userDataPath = app.getPath('userData')
const manifestPath = join(userDataPath, 'webapp', 'manifest.js')
- console.log('manifestPath: ', manifestPath)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'manifestPath: ' + manifestPath)
if (!fs.existsSync(manifestPath)) {
- console.log('Manifest file not found')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Manifest file not found')
reply &&
reply('logging', {
status: false,
@@ -540,7 +521,7 @@ export const getClientManifest = async (
data: 'Manifest file not found',
final: false
})
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
'DEVICE HANDLER: Client is not detected or downloaded! Please download the client! (downloads -> client)'
)
@@ -567,12 +548,11 @@ export const getClientManifest = async (
data: 'Manifest loaded!',
final: false
})
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'DEVICE HANDLER: Manifest file read successfully')
- console.log(manifest)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'DEVICE HANDLER: Manifest file read successfully')
return manifest
} catch (error) {
console.error('Error reading or parsing manifest file:', error)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
'DEVICE HANDLER: Error reading or parsing manifest file: ' + error
)
@@ -623,7 +603,7 @@ export const SetupProxy = async (
final: false
})
- console.log('Remounting...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Remounting...')
reply('logging', { status: true, data: 'Remounting...', final: false })
response = await handleAdbCommands(`-s ${deviceId} shell mount -o remount,rw /`)
@@ -701,7 +681,7 @@ user=root`
final: false,
error: `${Exception}`
})
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'SetupProxy encountered the error ' + Exception)
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'SetupProxy encountered the error ' + Exception)
throw new Error('SetupProxy encountered the error ' + Exception)
}
}
@@ -815,10 +795,7 @@ export const AppendToSupervisor = async (
final: false,
error: `${Exception}`
})
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- 'AppendToSupervisor encountered the error ' + Exception
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'AppendToSupervisor encountered the error ' + Exception)
}
}
@@ -910,7 +887,7 @@ files = /etc/supervisor.d/*.conf\n`
final: false,
error: `${Exception}`
})
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
'EnsureSupervisorInclude encountered the error ' + Exception
)
diff --git a/DeskThingServer/src/main/handlers/firewallHandler.ts b/DeskThingServer/src/main/handlers/firewallHandler.ts
index 7924a3e..e97159e 100644
--- a/DeskThingServer/src/main/handlers/firewallHandler.ts
+++ b/DeskThingServer/src/main/handlers/firewallHandler.ts
@@ -1,10 +1,10 @@
import { exec } from 'child_process'
import os from 'os'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import loggingStore from '../stores/loggingStore'
import fs from 'fs'
import { join } from 'path'
import { app } from 'electron'
-import { ReplyFn } from '@shared/types'
+import { ReplyFn, MESSAGE_TYPES } from '@shared/types'
// Function to execute shell commands
function runCommand(command: string): Promise {
@@ -45,7 +45,7 @@ async function checkFirewallRuleExists(port: number): Promise {
const result = await runCommand(checkCommand)
return result.trim() === 'true'
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `FIREWALL: Unsupported OS!`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `FIREWALL: Unsupported OS!`)
console.error('Unsupported OS')
return false
}
@@ -65,15 +65,18 @@ async function setupFirewall(port: number, reply?: ReplyFn): Promise {
reply && reply('logging', { status: true, data: 'Checking if rules exist', final: false })
const ruleExists = await checkFirewallRuleExists(port)
if (ruleExists) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`FIREWALL: Firewall rule for port ${port} verified successfully`
)
- console.log(`Firewall rule for port ${port} verified successfully`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `Firewall rule for port ${port} verified successfully`
+ )
reply &&
reply('logging', { status: true, data: 'Verified that the rule exists!', final: false })
} else {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`FIREWALL: Failed to verify firewall rule for port ${port}!`
)
@@ -112,11 +115,11 @@ async function setupFirewall(port: number, reply?: ReplyFn): Promise {
try {
await runCommand(`powershell -ExecutionPolicy Bypass -File "${tempScriptPath}"`)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`FIREWALL: Firewall rules set up successfully on Windows`
)
- console.log('Firewall rules set up successfully on Windows')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Firewall rules set up successfully on Windows')
reply &&
reply('logging', { status: true, data: 'Firewall ran without error', final: false })
@@ -140,11 +143,11 @@ async function setupFirewall(port: number, reply?: ReplyFn): Promise {
`
await runCommand(`echo "${script}" | bash`)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`FIREWALL: Firewall rules set up successfully on Linux`
)
- console.log('Firewall rules set up successfully on Linux')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Firewall rules set up successfully on Linux')
} else if (platform === 'darwin') {
reply &&
reply('logging', {
@@ -165,16 +168,16 @@ async function setupFirewall(port: number, reply?: ReplyFn): Promise {
`
await runCommand(`echo "${script}" | bash`)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`FIREWALL: Firewall rules set up successfully on macOS`
)
- console.log('Firewall rules set up successfully on macOS')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Firewall rules set up successfully on macOS')
} else {
console.error('Unsupported OS')
}
} catch (error) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`FIREWALL: Error encountered trying to setup firewall for ${port}! Run administrator and try again`
)
diff --git a/DeskThingServer/src/main/handlers/githubHandler.ts b/DeskThingServer/src/main/handlers/githubHandler.ts
index 150f2f3..36792a0 100644
--- a/DeskThingServer/src/main/handlers/githubHandler.ts
+++ b/DeskThingServer/src/main/handlers/githubHandler.ts
@@ -11,12 +11,10 @@ export async function getLatestRelease(repoUrl: string): Promise
const owner = repoMatch[1]
const repo = repoMatch[2]
- console.log('Repo:', owner, repo)
const apiUrl = `https://api.github.com/repos/${owner}/${repo}/releases/latest`
const response = await fetch(apiUrl)
if (!response.ok) {
- console.log('HTTP error fetching the latest release! Response: ', response)
throw new Error(`HTTP error! status: ${response.status}`)
}
diff --git a/DeskThingServer/src/main/handlers/musicHandler.ts b/DeskThingServer/src/main/handlers/musicHandler.ts
index 5358764..2b4c6cd 100644
--- a/DeskThingServer/src/main/handlers/musicHandler.ts
+++ b/DeskThingServer/src/main/handlers/musicHandler.ts
@@ -1,8 +1,9 @@
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import loggingStore from '../stores/loggingStore'
import settingsStore from '../stores/settingsStore'
-import { Settings, SocketData } from '@shared/types'
+import { Settings, SocketData, MESSAGE_TYPES } from '@shared/types'
import { sendMessageToApp } from '../services/apps'
import { getAppByName } from './configHandler'
+import appState from '../services/apps/appState'
export class MusicHandler {
private static instance: MusicHandler
@@ -22,10 +23,13 @@ export class MusicHandler {
private async initializeRefreshInterval(): Promise {
const settings = await settingsStore.getSettings() // Get from your settings store
+ this.currentApp = settings.playbackLocation || 'none'
+
this.updateRefreshInterval(settings.refreshInterval)
- dataListener.on(MESSAGE_TYPES.SETTINGS, this.handleSettingsUpdate)
+ settingsStore.addListener(this.handleSettingsUpdate.bind(this))
setTimeout(() => {
+ loggingStore.log(MESSAGE_TYPES.DEBUG, '[MusicHandler]: Initialized')
this.refreshMusicData()
}, 5000) // Delay to ensure settings are loaded
}
@@ -33,12 +37,12 @@ export class MusicHandler {
private handleSettingsUpdate = (settings: Settings): void => {
this.updateRefreshInterval(settings.refreshInterval)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`[MusicHandler]: Received settings update - checking for changes | Playback location: ${this.currentApp} -> ${settings.playbackLocation}`
)
if (settings.playbackLocation) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`[MusicHandler]: Setting restarting to use ${settings.playbackLocation}`
)
@@ -53,7 +57,13 @@ export class MusicHandler {
}
if (refreshRate < 0) {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `[MusicHandler]: Cancelling Refresh Interval!`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `[MusicHandler]: Cancelling Refresh Interval!`)
+ return
+ } else if (refreshRate < 5) {
+ loggingStore.log(
+ MESSAGE_TYPES.WARNING,
+ `[MusicHandler]: Refresh Interval is ${refreshRate}! Performance may be impacted`
+ )
return
}
@@ -62,19 +72,66 @@ export class MusicHandler {
}, refreshRate)
}
- private async refreshMusicData(): Promise {
- if (!this.currentApp || this.currentApp.length == 0 || this.currentApp == 'none') {
+ private async findCurrentPlaybackSource(): Promise {
+ const Apps = appState.getAllBase()
+
+ const audioSource = Apps.find((app) => app.manifest?.isAudioSource)
+
+ if (audioSource) {
+ loggingStore.log(
+ MESSAGE_TYPES.WARNING,
+ `[MusicHandler]: Found ${audioSource.name} as an audio source automatically. Applying.`
+ )
+ return audioSource.name
+ } else {
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `[MusicHandler]: Unable to automatically set an audio source. No app found!`
+ )
+ return null
+ }
+ }
+
+ private async getPlaybackSource(): Promise {
+ if (this.currentApp == 'disabled') {
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `[MusicHandler]: Music is disabled! Cancelling refresh`
+ )
+ const settings = await settingsStore.getSettings()
+ if (settings.refreshInterval > 0) {
+ settingsStore.updateSetting('refreshInterval', -1)
+ }
+ return null
+ }
+
+ if (this.currentApp == 'none') {
+ const app = await this.findCurrentPlaybackSource()
+ if (app) {
+ this.currentApp = app
+ settingsStore.updateSetting('playbackLocation', app)
+ return app
+ } else {
+ loggingStore.log(
+ MESSAGE_TYPES.ERROR,
+ `[MusicHandler]: No Audiosource Found! Go to Downloads -> Apps and download an audio source! (Spotify, MediaWin, GMP, etc)`
+ )
+ return null
+ }
+ }
+
+ if (!this.currentApp || this.currentApp.length == 0) {
// Attempt to get audiosource from settings
const currentApp = (await settingsStore.getSettings()).playbackLocation
- if (!currentApp || currentApp.length == 0 || currentApp == 'none') {
- dataListener.asyncEmit(
+ if (!currentApp || currentApp.length == 0) {
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`[MusicHandler]: No playback location set! Go to settings -> Music to set the playback location!`
)
- return
+ return null
} else {
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
+ loggingStore.log(
+ MESSAGE_TYPES.WARNING,
`[MusicHandler]: Playback location was not set! Setting to ${currentApp}`
)
this.currentApp = currentApp
@@ -84,29 +141,40 @@ export class MusicHandler {
const app = await getAppByName(this.currentApp)
if (!app || app.running == false) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`[MusicHandler]: App ${this.currentApp} is not found or not running!`
)
+ return null
+ }
+
+ return this.currentApp
+ }
+
+ private async refreshMusicData(): Promise {
+ const currentApp = await this.getPlaybackSource()
+
+ if (!currentApp) {
+ return
}
try {
- await sendMessageToApp(this.currentApp, { type: 'get', request: 'refresh', payload: '' })
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `[MusicHandler]: Refreshing Music Data!`)
+ await sendMessageToApp(currentApp, { type: 'get', request: 'refresh', payload: '' })
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `[MusicHandler]: Refreshing Music Data!`)
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `[MusicHandler]: Music refresh failed: ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `[MusicHandler]: Music refresh failed: ${error}`)
}
}
public async setAudioSource(source: string): Promise {
if (source.length == 0) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`[MusicHandler]: Unable to update playback location. No playback location passed!`
)
return
}
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`[MusicHandler]: Setting Playback Location to ${source}`
)
@@ -114,40 +182,24 @@ export class MusicHandler {
}
public async handleClientRequest(request: SocketData): Promise {
- if (!this.currentApp) {
- const settings = await settingsStore.getSettings()
- if (settings.playbackLocation) {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `[MusicHandler]: No playback location set!`)
- this.currentApp = settings.playbackLocation
- } else {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `[MusicHandler]: No playback location set!`)
- return
- }
- }
+ const currentApp = await this.getPlaybackSource()
- if (this.currentApp == 'none') {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- `[MusicHandler]: Playback location is 'none' ! Go to settings -> Music to set the playback location!`
- )
+ if (!currentApp) {
return
}
if (request.app != 'music' && request.app != 'utility') return
if (request.app == 'utility') {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`[MusicHandler]: Legacy Name called! Support for this will be dropped in future updates. Migrate your app to use 'music' instead!`
)
}
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- `[MusicHandler]: ${request.type} ${request.request}`
- )
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `[MusicHandler]: ${request.type} ${request.request}`)
- sendMessageToApp(this.currentApp, {
+ sendMessageToApp(currentApp, {
type: request.type,
request: request.request,
payload: request.payload
diff --git a/DeskThingServer/src/main/handlers/utilityHandler.ts b/DeskThingServer/src/main/handlers/utilityHandler.ts
index 53b64fa..2efb75a 100644
--- a/DeskThingServer/src/main/handlers/utilityHandler.ts
+++ b/DeskThingServer/src/main/handlers/utilityHandler.ts
@@ -1,13 +1,20 @@
-import { ButtonMapping, Client, GithubRelease, Settings } from '@shared/types'
-import { ReplyFn, UtilityIPCData } from '@shared/types/ipcTypes'
+import {
+ ReplyFn,
+ UtilityIPCData,
+ ButtonMapping,
+ Client,
+ MESSAGE_TYPES,
+ GithubRelease,
+ Log,
+ Settings
+} from '@shared/types'
import ConnectionStore from '../stores/connectionsStore'
import settingsStore from '../stores/settingsStore'
import { getReleases } from './githubHandler'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import loggingStore from '../stores/loggingStore'
import path from 'path'
import { shell, app, dialog } from 'electron'
import keyMapStore from '../stores/keyMapStore'
-import logger from '../utils/logger'
import { setupFirewall } from './firewallHandler'
import { disconnectClient } from '../services/client/clientCom'
import { restartServer } from '../services/client/websocket'
@@ -18,11 +25,19 @@ export const utilityHandler: Record<
data: UtilityIPCData,
replyFn: ReplyFn
) => Promise<
- void | string | Client[] | boolean | string[] | Settings | GithubRelease[] | ButtonMapping
+ | void
+ | string
+ | Client[]
+ | boolean
+ | string[]
+ | Settings
+ | GithubRelease[]
+ | ButtonMapping
+ | Log[]
>
> = {
ping: async () => {
- console.log('Pinged! pong')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Pinged! pong')
return 'pong'
},
zip: async (data): Promise => {
@@ -63,14 +78,18 @@ export const utilityHandler: Record<
try {
return await getReleases(data.payload)
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, error)
+ if (error instanceof Error) {
+ loggingStore.log(MESSAGE_TYPES.ERROR, error.message)
+ } else {
+ loggingStore.log(MESSAGE_TYPES.ERROR, String(error))
+ }
return []
}
},
logs: async (data) => {
switch (data.request) {
case 'get':
- return await logger.getLogs()
+ return await loggingStore.getLogs()
default:
return
}
@@ -132,14 +151,13 @@ const refreshFirewall = async (replyFn: ReplyFn): Promise => {
replyFn('logging', { status: true, data: 'Refreshing Firewall', final: false })
const payload = (await settingsStore.getSettings()) as Settings
if (payload) {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, '[firewall] Setting up firewall')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, '[firewall] Setting up firewall')
try {
await setupFirewall(payload.devicePort, replyFn)
} catch (firewallError) {
- console.log(firewallError)
if (!(firewallError instanceof Error)) return
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `FIREWALL: ${firewallError.message}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `FIREWALL: ${firewallError.message}`)
replyFn('logging', {
status: false,
data: 'Error in firewall',
@@ -149,7 +167,7 @@ const refreshFirewall = async (replyFn: ReplyFn): Promise => {
return
}
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, '[firewall] No settings found!')
+ loggingStore.log(MESSAGE_TYPES.ERROR, '[firewall] No settings found!')
replyFn('logging', {
status: false,
data: 'Error in firewall',
@@ -158,7 +176,7 @@ const refreshFirewall = async (replyFn: ReplyFn): Promise => {
})
}
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'SERVER: [firewall] Error saving manifest' + error)
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'SERVER: [firewall] Error saving manifest' + error)
console.error('[Firewall] Error setting client manifest:', error)
if (error instanceof Error) {
replyFn('logging', { status: false, data: 'Unfinished', error: error.message, final: true })
diff --git a/DeskThingServer/src/main/index.ts b/DeskThingServer/src/main/index.ts
index d5c6504..08dfa4c 100644
--- a/DeskThingServer/src/main/index.ts
+++ b/DeskThingServer/src/main/index.ts
@@ -1,4 +1,4 @@
-import { AppIPCData, AuthScopes, Client, UtilityIPCData } from '@shared/types'
+import { AppIPCData, AuthScopes, Client, UtilityIPCData, MESSAGE_TYPES } from '@shared/types'
import { app, shell, BrowserWindow, ipcMain, Tray, Menu, nativeImage } from 'electron'
import { join, resolve } from 'path'
import icon from '../../resources/icon.png?asset'
@@ -213,17 +213,16 @@ async function initializeDoc(): Promise {
}
async function setupIpcHandlers(): Promise {
- const dataListener = (await import('./utils/events')).default
- const { MESSAGE_TYPES } = await import('./utils/events')
+ const loggingStore = (await import('./stores/loggingStore')).default
const { appHandler } = await import('./handlers/appHandler')
const { clientHandler } = await import('./handlers/clientHandler')
const { utilityHandler } = await import('./handlers/utilityHandler')
- const { ResponseLogger } = await import('./utils/events')
+ const { ResponseLogger } = await import('./stores/loggingStore')
const defaultHandler = async (data: AppIPCData): Promise => {
console.error(`No handler implemented for type: ${data.type} ${data}`)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `No handler implemented for type: ${data.type}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `No handler implemented for type: ${data.type}`)
}
ipcMain.handle('APPS', async (event, data: AppIPCData) => {
@@ -238,7 +237,7 @@ async function setupIpcHandlers(): Promise {
}
} catch (error) {
console.error('Error in IPC handler:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error in IPC handler: ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error in IPC handler: ${error}`)
}
})
@@ -254,12 +253,11 @@ async function setupIpcHandlers(): Promise {
}
} catch (error) {
console.error('Error in IPC handler:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error in IPC handler: ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error in IPC handler: ${error}`)
}
})
ipcMain.handle('UTILITY', async (event, data: UtilityIPCData) => {
- console.log('Received IPC data:', data)
const handler = utilityHandler[data.type] || defaultHandler
const replyFn = ResponseLogger(event.sender.send.bind(event.sender))
@@ -272,19 +270,13 @@ async function setupIpcHandlers(): Promise {
}
} catch (error) {
console.error('Error in IPC handler:', error)
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error in IPC handler: ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error in IPC handler: ${error}`)
}
})
- dataListener.on(MESSAGE_TYPES.ERROR, (errorData) => {
- sendIpcData('error', errorData)
- })
- dataListener.on(MESSAGE_TYPES.LOGGING, (errorData) => {
+ loggingStore.addListener((errorData) => {
sendIpcData('log', errorData)
})
- dataListener.on(MESSAGE_TYPES.MESSAGE, (errorData) => {
- sendIpcData('message', errorData)
- })
ConnectionStore.on((clients: Client[]) => {
sendIpcData('connections', { status: true, data: clients.length, final: true })
sendIpcData('clients', { status: true, data: clients, final: true })
@@ -292,7 +284,7 @@ async function setupIpcHandlers(): Promise {
ConnectionStore.onDevice((devices: string[]) => {
sendIpcData('adbdevices', { status: true, data: devices, final: true })
})
- dataListener.on(MESSAGE_TYPES.SETTINGS, (newSettings) => {
+ settingsStore.addListener((newSettings) => {
sendIpcData('settings-updated', newSettings)
})
}
@@ -367,8 +359,6 @@ function handleUrl(url: string | undefined): void {
if (url && url.startsWith('deskthing://')) {
const path = url.replace('deskthing://', '')
- console.log('Handling URL:', url, path)
-
if (mainWindow) {
mainWindow.webContents.send('handle-protocol-url', path)
}
diff --git a/DeskThingServer/src/main/services/apps/appCommunication.ts b/DeskThingServer/src/main/services/apps/appCommunication.ts
index 818e287..fea4749 100644
--- a/DeskThingServer/src/main/services/apps/appCommunication.ts
+++ b/DeskThingServer/src/main/services/apps/appCommunication.ts
@@ -1,6 +1,6 @@
import { openAuthWindow, sendIpcAuthMessage } from '../..'
-import { AuthScopes, IncomingData, Key, Action, ToClientType } from '@shared/types'
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
+import { AuthScopes, MESSAGE_TYPES, IncomingData, Key, Action, ToClientType } from '@shared/types'
+import loggingStore from '../../stores/loggingStore'
import { ipcMain } from 'electron'
/**
@@ -18,7 +18,7 @@ export async function handleDataFromApp(app: string, appData: IncomingData): Pro
switch (appData.type) {
case 'message':
- dataListener.asyncEmit(MESSAGE_TYPES.MESSAGE, appData.payload)
+ loggingStore.log(MESSAGE_TYPES.MESSAGE, appData.payload, app.toUpperCase())
break
case 'get':
switch (appData.request) {
@@ -67,7 +67,7 @@ export async function handleDataFromApp(app: string, appData: IncomingData): Pro
if (appData.payload && appData.request) {
sendMessageToApp(appData.request, appData.payload)
} else {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`${app.toUpperCase()}: App data malformed`,
appData.payload
@@ -75,10 +75,10 @@ export async function handleDataFromApp(app: string, appData: IncomingData): Pro
}
break
case 'error':
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `${app.toUpperCase()}: ${appData.payload}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `${appData.payload}`, app.toUpperCase())
break
case 'log':
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `${app.toUpperCase()}: ${appData.payload}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `${appData.payload}`, app.toUpperCase())
break
case 'button':
if (appData.request == 'add') {
@@ -93,13 +93,13 @@ export async function handleDataFromApp(app: string, appData: IncomingData): Pro
Modes: appData.payload.Modes || []
}
keyMapStore.addKey(Key)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`${app.toUpperCase()}: Added Button Successfully`
)
}
} catch (Error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `${app.toUpperCase()}: ${Error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `${app.toUpperCase()}: ${Error}`)
}
} else if (appData.request == 'remove') {
keyMapStore.removeKey(appData.payload.id)
@@ -122,13 +122,13 @@ export async function handleDataFromApp(app: string, appData: IncomingData): Pro
source: app
}
keyMapStore.addAction(Action)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`${app.toUpperCase()}: Added Action Successfully`
)
}
} catch (Error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `${app.toUpperCase()}: ${Error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `${app.toUpperCase()}: ${Error}`)
}
break
case 'remove':
@@ -172,7 +172,7 @@ export async function requestUserInput(appName: string, scope: AuthScopes): Prom
export async function sendMessageToApp(appName: string, data: IncomingData): Promise {
const { AppHandler } = await import('./appState')
const appHandler = AppHandler.getInstance()
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`[sendMessageToApp] Sending message to ${appName} with ${data.type}`
)
@@ -181,7 +181,7 @@ export async function sendMessageToApp(appName: string, data: IncomingData): Pro
if (app && typeof app.func.toClient === 'function') {
;(app.func.toClient as ToClientType)(data)
} else {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`SERVER: App ${appName} not found or does not have toClient function. (is it running?)`
)
diff --git a/DeskThingServer/src/main/services/apps/appInstaller.ts b/DeskThingServer/src/main/services/apps/appInstaller.ts
index e946330..c10fe03 100644
--- a/DeskThingServer/src/main/services/apps/appInstaller.ts
+++ b/DeskThingServer/src/main/services/apps/appInstaller.ts
@@ -1,13 +1,14 @@
import { join, resolve } from 'path'
import { app } from 'electron'
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
+import loggingStore from '../../stores/loggingStore'
import {
IncomingData,
ToClientType,
Response,
Manifest,
DeskThing,
- AppReturnData
+ AppReturnData,
+ MESSAGE_TYPES
} from '@shared/types'
import { getAppFilePath, getManifest } from './appUtils'
import { mkdirSync, existsSync, rmSync, promises } from 'node:fs'
@@ -29,11 +30,14 @@ import { handleDataFromApp } from './appCommunication'
export async function handleZip(zipFilePath: string, reply?): Promise {
const { getManifest } = await import('./appUtils')
try {
- console.log(`[handleZip] Extracting ${zipFilePath}...`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `[handleZip] Extracting ${zipFilePath}...`)
const appPath = join(app.getPath('userData'), 'apps') // Extract to user data folder
// Create the extraction directory if it doesn't exist
if (!existsSync(appPath)) {
- console.log(`[handleZip] Creating extraction directory at ${appPath}...`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `[handleZip] Creating extraction directory at ${appPath}...`
+ )
mkdirSync(appPath, { recursive: true })
}
@@ -42,7 +46,10 @@ export async function handleZip(zipFilePath: string, reply?): Promise((resolve, reject) => {
try {
- console.log(`[handleZip] Extracting app...`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `[handleZip] Extracting app...`)
const zip = new AdmZip.default(zipFilePath)
zip.getEntries().forEach((entry) => {
if (entry.isDirectory) {
- console.log(`[handleZip] Skipping directory ${entry.entryName}`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `[handleZip] Skipping directory ${entry.entryName}`
+ )
} else {
- console.log(`[handleZip] Extracting file ${entry.entryName}`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `[handleZip] Extracting file ${entry.entryName}`
+ )
zip.extractEntryTo(entry, tempDir, true, true)
}
})
zip.extractAllTo(tempDir, true)
- console.log(`[handleZip] App extracted to ${tempDir}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `[handleZip] App extracted to ${tempDir}`)
resolve()
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `SERVER: Error extracting ${zipFilePath}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `SERVER: Error extracting ${zipFilePath}`)
reply && reply('logging', { status: false, data: 'Extraction failed!', final: true })
reject(error)
}
@@ -80,12 +93,9 @@ export async function handleZip(zipFilePath: string, reply?): Promise {
if (app && typeof app.func.start === 'function') {
app.func.start()
} else {
- console.log(`App ${appName} not found.`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `App ${appName} not found.`)
}
const DeskThing = await getDeskThing(appName)
@@ -270,17 +280,17 @@ export async function run(appName: string): Promise {
appState.appendManifest(manifest, appName)
}
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `Configuring ${appName}!`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `Configuring ${appName}!`)
await setupFunctions(appName, DeskThing)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `Running ${appName}!`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `Running ${appName}!`)
const result = await start(appName)
if (!result) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `App ${appName} failed to start!`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `App ${appName} failed to start!`)
}
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error running app ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error running app ${error}`)
console.error('Error running app:', error)
}
}
@@ -296,17 +306,14 @@ export const start = async (appName: string): Promise => {
const appInstance = appState.get(appName)
if (!appInstance || !appInstance.func.start || appInstance.func.start === undefined) {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- `App ${appName} not found. or not started correctly`
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, `App ${appName} not found. or not started correctly`)
return false
}
// Check if all required apps are running
const manifest = appInstance.manifest
if (!manifest) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `App ${appName} not found.`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `App ${appName} not found.`)
return false
}
@@ -314,7 +321,7 @@ export const start = async (appName: string): Promise => {
const requiredApps = manifest.requires || []
for (const requiredApp of requiredApps) {
if (!appState.getOrder().includes(requiredApp) && requiredApp.length > 2) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`Unable to run ${appName}! This app requires '${requiredApp}' to be enabled and running.`
)
@@ -327,20 +334,20 @@ export const start = async (appName: string): Promise => {
try {
const startResponse: Response = await appInstance.func.start()
if (startResponse.status == 200) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.MESSAGE,
`App ${appName} started successfully with response ${startResponse.data.message}`
)
return true
} else {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`App ${appName} failed to start with response ${startResponse.data.message}`
)
return false
}
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `Error starting app ${error}`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `Error starting app ${error}`)
console.error('Error starting app:', error)
}
return false
@@ -360,7 +367,7 @@ const setupFunctions = async (appName: string, DeskThing: DeskThing): Promise => {
return DeskThing.start({
toServer: (data) => handleDataFromApp(appName, data),
- SysEvents: (event: string, listener: (...args: string[]) => void) => {
- dataListener.on(event, listener) // Add event listener
- return () => dataListener.removeListener(event, listener)
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ SysEvents: (_event: string, _listener: (...args: string[]) => void) => {
+ return () => {
+ /* do something with this to let apps listen for server events like apps being added or settings being changed */
+ }
}
})
}
@@ -386,7 +395,7 @@ const setupFunctions = async (appName: string, DeskThing: DeskThing): Promise => {
} else if (existsSync(appEntryPointCjs)) {
appEntryPoint = appEntryPointCjs
} else {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`Entry point for app ${appName} not found. (Does it have an index.js file?)`
)
diff --git a/DeskThingServer/src/main/services/apps/appManager.ts b/DeskThingServer/src/main/services/apps/appManager.ts
index 5df36a6..8e1a3ca 100644
--- a/DeskThingServer/src/main/services/apps/appManager.ts
+++ b/DeskThingServer/src/main/services/apps/appManager.ts
@@ -1,6 +1,6 @@
import { rmSync, readdirSync, statSync, existsSync } from 'node:fs'
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
-
+import loggingStore from '../../stores/loggingStore'
+import { MESSAGE_TYPES } from '@shared/types'
export async function clearCache(appName: string): Promise {
try {
const { join } = await import('path')
@@ -21,24 +21,41 @@ export async function clearCache(appName: string): Promise {
const resolvedPath = require.resolve(itemPath)
if (require.cache[resolvedPath]) {
delete require.cache[resolvedPath]
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- `SERVER: Removed ${resolvedPath} from cache`
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `SERVER: Removed ${resolvedPath} from cache`)
+ } else {
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `SERVER: ${resolvedPath} not in cache!`)
+ }
+ } catch (error) {
+ if (error instanceof Error) {
+ loggingStore.log(
+ MESSAGE_TYPES.ERROR,
+ `SERVER: Error clearing cache for ${itemPath}:`,
+ error.message
)
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `SERVER: ${resolvedPath} not in cache!`)
+ loggingStore.log(
+ MESSAGE_TYPES.ERROR,
+ `SERVER: Error clearing cache for ${itemPath}:`,
+ String(error)
+ )
}
- } catch (e) {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `SERVER: clearCache Error`, e)
}
}
})
} catch (error) {
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- `SERVER: Error clearing cache for directory ${appName}:`,
- error
- )
+ if (error instanceof Error) {
+ loggingStore.log(
+ MESSAGE_TYPES.ERROR,
+ `SERVER: Error clearing cache for directory ${appName}:`,
+ error.message
+ )
+ } else {
+ loggingStore.log(
+ MESSAGE_TYPES.ERROR,
+ `SERVER: Error clearing cache for directory ${appName}:`,
+ String(error)
+ )
+ }
}
}
@@ -49,7 +66,7 @@ export async function clearCache(appName: string): Promise {
*/
export async function purgeApp(appName: string): Promise {
try {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `SERVER: Purging App ${appName}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `SERVER: Purging App ${appName}`)
const { purgeAppData } = await import('../../handlers/dataHandler')
const { purgeAppConfig } = await import('../../handlers/configHandler')
@@ -74,9 +91,9 @@ export async function purgeApp(appName: string): Promise {
// Remove the file from filesystem
if (existsSync(dir)) {
await rmSync(dir, { recursive: true, force: true })
- console.log(`Purged all data for app ${appName}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `Purged all data for app ${appName}`)
}
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `SERVER: Purged App ${appName}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `SERVER: Purged App ${appName}`)
} catch (error) {
console.error(`Error purging app data for ${appName}`, error)
}
diff --git a/DeskThingServer/src/main/services/apps/appRunner.ts b/DeskThingServer/src/main/services/apps/appRunner.ts
index 9d279db..627ce12 100644
--- a/DeskThingServer/src/main/services/apps/appRunner.ts
+++ b/DeskThingServer/src/main/services/apps/appRunner.ts
@@ -1,4 +1,5 @@
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
+import loggingStore from '../../stores/loggingStore'
+import { MESSAGE_TYPES } from '@shared/types'
/**
* Loads and runs all enabled apps from appData.json
@@ -12,12 +13,12 @@ export async function loadAndRunEnabledApps(): Promise {
try {
const appInstances = appHandler.getAll()
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'SERVER: Loaded apps config. Running apps...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'SERVER: Loaded apps config. Running apps...')
const enabledApps = appInstances.filter((appConfig) => appConfig.enabled === true)
await Promise.all(
enabledApps.map(async (appConfig) => {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`SERVER: Automatically running app ${appConfig.name}`
)
@@ -29,15 +30,12 @@ export async function loadAndRunEnabledApps(): Promise {
await Promise.all(
failedApps.map(async (failedApp) => {
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- `SERVER: Attempting to run ${failedApp.name} again`
- )
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `SERVER: Attempting to run ${failedApp.name} again`)
await appHandler.run(failedApp.name)
})
)
} catch (error) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`SERVER: Error loading and running enabled apps: ${error}`
)
diff --git a/DeskThingServer/src/main/services/apps/appState.ts b/DeskThingServer/src/main/services/apps/appState.ts
index 8707363..2eeae63 100644
--- a/DeskThingServer/src/main/services/apps/appState.ts
+++ b/DeskThingServer/src/main/services/apps/appState.ts
@@ -1,7 +1,6 @@
-import { App, AppInstance, Manifest, AppReturnData } from '@shared/types'
+import { App, AppInstance, Manifest, AppReturnData, MESSAGE_TYPES } from '@shared/types'
import { sendConfigData, sendSettingsData } from '../client/clientCom'
-import settingsStore from '../../stores/settingsStore'
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
+import loggingStore from '../../stores/loggingStore'
/**
* TODO: Sync with the file
@@ -34,7 +33,7 @@ export class AppHandler {
* Loads the apps from file
*/
async loadApps(): Promise {
- console.log('[appState] [loadApps]: Loading apps...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, '[appState] [loadApps]: Loading apps...')
const { getAppData } = await import('../../handlers/configHandler')
const data = await getAppData()
@@ -302,20 +301,6 @@ export class AppHandler {
// Add the manifest to the config file
addAppManifest(manifest, appName)
this.saveAppToFile(appName)
-
- const checkForSettings = async (): Promise => {
- const settings = await settingsStore.getSettings()
- const playbackLocation = settings.playbackLocation
- if (playbackLocation === 'none' || !playbackLocation) {
- settingsStore.updateSetting('playbackLocation', appName)
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- '[appState][addAppManifest]: Setting playbackLocation to ' + appName
- )
- }
- }
-
- checkForSettings()
}
}
diff --git a/DeskThingServer/src/main/services/apps/appUtils.ts b/DeskThingServer/src/main/services/apps/appUtils.ts
index 3999ffa..272249d 100644
--- a/DeskThingServer/src/main/services/apps/appUtils.ts
+++ b/DeskThingServer/src/main/services/apps/appUtils.ts
@@ -1,7 +1,7 @@
-import { Manifest } from '@shared/types'
+import { Manifest, MESSAGE_TYPES } from '@shared/types'
import { join } from 'path'
import { existsSync, promises } from 'node:fs'
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
+import loggingStore from '../../stores/loggingStore'
import { app } from 'electron'
let devAppPath: string
@@ -16,7 +16,7 @@ let devAppPath: string
*/
export async function getManifest(fileLocation: string): Promise {
try {
- console.log('[getManifest] Getting manifest for app')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, '[getManifest] Getting manifest for app')
const manifestPath = join(fileLocation, 'manifest.json')
if (!existsSync(manifestPath)) {
throw new Error('manifest.json not found after extraction')
@@ -39,7 +39,7 @@ export async function getManifest(fileLocation: string): Promise => {
- console.log(`Sending message to clients: ${JSON.stringify(data)}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `Sending message to clients: ${JSON.stringify(data)}`)
if (server) {
server.clients.forEach((client) => {
if (client.readyState === 1) {
@@ -15,7 +15,7 @@ export const sendMessageToClients = async (data: SocketData): Promise => {
}
})
} else {
- dataListener.emit(MESSAGE_TYPES.LOGGING, 'WSOCKET: No server running - setting one up')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: No server running - setting one up')
}
}
@@ -25,10 +25,13 @@ export const disconnectClient = (connectionId: string): void => {
if (client && server) {
client.socket.terminate()
Clients.splice(Clients.indexOf(client), 1)
- console.log(`Forcibly disconnected client: ${connectionId}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `Forcibly disconnected client: ${connectionId}`)
connectionsStore.removeClient(connectionId)
} else {
- console.log(`Client not found or server not running: ${connectionId}`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `Client not found or server not running: ${connectionId}`
+ )
}
}
@@ -58,7 +61,7 @@ export const sendConfigData = async (clientId?: string): Promise => {
sendMessageToClient(clientId, { app: 'client', type: 'config', payload: filteredAppData })
- console.log('WSOCKET: Preferences sent!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: Preferences sent!')
} catch (error) {
console.error('WSOCKET: Error getting config data:', error)
sendError(clientId, 'WSOCKET: Error getting config data')
@@ -89,7 +92,7 @@ export const sendSettingsData = async (clientId?: string): Promise => {
}
sendMessageToClient(clientId, { app: 'client', type: 'settings', payload: settings })
- console.log('WSOCKET: Preferences sent!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: Preferences sent!')
} catch (error) {
console.error('WSOCKET: Error getting config data:', error)
sendError(clientId, 'WSOCKET: Error getting config data')
@@ -102,8 +105,8 @@ export const sendMappings = async (clientId?: string): Promise => {
sendMessageToClient(clientId, { app: 'client', type: 'button_mappings', payload: mappings })
- console.log('WSOCKET: Button mappings sent!')
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Client has been sent button maps!`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: Button mappings sent!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Client has been sent button maps!`)
} catch (error) {
console.error('WSOCKET: Error getting button mappings:', error)
sendError(clientId, 'WSOCKET: Error getting button mappings')
diff --git a/DeskThingServer/src/main/services/client/clientUtils.ts b/DeskThingServer/src/main/services/client/clientUtils.ts
index 67a4cf1..f84c693 100644
--- a/DeskThingServer/src/main/services/client/clientUtils.ts
+++ b/DeskThingServer/src/main/services/client/clientUtils.ts
@@ -30,7 +30,6 @@ export const sendTime = async (): Promise => {
const formattedMinutes = minutes < 10 ? '0' + minutes : minutes
const time = `${formattedHours}:${formattedMinutes} ${ampm}`
sendMessageToClients({ app: 'client', type: 'time', payload: time })
- console.log(time)
}
const initializeTimer = async (): Promise => {
diff --git a/DeskThingServer/src/main/services/client/expressServer.ts b/DeskThingServer/src/main/services/client/expressServer.ts
index 9cd4cf4..4b4101b 100644
--- a/DeskThingServer/src/main/services/client/expressServer.ts
+++ b/DeskThingServer/src/main/services/client/expressServer.ts
@@ -1,4 +1,5 @@
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
+import loggingStore from '../../stores/loggingStore'
+import { MESSAGE_TYPES } from '@shared/types'
import { app as electronApp } from 'electron'
import { join } from 'path'
import { getAppFilePath } from '../apps'
@@ -24,11 +25,14 @@ export const setupExpressServer = async (expressApp: express.Application): Promi
): void => {
const userDataPath = electronApp.getPath('userData')
const webAppDir = join(userDataPath, 'webapp')
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${webAppDir}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${webAppDir}`)
const clientIp = req.hostname
- console.log(`WEBSOCKET: Serving ${appName} from ${webAppDir} to ${clientIp}`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `WEBSOCKET: Serving ${appName} from ${webAppDir} to ${clientIp}`
+ )
try {
if (req.path.endsWith('manifest.js')) {
const manifestPath = join(webAppDir, 'manifest.js')
@@ -71,7 +75,7 @@ export const setupExpressServer = async (expressApp: express.Application): Promi
handleClientConnection(appName, req, res, next)
} else {
const appPath = getAppFilePath(appName)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${appPath}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${appPath}`)
if (fs.existsSync(appPath)) {
express.static(appPath)(req, res, next)
@@ -87,7 +91,7 @@ export const setupExpressServer = async (expressApp: express.Application): Promi
const appName = req.params.appName
if (iconName != null) {
const appPath = getAppFilePath(appName)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${appPath}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${appPath}`)
if (fs.existsSync(join(appPath, 'icons', iconName))) {
express.static(join(appPath, 'icons'))(req, res, next)
@@ -103,7 +107,7 @@ export const setupExpressServer = async (expressApp: express.Application): Promi
const appName = req.params.appName
if (imageName != null) {
const appPath = getAppFilePath(appName)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${appPath}`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Serving ${appName} from ${appPath}`)
if (fs.existsSync(join(appPath, 'images', imageName))) {
express.static(join(appPath, 'icons'))(req, res, next)
@@ -117,10 +121,7 @@ export const setupExpressServer = async (expressApp: express.Application): Promi
expressApp.use('/fetch/:url(*)', async (req, res) => {
try {
const url = decodeURIComponent(req.params.url)
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- `WEBSOCKET: Fetching external resource from ${url}`
- )
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Fetching external resource from ${url}`)
const response = await fetch(url)
const contentType = response.headers.get('content-type')
@@ -133,7 +134,7 @@ export const setupExpressServer = async (expressApp: express.Application): Promi
}
} catch (error) {
if (error instanceof Error) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`WEBSOCKET: Error fetching external resource: ${error.message}`
)
diff --git a/DeskThingServer/src/main/services/client/websocket.ts b/DeskThingServer/src/main/services/client/websocket.ts
index d5b1cca..592ad86 100644
--- a/DeskThingServer/src/main/services/client/websocket.ts
+++ b/DeskThingServer/src/main/services/client/websocket.ts
@@ -1,7 +1,14 @@
import WebSocket, { WebSocketServer } from 'ws'
import { createServer, Server as HttpServer, IncomingMessage } from 'http'
-import dataListener, { MESSAGE_TYPES } from '../../utils/events'
-import { AppDataInterface, Client, ClientManifest, Settings, SocketData } from '@shared/types'
+import loggingStore from '../../stores/loggingStore'
+import {
+ AppDataInterface,
+ MESSAGE_TYPES,
+ Client,
+ ClientManifest,
+ Settings,
+ SocketData
+} from '@shared/types'
import { addData } from '../../handlers/dataHandler'
import { HandleDeviceData } from '../../handlers/deviceHandler'
import settingsStore from '../../stores/settingsStore'
@@ -36,8 +43,8 @@ const THROTTLE_DELAY = 100 // milliseconds
export const restartServer = async (): Promise => {
try {
if (server) {
- console.log('WSOCKET: Shutting down the WebSocket server...')
- dataListener.emit(MESSAGE_TYPES.LOGGING, 'WSOCKET: Shutting down the WebSocket server...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: Shutting down the WebSocket server...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: Shutting down the WebSocket server...')
ConnectionStore.removeAllClients()
server.clients.forEach((client) => {
@@ -47,25 +54,28 @@ export const restartServer = async (): Promise => {
server.close((err) => {
if (err) {
console.error('WSOCKET: Error shutting down WebSocket server:', err)
- dataListener.emit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
'WSOCKET: Error shutting down WebSocket server:' + err
)
} else {
- console.log('WSOCKET: WebSocket server shut down successfully.')
- dataListener.emit(
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ 'WSOCKET: WebSocket server shut down successfully.'
+ )
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
'WSOCKET: WebSocket server shut down successfully.'
)
}
if (httpServer && httpServer.listening) {
- console.log('WSOCKET: Stopping HTTP server...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: Stopping HTTP server...')
httpServer.close((err) => {
if (err) {
console.error('WSOCKET: Error stopping HTTP server:', err)
} else {
- console.log('WSOCKET: HTTP server stopped successfully.')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: HTTP server stopped successfully.')
setupServer()
}
})
@@ -74,14 +84,17 @@ export const restartServer = async (): Promise => {
}
})
} else {
- console.log('WSOCKET: No WebSocket server running - setting one up')
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ 'WSOCKET: No WebSocket server running - setting one up'
+ )
if (httpServer && httpServer.listening) {
- console.log('WSOCKET: Stopping HTTP server...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: Stopping HTTP server...')
httpServer.close((err) => {
if (err) {
console.error('WSOCKET: Error stopping HTTP server:', err)
} else {
- console.log('WSOCKET: HTTP server stopped successfully.')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: HTTP server stopped successfully.')
setupServer()
}
})
@@ -95,7 +108,7 @@ export const restartServer = async (): Promise => {
}
export const setupServer = async (): Promise => {
- dataListener.asyncEmit(MESSAGE_TYPES.MESSAGE, 'WSOCKET: Attempting to setup the server')
+ loggingStore.log(MESSAGE_TYPES.MESSAGE, 'WSOCKET: Attempting to setup the server')
if (!currentPort || !currentAddress) {
const settings = await settingsStore.getSettings()
@@ -112,11 +125,10 @@ export const setupServer = async (): Promise => {
server = new WebSocketServer({ server: httpServer })
- console.log('WSOCKET: WebSocket server is running.')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: WebSocket server is running.')
httpServer.listen(currentPort, currentAddress, () => {
- console.log(`CALLBACK: Server listening on ${currentAddress}:${currentPort}`)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`WEBSOCKET: Server is listening on ${currentAddress}:${currentPort}`
)
@@ -130,7 +142,10 @@ export const setupServer = async (): Promise => {
const clientIp = socket._socket.remoteAddress
// Setup the initial client data
- console.log(`WSOCKET: Client connected! Looking for client with IP ${clientIp}`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `WSOCKET: Client connected! Looking for client with IP ${clientIp}`
+ )
// Local client that is the true source of truth for the device details
const client: Client = {
@@ -145,13 +160,17 @@ export const setupServer = async (): Promise => {
Clients.push({ client, socket })
- console.log(
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
`WSOCKET: Client with id: ${client.connectionId} connected!\nWSOCKET: Sending preferences...`
)
ConnectionStore.addClient(client)
- console.log('WSOCKET: Client connected!\nWSOCKET: Sending preferences...')
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Sending client preferences...`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ 'WSOCKET: Client connected!\nWSOCKET: Sending preferences...'
+ )
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `WEBSOCKET: Sending client preferences...`)
sendConfigData(client.connectionId)
sendSettingsData(client.connectionId)
@@ -160,8 +179,7 @@ export const setupServer = async (): Promise => {
socket.on('message', async (message) => {
const messageData = JSON.parse(message) as SocketData
- console.log(`WSOCKET: ${client.connectionId} sent message `, messageData)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`WEBSOCKET: Client ${client.connectionId} has sent ${message}`
)
@@ -207,7 +225,7 @@ export const setupServer = async (): Promise => {
})
socket.on('close', () => {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`WSOCKET: Client ${client.connectionId} has disconnected!`
)
@@ -223,7 +241,10 @@ export const setupServer = async (): Promise => {
const handleServerMessage = (socket, client: Client, messageData: SocketData): void => {
try {
if (messageData.app === 'server') {
- console.log(`WSOCKET: Server message received! ${messageData.type}`)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ `WSOCKET: Server message received! ${messageData.type}`
+ )
try {
switch (messageData.type) {
case 'preferences':
@@ -241,7 +262,7 @@ const handleServerMessage = (socket, client: Client, messageData: SocketData): v
)
break
case 'pong':
- console.log('Received pong from ', client.connectionId)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Received pong from ', client.connectionId)
sendIpcData(`pong-${client.connectionId}`, messageData.payload)
break
case 'set':
@@ -266,7 +287,7 @@ const handleServerMessage = (socket, client: Client, messageData: SocketData): v
sendTime()
break
case 'message':
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.MESSAGE,
`${client.connectionId}: ${messageData.payload}`
)
@@ -279,7 +300,10 @@ const handleServerMessage = (socket, client: Client, messageData: SocketData): v
const manifest = messageData.payload as ClientManifest
if (!manifest) return
- console.log('WSOCKET: Received manifest from client', manifest)
+ loggingStore.log(
+ MESSAGE_TYPES.LOGGING,
+ 'WSOCKET: Received manifest from client' + JSON.stringify(manifest)
+ )
// Update the client to the info received from the client
@@ -313,10 +337,10 @@ const handleServerMessage = (socket, client: Client, messageData: SocketData): v
}
}
-dataListener.on(MESSAGE_TYPES.SETTINGS, (newSettings: Settings) => {
+settingsStore.addListener((newSettings: Settings) => {
if (currentPort !== newSettings.devicePort || currentAddress !== newSettings.address) {
restartServer()
} else {
- dataListener.emit(MESSAGE_TYPES.LOGGING, 'WSOCKET: No settings changed!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'WSOCKET: No settings changed!')
}
})
diff --git a/DeskThingServer/src/main/static/defaultMapping.ts b/DeskThingServer/src/main/static/defaultMapping.ts
index 9add34c..46e2244 100644
--- a/DeskThingServer/src/main/static/defaultMapping.ts
+++ b/DeskThingServer/src/main/static/defaultMapping.ts
@@ -103,12 +103,7 @@ const keys: Key[] = [
description: 'Physical Button Scroll',
version: '0.9.0',
enabled: true,
- Modes: [
- EventMode.ScrollUp,
- EventMode.ScrollDown,
- EventMode.ScrollLeft,
- EventMode.ScrollRight
- ]
+ Modes: [EventMode.ScrollUp, EventMode.ScrollDown, EventMode.ScrollLeft, EventMode.ScrollRight]
},
{
id: 'Enter',
@@ -132,12 +127,7 @@ const keys: Key[] = [
description: 'Touchpad Swipe Button',
version: '0.9.0',
enabled: true,
- Modes: [
- EventMode.ScrollUp,
- EventMode.ScrollDown,
- EventMode.ScrollLeft,
- EventMode.ScrollRight
- ]
+ Modes: [EventMode.ScrollUp, EventMode.ScrollDown, EventMode.ScrollLeft, EventMode.ScrollRight]
},
{
id: 'Pad1',
diff --git a/DeskThingServer/src/main/stores/connectionsStore.ts b/DeskThingServer/src/main/stores/connectionsStore.ts
index d69aab8..3fcfc19 100644
--- a/DeskThingServer/src/main/stores/connectionsStore.ts
+++ b/DeskThingServer/src/main/stores/connectionsStore.ts
@@ -1,6 +1,6 @@
-import { Client } from '@shared/types'
+import { Client, MESSAGE_TYPES } from '@shared/types'
import { handleAdbCommands } from '../handlers/adbHandler'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import loggingStore from '../stores/loggingStore'
import settingsStore from './settingsStore'
type ClientListener = (client: Client[]) => void
@@ -20,7 +20,7 @@ class ConnectionStore {
this.autoDetectADB = settings.autoDetectADB
})
- dataListener.on(MESSAGE_TYPES.SETTINGS, (newSettings) => {
+ settingsStore.addListener((newSettings) => {
try {
if (newSettings.autoDetectADB !== undefined) {
this.autoDetectADB = newSettings.autoDetectADB
@@ -31,14 +31,18 @@ class ConnectionStore {
if (newSettings.autoDetectADB) {
this.checkAutoDetectADB()
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, '[ADB]: Auto-Detect is Enabled')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, '[ADB]: Auto-Detect is Enabled')
} else {
- console.log('Auto-detect ADB disabled')
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, '[ADB]: Auto-Detect is Disabled')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Auto-detect ADB disabled')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, '[ADB]: Auto-Detect is Disabled')
}
}
} catch (error) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, 'ADB: Error updating with settings', error)
+ if (error instanceof Error) {
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'ADB: Error updating with settings', error.message)
+ } else {
+ loggingStore.log(MESSAGE_TYPES.ERROR, 'ADB: Error updating with settings', String(error))
+ }
}
})
@@ -70,7 +74,7 @@ class ConnectionStore {
}
pingClient(connectionId: string): boolean {
- console.log('Pinging client:', connectionId)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Pinging client:', connectionId)
const clientIndex = this.clients.findIndex((c) => c.connectionId === connectionId)
console.error('PINGING CLIENTS NOT IMPLEMENTED YET')
if (clientIndex !== -1) {
@@ -81,41 +85,38 @@ class ConnectionStore {
}
getClients(): Client[] {
- console.log('Getting clients:', this.clients)
return this.clients
}
getDevices(): string[] {
- console.log('Getting devices:', this.devices)
return this.devices
}
addClient(client: Client): void {
- console.log('Adding client:', client)
this.clients.push(client)
this.notifyListeners()
}
updateClient(connectionId: string, updates: Partial): void {
- console.log('Updating client:', connectionId, updates)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Updating client:' + connectionId + updates)
const clientIndex = this.clients.findIndex((c) => c.connectionId === connectionId)
if (clientIndex !== -1) {
this.clients[clientIndex] = { ...this.clients[clientIndex], ...updates }
this.notifyListeners()
} else {
- console.log('Client not found:', connectionId)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Client not found:', connectionId)
}
}
removeClient(connectionId: string): void {
- console.log('Removing client:', connectionId)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Removing client:' + connectionId)
this.clients = this.clients.filter((c) => c.connectionId !== connectionId)
this.notifyListeners()
}
removeAllClients(): void {
- console.log('Removing all clients')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Removing all clients')
this.clients = []
this.notifyListeners()
}
@@ -142,7 +143,7 @@ class ConnectionStore {
const newDevices = parseADBDevices(result) || []
this.devices = newDevices
this.notifyDeviceListeners()
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'ADB Device found!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'ADB Device found!')
return newDevices
})
.catch((error) => {
@@ -158,7 +159,7 @@ class ConnectionStore {
const checkAndAutoDetect = async (): Promise => {
if (this.autoDetectADB === true) {
- console.log('Auto-detecting ADB devices...')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'Auto-detecting ADB devices...')
await this.getAdbDevices()
this.clearTimeout = await setTimeout(checkAndAutoDetect, 7000)
}
diff --git a/DeskThingServer/src/main/stores/keyMapStore.ts b/DeskThingServer/src/main/stores/keyMapStore.ts
index c6e4eb3..b3ccb41 100644
--- a/DeskThingServer/src/main/stores/keyMapStore.ts
+++ b/DeskThingServer/src/main/stores/keyMapStore.ts
@@ -1,6 +1,13 @@
import { defaultData } from '../static/defaultMapping'
-import { Action, ButtonMapping, EventMode, Key, MappingStructure } from '@shared/types'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import {
+ Action,
+ ButtonMapping,
+ MESSAGE_TYPES,
+ EventMode,
+ Key,
+ MappingStructure
+} from '@shared/types'
+import loggingStore from '../stores/loggingStore'
import {
readFromFile,
readFromGlobalFile,
@@ -50,7 +57,7 @@ export class MappingState {
private loadMappings(): MappingStructure {
const data = readFromFile('mappings.json') as MappingStructure
if (!data || data?.version !== defaultData.version) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Mappings file is corrupt or does not exist, using default`
)
@@ -59,7 +66,7 @@ export class MappingState {
}
const parsedData = data as MappingStructure
if (!this.isValidFileStructure(parsedData)) {
- dataListener.emit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Mappings file is corrupt, resetting to default`
)
@@ -73,7 +80,7 @@ export class MappingState {
if (this.isValidFileStructure(mapping)) {
writeToFile(mapping, 'mappings.json')
} else {
- dataListener.emit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: New Mappings file is corrupt, resetting to default`
)
@@ -192,15 +199,10 @@ export class MappingState {
* @param Mode - default is 'onPress'
* @param profile - default is 'default'
*/
- addButton = (
- action: Action,
- key: string,
- Mode: EventMode,
- profile: string = 'default'
- ): void => {
+ addButton = (action: Action, key: string, Mode: EventMode, profile: string = 'default'): void => {
const mappings = this.mappings
if (!mappings[profile]) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Profile ${profile} does not exist! Create a new profile with the name ${profile} and try again`
)
@@ -211,7 +213,7 @@ export class MappingState {
}
// Ensure that the structure of the button is valid
if (!this.isValidAction(action)) {
- dataListener.emit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Action ${action.id} is invalid, cannot add to mapping`
)
@@ -234,7 +236,7 @@ export class MappingState {
removeButton = (key: string, Mode: EventMode | null, profile: string = 'default'): void => {
const mappings = this.mappings
if (!mappings[profile]) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Profile ${profile} does not exist! Create a new profile with the name ${profile} and try again`
)
@@ -242,7 +244,7 @@ export class MappingState {
}
// Ensuring the key exists in the mapping
if (!mappings[profile][key]) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Key ${key} does not exist in profile ${profile}!`
)
@@ -252,14 +254,14 @@ export class MappingState {
if (Mode === null) {
// Remove the entire key
delete mappings[profile][key]
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Key ${key} removed from profile ${profile}`
)
} else {
// Ensure that the Mode exists in the mapping
if (!mappings[profile][key][Mode]) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Mode ${Mode} does not exist in key ${key} in profile ${profile}!`
)
@@ -271,7 +273,7 @@ export class MappingState {
// Save the mappings to file
this.mappings = mappings
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Button ${key} removed from profile ${profile}`
)
@@ -281,7 +283,7 @@ export class MappingState {
const mappings = this.mappings
// Validate key structure
if (!this.isValidKey(key)) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `MAPHANDLER: Invalid key structure`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Invalid key structure`)
return
}
// Check if the key already exists
@@ -289,11 +291,11 @@ export class MappingState {
if (existingKeyIndex !== -1) {
// Replace the existing key
mappings.keys[existingKeyIndex] = key
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Key ${key.id} updated`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Key ${key.id} updated`)
} else {
// Add the new key
mappings.keys.push(key)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Key ${key.id} added`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Key ${key.id} added`)
}
// Save the mappings
this.mappings = mappings
@@ -306,9 +308,9 @@ export class MappingState {
if (keyIndex !== -1) {
// Remove the key
mappings.keys.splice(keyIndex, 1)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Key ${keyId} removed`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Key ${keyId} removed`)
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `MAPHANDLER: Key ${keyId} not found`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Key ${keyId} not found`)
}
// Save the mappings
this.mappings = mappings
@@ -323,7 +325,7 @@ export class MappingState {
const mappings = this.mappings
// Validate action structure
if (!this.isValidAction(action)) {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `MAPHANDLER: Invalid action structure`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Invalid action structure`)
return
}
// Check if the action already exists
@@ -331,11 +333,11 @@ export class MappingState {
if (existingActionIndex !== -1) {
// Replace the existing action
mappings.actions[existingActionIndex] = action
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Action ${action.id} updated`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Action ${action.id} updated`)
} else {
// Add the new action
mappings.actions.push(action)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Action ${action.id} added`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Action ${action.id} added`)
}
// Save the mappings
this.mappings = mappings
@@ -348,9 +350,9 @@ export class MappingState {
if (actionIndex !== -1) {
// Remove the action
mappings.actions.splice(actionIndex, 1)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Action ${actionId} removed`)
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Action ${actionId} removed`)
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `MAPHANDLER: Action ${actionId} not found`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Action ${actionId} not found`)
}
// Save the mappings
this.mappings = mappings
@@ -385,7 +387,7 @@ export class MappingState {
// Remove keys with the specified source
mappings.keys = mappings.keys.filter((key) => key.source !== sourceId)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Actions for source ${sourceId} disabled in all profiles, global actions, and keys`
)
@@ -427,7 +429,7 @@ export class MappingState {
}
})
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Actions for source ${sourceId} disabled in all profiles, global actions, and keys`
)
@@ -443,12 +445,9 @@ export class MappingState {
if (actionIndex !== -1) {
// Update the icon
mappings.actions[actionIndex].icon = icon
- dataListener.asyncEmit(
- MESSAGE_TYPES.LOGGING,
- `MAPHANDLER: Icon for action ${actionId} updated`
- )
+ loggingStore.log(MESSAGE_TYPES.LOGGING, `MAPHANDLER: Icon for action ${actionId} updated`)
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `MAPHANDLER: Action ${actionId} not found`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Action ${actionId} not found`)
}
// Update the icon for all actions inside the current profile
@@ -476,7 +475,7 @@ export class MappingState {
// Update the icon
return mappings.actions[actionIndex]
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.ERROR, `MAPHANDLER: Action ${actionId} not found`)
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Action ${actionId} not found`)
return null
}
}
@@ -492,7 +491,7 @@ export class MappingState {
if (this.mappings.profiles[profile]) {
this.mappings.selected_profile = profile
} else {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Profile ${profile} does not exist! Create a new profile with the name ${profile} and try again`
)
@@ -513,16 +512,13 @@ export class MappingState {
// Check if the profile name already exists
if (mappings.profiles[profileName]) {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- `MAPHANDLER: Profile "${profileName}" already exists!`
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Profile "${profileName}" already exists!`)
return
}
// Ensure the base profile exists
if (!mappings.profiles[baseProfile]) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Base profile "${baseProfile}" does not exist!`
)
@@ -549,7 +545,7 @@ export class MappingState {
// Save the updated mappings
this.mappings = mappings
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Profile "${profileName}" added successfully.`
)
@@ -564,19 +560,13 @@ export class MappingState {
// Prevent removal of the default profile
if (profileName === 'default') {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- `MAPHANDLER: The "default" profile cannot be removed.`
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: The "default" profile cannot be removed.`)
return
}
// Check if the profile exists
if (!mappings.profiles[profileName]) {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- `MAPHANDLER: Profile "${profileName}" does not exist!`
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Profile "${profileName}" does not exist!`)
return
}
@@ -586,7 +576,7 @@ export class MappingState {
// If the removed profile was the selected profile, revert to default
if (mappings.selected_profile === profileName) {
mappings.selected_profile = 'default'
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Selected profile was removed. Reverted to "default" profile.`
)
@@ -595,7 +585,7 @@ export class MappingState {
// Save the updated mappings
this.mappings = mappings
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Profile "${profileName}" removed successfully.`
)
@@ -610,7 +600,7 @@ export class MappingState {
const mappings = this.mappings
if (!mappings.profiles[profile]) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Profile ${profile} does not exist! Cannot export.`
)
@@ -620,7 +610,7 @@ export class MappingState {
const profileData = mappings.profiles[profile]
writeToGlobalFile(profileData, filePath)
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Profile ${profile} exported to ${filePath}`
)
@@ -638,7 +628,7 @@ export class MappingState {
const profileData = readFromGlobalFile(filePath)
if (!profileData) {
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.ERROR,
`MAPHANDLER: Failed to load profile data from ${filePath}`
)
@@ -646,10 +636,7 @@ export class MappingState {
}
if (!this.isValidButtonMapping(profileData)) {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- `MAPHANDLER: Invalid profile data in file ${filePath}`
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Invalid profile data in file ${filePath}`)
return
}
@@ -657,7 +644,7 @@ export class MappingState {
mappings.profiles[profileName] = profileData
this.mappings = mappings
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Profile ${profileName} imported from ${filePath}`
)
@@ -667,16 +654,13 @@ export class MappingState {
const mappings = this.mappings
const profile = mappings.profiles[profileName]
if (!profile) {
- dataListener.asyncEmit(
- MESSAGE_TYPES.ERROR,
- `MAPHANDLER: Profile ${profileName} does not exist!`
- )
+ loggingStore.log(MESSAGE_TYPES.ERROR, `MAPHANDLER: Profile ${profileName} does not exist!`)
return
}
// Update the profile with the provided data
deepMerge(profile, updatedProfile)
this.mappings = mappings
- dataListener.asyncEmit(
+ loggingStore.log(
MESSAGE_TYPES.LOGGING,
`MAPHANDLER: Profile ${profileName} updated successfully.`
)
diff --git a/DeskThingServer/src/main/stores/loggingStore.ts b/DeskThingServer/src/main/stores/loggingStore.ts
new file mode 100644
index 0000000..70e7f32
--- /dev/null
+++ b/DeskThingServer/src/main/stores/loggingStore.ts
@@ -0,0 +1,133 @@
+import fs from 'fs'
+import { join } from 'path'
+import { app } from 'electron'
+import { MESSAGE_TYPES, Log, LOGGING_LEVEL, Settings, ReplyData, ReplyFn } from '@shared/types'
+import settingsStore from './settingsStore'
+
+// LoggingStore configuration
+const logFile = join(app.getPath('userData'), 'application.log.json')
+const readableLogFile = join(app.getPath('userData'), 'readable.log')
+
+// Ensure log directory exists
+const logDir = app.getPath('userData')
+if (!fs.existsSync(logDir)) {
+ fs.mkdirSync(logDir, { recursive: true })
+}
+
+class LoggingStore {
+ private static instance: LoggingStore
+ private listeners: ((data: Log) => void)[] = []
+ private logs: Log[] = []
+ private logLevel: LOGGING_LEVEL = LOGGING_LEVEL.PRODUCTION
+
+ private constructor() {
+ fs.writeFileSync(logFile, '[]')
+ fs.writeFileSync(readableLogFile, '')
+
+ settingsStore.addListener(this.settingsStoreListener.bind(this))
+ }
+
+ private settingsStoreListener(settings: Settings): void {
+ this.logLevel = settings.logLevel
+ }
+
+ // Singleton instance
+ public static getInstance(): LoggingStore {
+ if (!LoggingStore.instance) {
+ LoggingStore.instance = new LoggingStore()
+ }
+ return LoggingStore.instance
+ }
+
+ // Log a message
+ async log(level: MESSAGE_TYPES, message: string, source: string = 'server'): Promise {
+ if (
+ level === MESSAGE_TYPES.LOGGING &&
+ source === 'server' &&
+ this.logLevel != LOGGING_LEVEL.SYSTEM
+ ) {
+ return
+ }
+
+ if (level === MESSAGE_TYPES.LOGGING && this.logLevel == LOGGING_LEVEL.PRODUCTION) {
+ return
+ }
+
+ const timestamp = new Date().toISOString()
+ const trace = new Error().stack || ''
+
+ const logData: Log = {
+ source: source,
+ type: level,
+ log: message,
+ trace: trace,
+ date: timestamp
+ }
+
+ this.logs.push(logData)
+ this.notifyListeners(logData)
+
+ const readableTimestamp = new Date(timestamp).toLocaleString()
+ const readableMessage = `[${readableTimestamp}] [${source}] ${level.toUpperCase()}: ${message}\n`
+
+ console.log(readableMessage)
+
+ // Write to log file as JSON array
+ return new Promise((resolve, reject) => {
+ fs.writeFile(logFile, JSON.stringify(this.logs, null, 2), (err) => {
+ if (err) {
+ console.error('Failed to write to log file:', err)
+ reject(err)
+ }
+ resolve()
+ })
+
+ fs.appendFile(readableLogFile, readableMessage, (err) => {
+ if (err) {
+ console.error('Failed to write to log file:', err)
+ reject(err)
+ }
+ resolve()
+ })
+ })
+ }
+
+ notifyListeners(data: Log): void {
+ this.listeners.forEach((listener) => listener(data))
+ }
+
+ addListener(callback: (data: Log) => void): void {
+ this.listeners.push(callback)
+ }
+
+ public async getLogs(): Promise {
+ return new Promise((resolve, reject) => {
+ if (!fs.existsSync(logFile)) {
+ resolve([])
+ return
+ }
+
+ fs.readFile(logFile, 'utf8', (err, data) => {
+ if (err) {
+ return reject(err)
+ }
+ try {
+ const logs = data ? JSON.parse(data) : []
+ resolve(logs)
+ } catch (error) {
+ reject(error)
+ }
+ })
+ })
+ }
+}
+
+export const ResponseLogger = (replyFn: ReplyFn): ReplyFn => {
+ return async (channel: string, reply: ReplyData): Promise => {
+ LoggingStore.getInstance().log(MESSAGE_TYPES.LOGGING, `[${channel}]: ${JSON.stringify(reply)}`)
+
+ replyFn(channel, reply)
+ }
+}
+
+export default LoggingStore.getInstance()
diff --git a/DeskThingServer/src/main/stores/settingsStore.ts b/DeskThingServer/src/main/stores/settingsStore.ts
index 4cabccc..327b884 100644
--- a/DeskThingServer/src/main/stores/settingsStore.ts
+++ b/DeskThingServer/src/main/stores/settingsStore.ts
@@ -1,15 +1,18 @@
import { readFromFile, writeToFile } from '../utils/fileHandler'
-import dataListener, { MESSAGE_TYPES } from '../utils/events'
+import loggingStore from './loggingStore'
import os from 'os'
-import { Settings } from '@shared/types'
+import { LOGGING_LEVEL, Settings, MESSAGE_TYPES } from '@shared/types'
const settingsVersion = '0.9.2'
const version_code = 9.2
+type SettingsStoreListener = (settings: Settings) => void
+
class SettingsStore {
private settings: Settings
private settingsFilePath: string = 'settings.json'
private static instance: SettingsStore
+ private listeners: SettingsStoreListener[] = []
constructor() {
this.settings = this.getDefaultSettings()
@@ -18,7 +21,7 @@ class SettingsStore {
if (settings) {
this.settings = settings as Settings
this.settings.localIp = getLocalIpAddress()
- dataListener.asyncEmit(MESSAGE_TYPES.SETTINGS, this.settings)
+ this.notifyListeners()
}
})
.catch((err) => {
@@ -32,6 +35,16 @@ class SettingsStore {
return SettingsStore.instance
}
+ public addListener(listener: SettingsStoreListener): void {
+ this.listeners.push(listener)
+ }
+
+ private async notifyListeners(): Promise {
+ this.listeners.forEach((listener) => {
+ listener(this.settings)
+ })
+ }
+
public async getSettings(): Promise {
if (this.settings) {
return this.settings
@@ -51,14 +64,13 @@ class SettingsStore {
this.updateAutoLaunch(value)
}
this.settings[key] = value
- dataListener.asyncEmit(MESSAGE_TYPES.SETTINGS, this.settings)
this.saveSettings()
}
public async loadSettings(): Promise {
try {
const data = await readFromFile(this.settingsFilePath)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'SETTINGS: Loaded settings!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'SETTINGS: Loaded settings!')
if (!data || !data.version_code || data.version_code < version_code) {
// File does not exist, create it with default settings
@@ -71,6 +83,8 @@ class SettingsStore {
await this.updateAutoLaunch(data.autoStart)
}
+ this.notifyListeners()
+
return data
} catch (err) {
console.error('Error loading settings:', err)
@@ -103,12 +117,13 @@ class SettingsStore {
if (settings) {
this.settings = settings as Settings
await writeToFile(this.settings, this.settingsFilePath)
- dataListener.asyncEmit(MESSAGE_TYPES.SETTINGS, this.settings)
console.log('SETTINGS: Updated settings!', this.settings)
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'SETTINGS: Updated settings!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'SETTINGS: Updated settings!')
} else {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, 'SETTINGS: Invalid setting format!')
+ loggingStore.log(MESSAGE_TYPES.LOGGING, 'SETTINGS: Invalid setting format!')
}
+
+ this.notifyListeners()
} catch (err) {
console.error('Error saving settings:', err)
}
@@ -125,6 +140,7 @@ class SettingsStore {
callbackPort: 8888,
devicePort: 8891,
address: '0.0.0.0',
+ LogLevel: LOGGING_LEVEL.PRODUCTION,
autoStart: false,
autoConfig: false,
minimizeApp: true,
diff --git a/DeskThingServer/src/main/utils/events.ts b/DeskThingServer/src/main/utils/events.ts
deleted file mode 100644
index 1d0a204..0000000
--- a/DeskThingServer/src/main/utils/events.ts
+++ /dev/null
@@ -1,79 +0,0 @@
-import EventEmitter from 'events'
-import Logger from './logger'
-import { ReplyData, ReplyFn, SocketData } from '@shared/types'
-
-/**
- * The MESSAGE_TYPES object defines a set of constants that represent the different types of messages that can be sent or received in the application.
- */
-export enum MESSAGE_TYPES {
- ERROR = 'error',
- LOGGING = 'log',
- MESSAGE = 'message',
- WARNING = 'warning',
- FATAL = 'fatal',
- DEBUG = 'debugging',
- CONFIG = 'config',
- SETTINGS = 'settings',
- MAPPINGS = 'mapping'
-}
-
-/**
- * Events is a class that extends the EventEmitter class from the 'events' module.
- */
-class Events extends EventEmitter {
- constructor() {
- super()
- }
-
- /**
- * Emits an event with associated data to all connected clients.
- *
- * @param event - The name of the event to emit. Should be one of the MESSAGE_TYPES defined in this file.
- * @param data - The data to be sent along with the event. Can be of any type, but typically an object containing relevant information.
- * @returns void
- *
- * Usage:
- * 1. Import the Events instance from this file.
- * 2. Call the method with the appropriate event type and data.
- *
- * @example
- *
- * import { events } from './events'
- *
- * events.emit(MESSAGE_TYPES.MESSAGE, { content: 'Hello, world!' })
- */
- async asyncEmit(event: MESSAGE_TYPES, ...data: (string | SocketData | unknown)[]): Promise {
- console.log(`[${event}] `, data)
- return new Promise((resolve) => {
- setImmediate(() => {
- // Ensure that two arguments are only emitted at once
- if (Array.isArray(data) && data.length > 0 && typeof data[0] === 'string') {
- this.emit(event, data.join(' '))
- } else {
- this.emit(event, data[0])
- }
-
- Logger.log(event, `[${event}]: ${JSON.stringify(data, null, 2)}`)
-
- resolve()
- })
- })
- }
-}
-
-const dataListener = new Events()
-
-/**
- * Handles and standardizes the way to reply to ipc handlers
- * @param replyFn
- * @returns
- */
-export const ResponseLogger = (replyFn: ReplyFn): ReplyFn => {
- return async (channel: string, reply: ReplyData): Promise => {
- dataListener.asyncEmit(MESSAGE_TYPES.LOGGING, `[CHANNEL][${channel}]: ${JSON.stringify(reply)}`)
-
- replyFn(channel, reply)
- }
-}
-
-export default dataListener
diff --git a/DeskThingServer/src/main/utils/logger.ts b/DeskThingServer/src/main/utils/logger.ts
deleted file mode 100644
index 61cefae..0000000
--- a/DeskThingServer/src/main/utils/logger.ts
+++ /dev/null
@@ -1,57 +0,0 @@
-import fs from 'fs'
-import { join } from 'path'
-import { app } from 'electron'
-import { MESSAGE_TYPES } from './events'
-
-// Logger configuration
-const logFile = join(app.getPath('userData'), 'application.log')
-
-// Ensure log directory exists
-const logDir = app.getPath('userData')
-if (!fs.existsSync(logDir)) {
- fs.mkdirSync(logDir, { recursive: true })
-}
-
-class Logger {
- private static instance: Logger
-
- private constructor() {
- fs.writeFileSync(logFile, '')
- }
-
- // Singleton instance
- public static getInstance(): Logger {
- if (!Logger.instance) {
- Logger.instance = new Logger()
- }
- return Logger.instance
- }
-
- // Log a message
- async log(level: MESSAGE_TYPES, message: string): Promise {
- const timestamp = new Date().toLocaleTimeString()
- const logMessage = `[${timestamp}]: ${level.toUpperCase()} | ${message}`
-
- // Append to log file
- fs.appendFile(logFile, logMessage + '\n', (err) => {
- if (err) {
- console.error('Failed to write to log file:', err)
- }
- })
- }
-
- public async getLogs(): Promise {
- console.log('LOGGER: Getting logs')
- return new Promise((resolve, reject) => {
- fs.readFile(logFile, 'utf8', (err, data) => {
- if (err) {
- return reject(err)
- }
- const logs = data.trim().split('\n').filter(Boolean)
- resolve(logs)
- })
- })
- }
-}
-
-export default Logger.getInstance()
diff --git a/DeskThingServer/src/preload/index.d.ts b/DeskThingServer/src/preload/index.d.ts
index f3e5bb1..e6cf083 100644
--- a/DeskThingServer/src/preload/index.d.ts
+++ b/DeskThingServer/src/preload/index.d.ts
@@ -1,5 +1,5 @@
import { ElectronAPI } from '@electron-toolkit/preload'
-import { AppDataInterface, AppReturnData, Client, ClientManifest } from '@shared/types'
+import { AppDataInterface, AppReturnData, Client, ClientManifest, Log } from '@shared/types'
type AppData = { [key: string]: string }
@@ -38,7 +38,7 @@ declare global {
saveSettings: (settings: Settings) => Promise
getSettings: () => Promise
fetchGithub: (url: string) => Promise
- getLogs: () => Promise
+ getLogs: () => Promise
getMappings: () => Promise
addProfile: (profile: string, baseProfile?: string) => Promise
deleteProfile: (profile: string) => Promise
diff --git a/DeskThingServer/src/preload/index.ts b/DeskThingServer/src/preload/index.ts
index 5a38ef4..7195ade 100644
--- a/DeskThingServer/src/preload/index.ts
+++ b/DeskThingServer/src/preload/index.ts
@@ -11,6 +11,7 @@ import {
IncomingData,
IPC_HANDLERS,
IPCData,
+ Log,
Settings,
SocketData
} from '@shared/types'
@@ -209,7 +210,7 @@ const api = {
})
},
- getLogs: (): Promise => {
+ getLogs: (): Promise => {
return sendCommand('UTILITY', {
type: 'logs',
request: 'get',
diff --git a/DeskThingServer/src/renderer/src/assets/icons/icon/IconToggle.tsx b/DeskThingServer/src/renderer/src/assets/icons/icon/IconToggle.tsx
index 6ef3df5..afcc11b 100644
--- a/DeskThingServer/src/renderer/src/assets/icons/icon/IconToggle.tsx
+++ b/DeskThingServer/src/renderer/src/assets/icons/icon/IconToggle.tsx
@@ -3,9 +3,10 @@ import { useEffect, useRef } from 'react'
interface ToggleProps extends IconProps {
checked: boolean
+ disabled?: boolean
}
-function IconToggle({ checked, ...props }: ToggleProps): JSX.Element {
+function IconToggle({ disabled = false, checked, ...props }: ToggleProps): JSX.Element {
const circleRef = useRef(null)
useEffect(() => {
@@ -29,9 +30,16 @@ function IconToggle({ checked, ...props }: ToggleProps): JSX.Element {
stroke="currentColor"
strokeLinecap="round"
strokeLinejoin="round"
+ style={{ opacity: disabled ? 0.5 : 1, cursor: disabled ? 'not-allowed' : 'pointer' }}
>
-
+ = ({ client }) =>
const [showLogging, setShowLogging] = useState(false)
const [offline, setOffline] = useState(false)
const refreshADbClients = useClientStore((store) => store.requestADBDevices)
+ const requestClientManifest = useClientStore((store) => store.requestClientManifest)
const devicePort = useSettingsStore((store) => store.settings.devicePort)
useEffect(() => {
@@ -106,6 +107,7 @@ const ConnectionComponent: React.FC = ({ client }) =>
setLogging(reply)
if (reply.final) {
unsubscribe()
+ requestClientManifest()
}
})
} catch (error) {
@@ -219,12 +221,13 @@ const ConnectionComponent: React.FC = ({ client }) =>
{!client.connected && (
diff --git a/DeskThingServer/src/renderer/src/components/NotificationButton.tsx b/DeskThingServer/src/renderer/src/components/NotificationButton.tsx
index 70a3764..a4267d0 100644
--- a/DeskThingServer/src/renderer/src/components/NotificationButton.tsx
+++ b/DeskThingServer/src/renderer/src/components/NotificationButton.tsx
@@ -9,6 +9,7 @@ const NotificationButton: React.FC = () => {
const taskNum = useNotificationStore((state) => state.totalTasks)
const logs = useNotificationStore((state) => state.logs)
+ const requests = useNotificationStore((state) => state.requestQueue)
const issues = useNotificationStore((state) => state.issues.length)
const [errors, setErrors] = useState(0)
@@ -30,8 +31,11 @@ const NotificationButton: React.FC = () => {