Spaces:
Running
Running
| /** | |
| * Copyright 2024 Google LLC | |
| * | |
| * Licensed under the Apache License, Version 2.0 (the "License"); | |
| * you may not use this file except in compliance with the License. | |
| * You may obtain a copy of the License at | |
| * | |
| * http://www.apache.org/licenses/LICENSE-2.0 | |
| * | |
| * Unless required by applicable law or agreed to in writing, software | |
| * distributed under the License is distributed on an "AS IS" BASIS, | |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| * See the License for the specific language governing permissions and | |
| * limitations under the License. | |
| */ | |
| import { useRef, useState, useEffect } from "react"; | |
| import "./App.scss"; | |
| import { LiveAPIProvider } from "./contexts/LiveAPIContext"; | |
| import SidePanel from "./components/side-panel/SidePanel"; | |
| import { P5WithEditor } from "./components/p5/P5WithEditor"; | |
| import { P5Sketch } from "./components/p5/P5Sketch"; | |
| import ControlTray from "./components/control-tray/ControlTray"; | |
| import { IOSModal } from "./components/ios-modal/IOSModal"; | |
| import { isIOS } from "./lib/platform"; | |
| import cn from "classnames"; | |
| function App() { | |
| // this video reference is used for displaying the active stream, whether that is the webcam or screen capture | |
| // feel free to style as you see fit | |
| const videoRef = useRef<HTMLVideoElement>(null); | |
| // either the screen capture, the video or null, if null we hide it | |
| const [videoStream, setVideoStream] = useState<MediaStream | null>(null); | |
| const [showIOSModal, setShowIOSModal] = useState(false); | |
| const [isMobile, setIsMobile] = useState(window.innerWidth < 768); | |
| useEffect(() => { | |
| const handleResize = () => { | |
| setIsMobile(window.innerWidth < 768); | |
| }; | |
| window.addEventListener('resize', handleResize); | |
| // Check iOS on mount | |
| if (isIOS()) { | |
| setShowIOSModal(true); | |
| } | |
| return () => window.removeEventListener('resize', handleResize); | |
| }, []); | |
| return ( | |
| <div className="App"> | |
| <LiveAPIProvider> | |
| <div className="streaming-console"> | |
| <SidePanel initialCollapsed={true} /> | |
| <main> | |
| <h1 className="app-title"> | |
| LiveCoder <span className="subtitle">Built with <a target="_blank" href="https://ai.google.dev/gemini-api/docs/multimodal-live">Google Live API</a> + <a target="_blank" href="https://p5js.org/reference/">p5.js</a></span> | |
| </h1> | |
| <div className="main-app-area"> | |
| {/* APP goes here */} | |
| <div className="p5-editor-container"> | |
| {isMobile ? <P5Sketch /> : <P5WithEditor />} | |
| </div> | |
| </div> | |
| <video | |
| style={{ background: "black" }} | |
| className={cn("stream float minimal", { | |
| hidden: !videoRef.current || !videoStream, | |
| })} | |
| ref={videoRef} | |
| autoPlay | |
| playsInline | |
| /> | |
| <ControlTray | |
| videoRef={videoRef} | |
| supportsVideo={false} | |
| onVideoStreamChange={setVideoStream} | |
| > | |
| {/* put your own buttons here */} | |
| </ControlTray> | |
| </main> | |
| </div> | |
| </LiveAPIProvider> | |
| <IOSModal | |
| isOpen={showIOSModal} | |
| onClose={() => setShowIOSModal(false)} | |
| /> | |
| </div> | |
| ); | |
| } | |
| export default App; | |