浏览代码

feature: support video and audio components (#1095)

TaiJuWu 2 年之前
父节点
当前提交
e3914136f8

+ 1 - 0
pynecone/.templates/web/package.json

@@ -24,6 +24,7 @@
     "react-dom": "^18.2.0",
     "react-dropzone": "^14.2.3",
     "react-markdown": "^8.0.7",
+    "react-player": "^2.12.0",
     "react-plotly.js": "^2.6.0",
     "react-syntax-highlighter": "^15.5.0",
     "rehype-katex": "^6.0.3",

+ 2 - 0
pynecone/components/__init__.py

@@ -168,6 +168,8 @@ avatar_badge = AvatarBadge.create
 avatar_group = AvatarGroup.create
 icon = Icon.create
 image = Image.create
+video = Video.create
+audio = Audio.create
 breadcrumb = Breadcrumb.create
 breadcrumb_item = BreadcrumbItem.create
 breadcrumb_link = BreadcrumbLink.create

+ 55 - 0
pynecone/components/libs/react_player.py

@@ -0,0 +1,55 @@
+"""React-Player component."""
+
+from __future__ import annotations
+
+from typing import Optional
+
+from pynecone.components.component import Component
+from pynecone.utils import imports
+from pynecone.vars import Var
+
+
+class ReactPlayerComponent(Component):
+    """Using react-player and not implement all props and callback yet.
+    reference: https://github.com/cookpete/react-player.
+    """
+
+    library = "react-player"
+
+    tag = "ReactPlayer"
+
+    # The url of a video or song to play
+    url: Var[str]
+
+    # Set to true or false to pause or play the media
+    playing: Var[str]
+
+    # Set to true or false to loop the media
+    loop: Var[bool]
+
+    # Set to true or false to display native player controls.
+    controls: Var[bool] = True  # type: ignore
+
+    # Set to true to show just the video thumbnail, which loads the full player on click
+    light: Var[bool]
+
+    # Set the volume of the player, between 0 and 1
+    volume: Var[float]
+
+    # Mutes the player
+    muted: Var[bool]
+
+    # Set the width of the player: ex:640px
+    width: Var[str]
+
+    # Set the height of the player: ex:640px
+    height: Var[str]
+
+    def _get_imports(self) -> Optional[imports.ImportDict]:
+        return {}
+
+    def _get_custom_code(self) -> Optional[str]:
+        return """
+import dynamic from "next/dynamic";
+const ReactPlayer = dynamic(() => import("react-player/lazy"), { ssr: false });
+"""

+ 2 - 0
pynecone/components/media/__init__.py

@@ -1,7 +1,9 @@
 """Media components."""
 
+from .audio import Audio
 from .avatar import Avatar, AvatarBadge, AvatarGroup
 from .icon import Icon
 from .image import Image
+from .video import Video
 
 __all__ = [f for f in dir() if f[0].isupper()]  # type: ignore

+ 8 - 0
pynecone/components/media/audio.py

@@ -0,0 +1,8 @@
+"""A audio component."""
+from pynecone.components.libs.react_player import ReactPlayerComponent
+
+
+class Audio(ReactPlayerComponent):
+    """Audio component share with Video component."""
+
+    pass

+ 8 - 0
pynecone/components/media/video.py

@@ -0,0 +1,8 @@
+"""A video component."""
+from pynecone.components.libs.react_player import ReactPlayerComponent
+
+
+class Video(ReactPlayerComponent):
+    """Video component share with audio component."""
+
+    pass