Skip to content

Commit

Permalink
improve clapper ui on mobile
Browse files Browse the repository at this point in the history
  • Loading branch information
jbilcke-hf committed Sep 12, 2024
1 parent 74b7509 commit 3eb5955
Show file tree
Hide file tree
Showing 11 changed files with 313 additions and 61 deletions.
Binary file modified bun.lockb
Binary file not shown.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,5 +43,6 @@
"packages/app"
],
"dependencies": {
"react-responsive": "^10.0.0"
}
}
13 changes: 8 additions & 5 deletions packages/app/src/app/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ import { TopBar } from '@/components/toolbars/top-bar'
import { Timeline } from '@/components/core/timeline'
import { ChatView } from '@/components/assistant/ChatView'
import { Editors } from '@/components/editors/Editors'
import { BottomToolbar } from '@/components/toolbars/bottom-bar'
import { BottomBar } from '@/components/toolbars/bottom-bar'
import { FruityDesktop, FruityWindow } from '@/components/windows'
import { ScriptEditor } from '@/components/editors/ScriptEditor'
import { SegmentEditor } from '@/components/editors/SegmentEditor'
Expand All @@ -35,6 +35,7 @@ import { useDynamicWorkflows } from '@/services/editors/workflow-editor/useDynam
import { useQueryStringLoader } from '@/components/toolbars/top-menu/file/useQueryStringLoader'
import { useSetupIframeOnce } from './embed/useSetupIframeOnce'
import { TimelineZoom } from '@/components/core/timeline/TimelineZoom'
import { useBreakpoints } from '@/lib/hooks/useBreakpoints'

export enum ClapperIntegrationMode {
APP = 'APP',
Expand All @@ -57,6 +58,8 @@ function MainContent({ mode }: { mode: ClapperIntegrationMode }) {

const isIframe = mode === ClapperIntegrationMode.IFRAME

const { isMd } = useBreakpoints()

// this has to be done at the root of the app, that way it can
// perform its routine even when the monitor component is hidden
useRenderLoop()
Expand Down Expand Up @@ -323,14 +326,14 @@ function MainContent({ mode }: { mode: ClapperIntegrationMode }) {
`dark fixed flex h-screen w-screen select-none flex-col overflow-hidden font-light text-neutral-900/90 dark:text-neutral-100/90`
)}
>
<TopBar className={isIframe ? 'fixed scale-0 opacity-0' : ''} />
<TopBar className={isIframe ? 'hidden' : ''} />
<div
className={cn(
`flex w-screen flex-row overflow-hidden`,
isIframe
? 'h-screen'
: windowLayout === UIWindowLayout.GRID
? 'h-[calc(100vh-64px)]'
? 'h-[calc(100vh-48px)] md:h-[calc(100vh-64px)]'
: 'h-[calc(100vh-36px)]'
)}
style={
Expand All @@ -346,12 +349,12 @@ function MainContent({ mode }: { mode: ClapperIntegrationMode }) {
: gridLayout}
</div>

{!isIframe && welcomeScreen}
{!isIframe && isMd && welcomeScreen}

<SettingsDialog />
<LoadingDialog />
<Toaster />
{!isIframe && windowLayout === UIWindowLayout.GRID && <BottomToolbar />}
{!isIframe && windowLayout === UIWindowLayout.GRID && <BottomBar />}
</div>
)
}
Expand Down
83 changes: 83 additions & 0 deletions packages/app/src/components/toolbars/bottom-bar/BottomMenuItem.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { ReactNode } from 'react'
import { EditorView } from '@aitube/clapper-services'

import { cn } from '@/lib/utils'
import { useEditors } from '@/services/editors/useEditors'
import { useTheme } from '@/services/ui/useTheme'
import { useUI } from '@/services'

export function BottomMenuItem({
children,
view: expectedView,
label,
onClick,
}: {
children: ReactNode

/**
* Name of the menu item
*/
view?: EditorView

/**
* Label of the tooltip
*/
label?: string

/**
* Custom handler
*/
onClick?: () => void
}) {
const theme = useTheme()
const view = useEditors((s) => s.view)
const setView = useEditors((s) => s.setView)
const setShowExplorer = useUI((s) => s.setShowExplorer)
const setShowVideoPlayer = useUI((s) => s.setShowVideoPlayer)

const isActive = view === expectedView

const tooltipLabel = label || expectedView

const handleClick = () => {
onClick?.()

// nothing to do if there is no name or if we are already selecterd
if (!expectedView || isActive) {
return
}
setView(expectedView)
setShowExplorer(true)
setShowVideoPlayer(false)
}

return (
<div
className={cn(
`flex flex-col`,
`transition-all duration-150 ease-out`,
`items-center justify-center`,
isActive ? '' : `cursor-pointer`,
`transition-all duration-200 ease-in-out`,
isActive
? 'fill-neutral-50/80 text-neutral-50 opacity-100 hover:fill-neutral-50 hover:text-neutral-50'
: 'fill-neutral-400/80 text-gray-400 opacity-80 hover:fill-neutral-200 hover:text-neutral-200 hover:opacity-100',
`group`
)}
onClick={handleClick}
>
<div
className={cn(
`flex flex-col items-center justify-center`,
`text-center`,
`h-11 w-11 text-[32px]`,
`transition-all duration-200 ease-out`,
`stroke-1`,
isActive ? `scale-110` : `group-hover:scale-110`
)}
>
{children}
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { cn } from '@/lib/utils'
import { useTheme } from '@/services/ui/useTheme'

import { APP_REVISION } from '@/lib/core/constants'
import { Tasks } from './tasks'
import { useTimeline } from '@aitube/timeline'
import { TimelineZoom } from '@/components/core/timeline/TimelineZoom'

export function DesktopBottomBar() {
const theme = useTheme()
const bpm = useTimeline((s) => s.bpm)
const frameRate = useTimeline((s) => s.frameRate)

return (
<div
className={cn(
`hidden flex-row md:flex`,
`items-center justify-between`,
`h-7 w-full px-3`,
`text-xs font-light text-white/40`
)}
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-white/40">app version:</span>
<span className="text-white/55">{APP_REVISION}</span>
</div>

{/*
Note sure that's really useful since there is a garbage collector,
I got a situation where I had 1.2 Gb when loaded empty,
and it turned into 800 Mb after loading a big project,
thanks to the GC kicking in.
what would be more useful is to collect system metrics in the Desktop version.
<Metrics />
*/}

<div className="flex flex-row space-x-1">
<span className="text-white/40">BPM:</span>
<span className="text-white/55">{Math.round(bpm * 1000) / 1000}</span>
</div>

<div className="flex flex-row space-x-1">
<span className="text-white/40">FPS:</span>
<span className="text-white/55">
{Math.round(frameRate * 1000) / 1000}
</span>
</div>
</div>
<div className="flex flex-row space-x-6">
<TimelineZoom />
<Tasks />
</div>
</div>
)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,99 @@
import { CiViewTimeline } from 'react-icons/ci'
import { MdMovieEdit } from 'react-icons/md'
import { GoVideo } from 'react-icons/go'
import { GrUserSettings } from 'react-icons/gr'
import { PiBookOpenTextLight, PiTreeStructureLight } from 'react-icons/pi'
import { EditorView, SettingsCategory } from '@aitube/clapper-services'

import { cn } from '@/lib/utils'
import { useEditors, useUI } from '@/services'
import { useTheme } from '@/services/ui/useTheme'

import { NatureIcon } from '../editors-menu/NatureIcon'
import { BottomMenuItem } from './BottomMenuItem'
import { useEffect } from 'react'
import { useBreakpoints } from '@/lib/hooks/useBreakpoints'

export function MobileBottomBar() {
const theme = useTheme()
const setView = useEditors((s) => s.setView)
const setShowExplorer = useUI((s) => s.setShowExplorer)
const setShowVideoPlayer = useUI((s) => s.setShowVideoPlayer)
const setShowAssistant = useUI((s) => s.setShowAssistant)
const setShowSettings = useUI((s) => s.setShowSettings)

const { isMd } = useBreakpoints()

useEffect(() => {
if (isMd) {
setShowExplorer(true)
setShowVideoPlayer(true)
} else {
setShowAssistant(false)
setShowExplorer(false)
setShowVideoPlayer(true)
}
}, [isMd])

return (
<div
className={cn(
`flex flex-row md:hidden`,
`items-center justify-between`,
`h-12 w-full px-3`,
`border-t`,
`text-xs font-light text-white/40`,
`transition-all duration-200 ease-in-out`
)}
style={{
backgroundColor:
theme.editorMenuBgColor || theme.defaultBgColor || '#eeeeee',
borderTopColor:
theme.editorBorderColor || theme.defaultBorderColor || '#eeeeee',
}}
>
<BottomMenuItem
view={EditorView.PROJECT}
label="Project settings"
onClick={() => {
setShowExplorer(false)
}}
>
<MdMovieEdit />
</BottomMenuItem>
<BottomMenuItem view={EditorView.SCRIPT} label="Story">
<PiBookOpenTextLight />
</BottomMenuItem>
<BottomMenuItem view={EditorView.ENTITY} label="Entities">
<NatureIcon />
</BottomMenuItem>
<BottomMenuItem view={EditorView.SEGMENT} label="Segment editor">
<CiViewTimeline />
</BottomMenuItem>
<BottomMenuItem
view={EditorView.WORKFLOW}
label="Workflows"
onClick={() => {
setShowExplorer(false)
}}
>
<PiTreeStructureLight />
</BottomMenuItem>
<BottomMenuItem
label="Monitor"
onClick={() => {
setShowExplorer(false)
setShowVideoPlayer(true)
}}
>
<GoVideo />
</BottomMenuItem>
<BottomMenuItem
label="Preferences"
onClick={() => setShowSettings(SettingsCategory.PROVIDER)}
>
<GrUserSettings className="h-6 w-6" />
</BottomMenuItem>
</div>
)
}
59 changes: 6 additions & 53 deletions packages/app/src/components/toolbars/bottom-bar/index.tsx
Original file line number Diff line number Diff line change
@@ -1,66 +1,19 @@
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'
import { useTimeline } from '@aitube/timeline'
import { TimelineZoom } from '@/components/core/timeline/TimelineZoom'

export function BottomToolbar() {
const theme = useTheme()
const bpm = useTimeline((s) => s.bpm)
const frameRate = useTimeline((s) => s.frameRate)
import { DesktopBottomBar } from './DesktopBottomBar'
import { MobileBottomBar } from './MobileBottomBar'

export function BottomBar() {
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-white/40`
`left-0 right-0`
)}
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-white/40">app version:</span>
<span className="text-white/55">{APP_REVISION}</span>
</div>

{/*
Note sure that's really useful since there is a garbage collector,
I got a situation where I had 1.2 Gb when loaded empty,
and it turned into 800 Mb after loading a big project,
thanks to the GC kicking in.
what would be more useful is to collect system metrics in the Desktop version.
<Metrics />
*/}

<div className="flex flex-row space-x-1">
<span className="text-white/40">BPM:</span>
<span className="text-white/55">{Math.round(bpm * 1000) / 1000}</span>
</div>

<div className="flex flex-row space-x-1">
<span className="text-white/40">FPS:</span>
<span className="text-white/55">
{Math.round(frameRate * 1000) / 1000}
</span>
</div>
</div>
<div className="flex flex-row space-x-6">
<TimelineZoom />
<Tasks />
</div>
<MobileBottomBar />
<DesktopBottomBar />
</div>
)
}
Loading

0 comments on commit 3eb5955

Please sign in to comment.