Compare commits
No commits in common. "5d898ac48510707dd910d344c5ef2f9ca546d544" and "5cbd1d5c026015bcc43e8d0a4ffde75ff0d36f7d" have entirely different histories.
5d898ac485
...
5cbd1d5c02
|
|
@ -9,8 +9,6 @@ import { openEmojiPicker } from './tags/emoji-picker'
|
||||||
let selectedApp: string | null = localStorage.getItem('selectedApp')
|
let selectedApp: string | null = localStorage.getItem('selectedApp')
|
||||||
let sidebarCollapsed: boolean = localStorage.getItem('sidebarCollapsed') === 'true'
|
let sidebarCollapsed: boolean = localStorage.getItem('sidebarCollapsed') === 'true'
|
||||||
|
|
||||||
const DEFAULT_EMOJI = '🖥️'
|
|
||||||
|
|
||||||
// Server state (from SSE)
|
// Server state (from SSE)
|
||||||
let apps: App[] = []
|
let apps: App[] = []
|
||||||
|
|
||||||
|
|
@ -382,7 +380,7 @@ const AppDetail = ({ app }: { app: App }) => (
|
||||||
<>
|
<>
|
||||||
<MainHeader>
|
<MainHeader>
|
||||||
<MainTitle>
|
<MainTitle>
|
||||||
<OpenEmojiPicker app={app}>{app.icon ?? DEFAULT_EMOJI}</OpenEmojiPicker>
|
<OpenEmojiPicker app={app}>{app.icon ?? <StatusDot state={app.state} />}</OpenEmojiPicker>
|
||||||
|
|
||||||
{app.name}
|
{app.name}
|
||||||
</MainTitle>
|
</MainTitle>
|
||||||
|
|
@ -402,6 +400,7 @@ const AppDetail = ({ app }: { app: App }) => (
|
||||||
<InfoValue>
|
<InfoValue>
|
||||||
<StatusDot state={app.state} />
|
<StatusDot state={app.state} />
|
||||||
{stateLabels[app.state]}
|
{stateLabels[app.state]}
|
||||||
|
{app.port ? ` on :${app.port}` : ''}
|
||||||
</InfoValue>
|
</InfoValue>
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
{app.state === 'running' && app.port && (
|
{app.state === 'running' && app.port && (
|
||||||
|
|
@ -414,14 +413,6 @@ const AppDetail = ({ app }: { app: App }) => (
|
||||||
</InfoValue>
|
</InfoValue>
|
||||||
</InfoRow>
|
</InfoRow>
|
||||||
)}
|
)}
|
||||||
{app.state === 'running' && app.port && (
|
|
||||||
<InfoRow>
|
|
||||||
<InfoLabel>Port</InfoLabel>
|
|
||||||
<InfoValue>
|
|
||||||
{app.port}
|
|
||||||
</InfoValue>
|
|
||||||
</InfoRow>
|
|
||||||
)}
|
|
||||||
{app.started && (
|
{app.started && (
|
||||||
<InfoRow>
|
<InfoRow>
|
||||||
<InfoLabel>Started</InfoLabel>
|
<InfoLabel>Started</InfoLabel>
|
||||||
|
|
@ -509,15 +500,12 @@ const Dashboard = () => {
|
||||||
style={sidebarCollapsed ? { justifyContent: 'center', padding: '10px 12px' } : undefined}
|
style={sidebarCollapsed ? { justifyContent: 'center', padding: '10px 12px' } : undefined}
|
||||||
title={sidebarCollapsed ? app.name : undefined}
|
title={sidebarCollapsed ? app.name : undefined}
|
||||||
>
|
>
|
||||||
{sidebarCollapsed ? (
|
{app.state === 'running' && app.icon ? (
|
||||||
<span style={{ fontSize: 18 }}>{app.icon ?? DEFAULT_EMOJI}</span>
|
<span style={{ fontSize: sidebarCollapsed ? 18 : 14 }}>{app.icon}</span>
|
||||||
) : (
|
) : (
|
||||||
<>
|
<StatusDot state={app.state} />
|
||||||
<span style={{ fontSize: 14 }}>{app.icon ?? DEFAULT_EMOJI}</span>
|
|
||||||
{app.name}
|
|
||||||
<StatusDot state={app.state} style={{ marginLeft: 'auto' }} />
|
|
||||||
</>
|
|
||||||
)}
|
)}
|
||||||
|
{!sidebarCollapsed && app.name}
|
||||||
</AppItem>
|
</AppItem>
|
||||||
))}
|
))}
|
||||||
</AppList>
|
</AppList>
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,5 @@
|
||||||
import type { Subprocess } from 'bun'
|
import type { Subprocess } from 'bun'
|
||||||
import {
|
import { existsSync, readdirSync, readFileSync, writeFileSync, watch } from 'fs'
|
||||||
existsSync, readdirSync, readFileSync, writeFileSync,
|
|
||||||
statSync, watch
|
|
||||||
} from 'fs'
|
|
||||||
import { join } from 'path'
|
import { join } from 'path'
|
||||||
import type { App as SharedApp, AppState, LogLine } from '../shared/types'
|
import type { App as SharedApp, AppState, LogLine } from '../shared/types'
|
||||||
|
|
||||||
|
|
@ -211,8 +208,9 @@ export const stopApp = (dir: string) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
const watchAppsDir = () => {
|
const watchAppsDir = () => {
|
||||||
watch(APPS_DIR, { recursive: true }, (event, filename) => {
|
watch(APPS_DIR, { recursive: true }, (_event, filename) => {
|
||||||
if (!filename) return
|
if (!filename) return
|
||||||
|
if (!filename.includes('/')) return
|
||||||
|
|
||||||
// Extract the app directory name from the path (e.g., "myapp/package.json" -> "myapp")
|
// Extract the app directory name from the path (e.g., "myapp/package.json" -> "myapp")
|
||||||
const dir = filename.split('/')[0]!
|
const dir = filename.split('/')[0]!
|
||||||
|
|
@ -232,13 +230,6 @@ const watchAppsDir = () => {
|
||||||
|
|
||||||
const app = _apps.get(dir)!
|
const app = _apps.get(dir)!
|
||||||
|
|
||||||
// check if app was deleted
|
|
||||||
if (!isDir(join(APPS_DIR, dir))) {
|
|
||||||
_apps.delete(dir)
|
|
||||||
update()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// Only care about package.json changes for existing apps
|
// Only care about package.json changes for existing apps
|
||||||
if (!filename.endsWith('package.json')) return
|
if (!filename.endsWith('package.json')) return
|
||||||
|
|
||||||
|
|
@ -265,7 +256,6 @@ const watchAppsDir = () => {
|
||||||
app.state = 'invalid'
|
app.state = 'invalid'
|
||||||
update()
|
update()
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!error && app.state === 'invalid') {
|
if (!error && app.state === 'invalid') {
|
||||||
app.state = 'stopped'
|
app.state = 'stopped'
|
||||||
update()
|
update()
|
||||||
|
|
@ -273,14 +263,6 @@ const watchAppsDir = () => {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function isDir(path: string): boolean {
|
|
||||||
try {
|
|
||||||
return statSync(path).isDirectory()
|
|
||||||
} catch {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export const initApps = () => {
|
export const initApps = () => {
|
||||||
discoverApps()
|
discoverApps()
|
||||||
runApps()
|
runApps()
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user