Skip to content

Commit

Permalink
fix theme + work on task manager
Browse files Browse the repository at this point in the history
  • Loading branch information
jbilcke-hf committed Jul 23, 2024
1 parent 5bd8810 commit 74c9d0e
Show file tree
Hide file tree
Showing 14 changed files with 453 additions and 1,149 deletions.
1,305 changes: 182 additions & 1,123 deletions package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@
"dependencies": {
"@aitube/broadway": "0.0.22",
"@aitube/clap": "0.0.30",
"@aitube/clapper-services": "0.0.34",
"@aitube/clapper-services": "0.0.35",
"@aitube/engine": "0.0.26",
"@aitube/timeline": "0.0.44",
"@aitube/timeline": "0.0.45",
"@fal-ai/serverless-client": "^0.13.0",
"@ffmpeg/ffmpeg": "^0.12.10",
"@ffmpeg/util": "^0.12.1",
Expand Down
6 changes: 4 additions & 2 deletions src/app/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { Timeline } from '@/components/core/timeline'
import { ChatView } from '@/components/assistant/ChatView'
import { Editors } from '@/components/editors/Editors'
import { useTheme } from '@/services/ui/useTheme'
import { BottomToolbar } from '@/components/toolbars/bottom-bar'

type DroppableThing = { files: File[] }

Expand Down Expand Up @@ -76,9 +77,9 @@ function MainContent() {
<ReflexElement minSize={showTimeline ? 100 : 1}>
<ReflexContainer orientation="vertical">
<ReflexElement
size={showTimeline ? 400 : 1}
size={showTimeline ? 700 : 1}
minSize={showTimeline ? 100 : 1}
maxSize={showTimeline ? 1600 : 1}
maxSize={showTimeline ? 2000 : 1}
>
<Editors />
</ReflexElement>
Expand All @@ -95,6 +96,7 @@ function MainContent() {
maxSize={showTimeline ? 1600 : 1}
>
<Timeline />
<BottomToolbar />
</ReflexElement>
</ReflexContainer>
</ReflexElement>
Expand Down
3 changes: 1 addition & 2 deletions src/components/core/timeline/index.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { useEffect } from 'react'
import { ClapTimeline, useTimeline, SegmentResolver } from '@aitube/timeline'

import { cn } from '@/lib/utils'
import { useMonitor } from '@/services/monitor/useMonitor'
import { useResolver } from '@/services/resolver/useResolver'
import { useUI } from '@/services/ui'
Expand Down Expand Up @@ -49,5 +48,5 @@ export function Timeline() {
togglePlayback,
])

return <ClapTimeline showFPS={false} className={cn('bg-[rgb(58,54,50)]')} />
return <ClapTimeline showFPS={false} />
}
4 changes: 2 additions & 2 deletions src/components/monitor/PlayerControls/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export function PlayerControls({ className }: { className?: string }) {
>
<Counter
valueInMs={cursorTimestampAtInMs}
color={theme.monitorSecondaryTextColor || theme.defaultTextColor || ''}
color={theme.monitorPrimaryTextColor || theme.defaultPrimaryColor || ''}
/>
<div
className={cn(
Expand Down Expand Up @@ -78,7 +78,7 @@ export function PlayerControls({ className }: { className?: string }) {
</div>
<Counter
valueInMs={totalDurationInMs}
color={theme.monitorPrimaryTextColor || theme.defaultPrimaryColor || ''}
color={theme.monitorSecondaryTextColor || theme.defaultTextColor || ''}
/>
</div>
)
Expand Down
41 changes: 41 additions & 0 deletions src/components/toolbars/bottom-bar/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
import { cn } from '@/lib/utils'
import { useTheme } from '@/services/ui/useTheme'

import { Metrics } from './metrics'
import { APP_REVISION } from '@/lib/core/constants'
import { Tasks } from './tasks'

export function BottomToolbar() {
const theme = useTheme()

return (
<div
className={cn(
`absolute bottom-0 flex flex-row`,
`items-center justify-between`,
`left-0 right-0 h-7`,
`px-3`,
`text-xs font-light text-stone-400`
)}
style={{
borderTop: 'solid 1px rgba(255,255,255,0.3)',
backgroundColor:
theme.editorMenuBgColor || theme.defaultBgColor || '#afafaf',
// borderTopColor: theme.editorTextColor || theme.defaultBorderColor || "#bfbfbf",
color: theme.editorTextColor || theme.defaultTextColor || '#ffffff',
}}
>
<div className="flex flex-row space-x-3">
<div className="flex flex-row space-x-1">
<span className="text-stone-400/70">app version:</span>
<span className="text-stone-300/70">{APP_REVISION}</span>
</div>

<Metrics />
</div>
<div className="flex flex-row space-x-6">
<Tasks />
</div>
</div>
)
}
28 changes: 28 additions & 0 deletions src/components/toolbars/bottom-bar/metrics/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import usePerformanceMeter from '@/lib/hooks/usePerformanceMeter'
import { cn } from '@/lib/utils'

export function Metrics() {
const { isAvailable, isMeasuring, bytes, humanReadableString } =
usePerformanceMeter({
delayBetweenMeasures: 20,
})
console.log('debug:', {
isAvailable,
isMeasuring,
bytes,
humanReadableString,
})

if (!isAvailable) {
return null
}

return (
<div className="flex flex-row space-x-1">
<span className="text-stone-500">memory usage:</span>
<span className="text-stone-400">
{!bytes ? 'waiting..' : humanReadableString || ''}
</span>
</div>
)
}
56 changes: 56 additions & 0 deletions src/components/toolbars/bottom-bar/tasks/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
import { TaskStatus, TaskVisibility } from '@aitube/clapper-services'

import {
Popover,
PopoverContent,
PopoverTrigger,
} from '@/components/ui/popover'
import { cn } from '@/lib/utils'
import { useTasks } from '@/services'

export function Tasks() {
const { find, tasks } = useTasks()

const runningBlockerTasks = find({
status: TaskStatus.RUNNING,
visibility: TaskVisibility.BLOCKER,
})
const runningBackgroundTasks = find({
status: TaskStatus.RUNNING,
visibility: TaskVisibility.BACKGROUND,
})

const nbRunningBackgroundTasks = runningBackgroundTasks.length
const hasRunningBackgroundTasks = nbRunningBackgroundTasks > 0
const currentRunningBackgroundTaskProgress =
runningBackgroundTasks[0]?.progress || 0

const nbRunningBlockerTasks = runningBlockerTasks.length
const hasRunningBlockerTasks = nbRunningBlockerTasks > 0
const currentRunningBlockerTaskProgress =
runningBlockerTasks[0]?.progress || 0

return (
<div className={cn(``)}>
<Popover>
<PopoverTrigger>
{nbRunningBackgroundTasks || 'no'} pending tasks
</PopoverTrigger>
<PopoverContent>
<div className={cn(`flex flex-col text-xs font-light`)}>
{runningBackgroundTasks.map((task) => {
return (
<div className="flex flex-row" key={task.id}>
<div>{task.status}</div>
<div>{task.priority}</div>
<div>{task.category}</div>
<div>{task.progress}%</div>
</div>
)
})}
</div>
</PopoverContent>
</Popover>
</div>
)
}
10 changes: 10 additions & 0 deletions src/components/toolbars/top-menu/file/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import { useOpenFilePicker, useQueryStringParams } from '@/lib/hooks'
import { IframeWarning } from '@/components/dialogs/iframe-warning'
import { useIO, useUI } from '@/services'
import { newClap } from '@aitube/clap'
import { getDemoGame } from '@/experiments/samples/demo'

export function TopMenuFile() {
const { clapUrl } = useQueryStringParams({
Expand Down Expand Up @@ -98,6 +99,15 @@ export function TopMenuFile() {
<MenubarSub>
<MenubarSubTrigger>Import an example</MenubarSubTrigger>
<MenubarSubContent>
{hasBetaAccess && (
<MenubarItem
onClick={() => {
setClap(getDemoGame())
}}
>
(secret demo)
</MenubarItem>
)}
<MenubarItem
onClick={() => {
openClapUrl('/samples/claps/wasteland.clap')
Expand Down
1 change: 0 additions & 1 deletion src/components/toolbars/top-menu/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,6 @@ export function TopMenu() {
{
// clap?.meta?.title || "Untitled"
}
<span className="text-stone-500">{APP_REVISION}</span>
</div>
</Menubar>
)
Expand Down
46 changes: 46 additions & 0 deletions src/experiments/samples/demo.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import {
ClapProject,
ClapSegment,
ClapSegmentCategory,
newClap,
newSegment,
} from '@aitube/clap'

export async function getDemoGame() {
const demo: ClapProject = newClap({
meta: {
title: 'Demo Game',
isInteractive: true,
// isLoop: true,
},
})

const startTimeInMs = 0

// 1 hour session
const endTimeInMs = 60 * 60 * 1000

const defaultMessage: ClapSegment = newSegment({
track: 1,
category: ClapSegmentCategory.INTERFACE,
prompt: 'Hello world',
label: 'Hello world',
startTimeInMs,
endTimeInMs,
})
demo.segments.push(defaultMessage)

const aiShouldRespondToMessage: ClapSegment = newSegment({
track: 2,
category: ClapSegmentCategory.PHENOMENON,
prompt: 'When the user asks a question, an assistant will answer',
label: 'Assistant',
startTimeInMs,
endTimeInMs,
})
demo.segments.push(aiShouldRespondToMessage)

// TODO: experiment with a pong game too

return demo
}
2 changes: 1 addition & 1 deletion src/lib/core/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
export const HARD_LIMIT_NB_MAX_ASSETS_TO_GENERATE_IN_PARALLEL = 32

export const APP_NAME = 'Clapper.app'
export const APP_REVISION = 'r20240722-2258'
export const APP_REVISION = '20240723+1632'

export const APP_DOMAIN = 'Clapper.app'
export const APP_LINK = 'https://clapper.app'
64 changes: 64 additions & 0 deletions src/lib/hooks/usePerformanceMeter.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { useState, useEffect, useCallback } from 'react'

interface PerformanceMeterOptions {
delayBetweenMeasures: number
}

interface PerformanceMeterResult {
isAvailable: boolean
isMeasuring: boolean
bytes: number | null
humanReadableString: string | null
}

const usePerformanceMeter = ({
delayBetweenMeasures,
}: PerformanceMeterOptions): PerformanceMeterResult => {
const [isAvailable, setIsAvailable] = useState<boolean>(false)
const [isMeasuring, setIsMeasuring] = useState<boolean>(false)
const [bytes, setBytes] = useState<number | null>(null)
const [humanReadableString, setHumanReadableString] = useState<string | null>(
null
)

const measureMemory = useCallback(async () => {
if (!isAvailable) return

setIsMeasuring(true)
try {
const result = await (performance as any).measureUserAgentSpecificMemory()
setBytes(result.bytes)
setHumanReadableString(formatBytes(result.bytes))
} catch (error) {
console.error('Error measuring memory:', error)
} finally {
setIsMeasuring(false)
}
}, [isAvailable])

useEffect(() => {
const checkAvailability = () => {
const available = 'measureUserAgentSpecificMemory' in performance
setIsAvailable(available)
return available
}

if (checkAvailability()) {
measureMemory() // Start measuring immediately
const intervalId = setInterval(measureMemory, delayBetweenMeasures * 1000)
return () => clearInterval(intervalId)
}
}, [delayBetweenMeasures, measureMemory])

const formatBytes = (bytes: number): string => {
if (bytes === 0) return '0 Bytes'
const k = 1024
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']
const i = Math.floor(Math.log(bytes) / Math.log(k))
return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i]
}

return { isAvailable, isMeasuring, bytes, humanReadableString }
}

export default usePerformanceMeter
Loading

0 comments on commit 74c9d0e

Please sign in to comment.