✨ Embeddable
This commit is contained in:
		| @@ -3,6 +3,93 @@ import mediumZoom from "medium-zoom"; | ||||
|  | ||||
| import styles from "./PostAttachments.module.css"; | ||||
|  | ||||
| // @ts-ignore | ||||
| import APlayer from "aplayer"; | ||||
| import Artplayer from "artplayer"; | ||||
| import HlsJs from "hls.js"; | ||||
| import FlvJs from "flv.js"; | ||||
|  | ||||
| import "aplayer/dist/APlayer.min.css"; | ||||
|  | ||||
| function Video({ url, ...rest }: any) { | ||||
|   let container: any; | ||||
|  | ||||
|   function playM3u8(video: HTMLVideoElement, url: string, art: Artplayer) { | ||||
|     if (HlsJs.isSupported()) { | ||||
|       if (art.hls) art.hls.destroy(); | ||||
|       const hls = new HlsJs(); | ||||
|       hls.loadSource(url); | ||||
|       hls.attachMedia(video); | ||||
|       art.hls = hls; | ||||
|       art.on('destroy', () => hls.destroy()); | ||||
|     } else if (video.canPlayType('application/vnd.apple.mpegurl')) { | ||||
|       video.src = url; | ||||
|     } else { | ||||
|       art.notice.show = 'Unsupported playback format: m3u8'; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   function playFlv(video: HTMLVideoElement, url: string, art: Artplayer) { | ||||
|     if (FlvJs.isSupported()) { | ||||
|       if (art.flv) art.flv.destroy(); | ||||
|       const flv = FlvJs.createPlayer({ type: 'flv', url }); | ||||
|       flv.attachMediaElement(video); | ||||
|       flv.load(); | ||||
|       art.flv = flv; | ||||
|       art.on('destroy', () => flv.destroy()); | ||||
|     } else { | ||||
|       art.notice.show = 'Unsupported playback format: flv'; | ||||
|     } | ||||
|   } | ||||
|  | ||||
|   createEffect(() => { | ||||
|     new Artplayer({ | ||||
|       container: container as HTMLDivElement, | ||||
|       url: url, | ||||
|       setting: true, | ||||
|       flip: true, | ||||
|       loop: true, | ||||
|       playbackRate: true, | ||||
|       aspectRatio: true, | ||||
|       subtitleOffset: true, | ||||
|       fullscreen: true, | ||||
|       fullscreenWeb: true, | ||||
|       screenshot: true, | ||||
|       autoPlayback: true, | ||||
|       airplay: true, | ||||
|       theme: "#49509e", | ||||
|       customType: { | ||||
|         m3u8: playM3u8, | ||||
|         flv: playFlv, | ||||
|       }, | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   return ( | ||||
|     <div ref={container} {...rest}></div> | ||||
|   ); | ||||
| } | ||||
|  | ||||
| function Audio({ url, caption, ...rest }: any) { | ||||
|   let container: any; | ||||
|  | ||||
|   createEffect(() => { | ||||
|     new APlayer({ | ||||
|       container: container as HTMLDivElement, | ||||
|       audio: [{ | ||||
|         name: caption, | ||||
|         url: url, | ||||
|         theme: "#49509e" | ||||
|       }] | ||||
|     }); | ||||
|   }); | ||||
|  | ||||
|   return ( | ||||
|     <div ref={container} {...rest}></div> | ||||
|   ); | ||||
| } | ||||
|  | ||||
|  | ||||
| export default function PostAttachments(props: { attachments: any[] }) { | ||||
|   if (props.attachments.length <= 0) return null; | ||||
|  | ||||
| @@ -52,6 +139,12 @@ export default function PostAttachments(props: { attachments: any[] }) { | ||||
|               <img class="object-cover" src={getUrl(item())} alt={item().filename} /> | ||||
|             </figure> | ||||
|           </Match> | ||||
|           <Match when={getRenderType(item()) === "audio"}> | ||||
|             <Audio class="w-full" url={getUrl(item())} caption={item().filename} /> | ||||
|           </Match> | ||||
|           <Match when={getRenderType(item()) === "video"}> | ||||
|             <Video class="h-[360px] w-full" url={getUrl(item())} caption={item().filename} /> | ||||
|           </Match> | ||||
|         </Switch> | ||||
|  | ||||
|         <div id="attachments-control" class="flex justify-between border-t border-base-200"> | ||||
|   | ||||
| @@ -1,8 +1,8 @@ | ||||
| import Navbar from "./shared/Navbar.tsx"; | ||||
| import { readProfiles, useUserinfo } from "../stores/userinfo.tsx"; | ||||
| import { createEffect, createSignal, Show } from "solid-js"; | ||||
| import { createEffect, createMemo, createSignal, Show } from "solid-js"; | ||||
| import { readWellKnown } from "../stores/wellKnown.tsx"; | ||||
| import { BeforeLeaveEventArgs, useBeforeLeave, useLocation, useNavigate } from "@solidjs/router"; | ||||
| import { BeforeLeaveEventArgs, useBeforeLeave, useLocation, useNavigate, useSearchParams } from "@solidjs/router"; | ||||
|  | ||||
| export default function RootLayout(props: any) { | ||||
|   const [ready, setReady] = createSignal(false); | ||||
| @@ -12,6 +12,7 @@ export default function RootLayout(props: any) { | ||||
|   const navigate = useNavigate(); | ||||
|   const userinfo = useUserinfo(); | ||||
|  | ||||
|   const [searchParams] = useSearchParams(); | ||||
|   const location = useLocation(); | ||||
|  | ||||
|   createEffect(() => { | ||||
| @@ -31,6 +32,14 @@ export default function RootLayout(props: any) { | ||||
|  | ||||
|   useBeforeLeave((e: BeforeLeaveEventArgs) => keepGate(e.to.toString().split("?")[0], e)); | ||||
|  | ||||
|   const mainContentStyles = createMemo(() => { | ||||
|     if(!searchParams["noTitle"]) { | ||||
|       return "h-[calc(100vh-64px)] mt-[64px]" | ||||
|     } else { | ||||
|       return "h-[100vh]" | ||||
|     } | ||||
|   }) | ||||
|  | ||||
|   return ( | ||||
|     <Show when={ready()} fallback={ | ||||
|       <div class="h-screen w-screen flex justify-center items-center"> | ||||
| @@ -39,8 +48,11 @@ export default function RootLayout(props: any) { | ||||
|         </div> | ||||
|       </div> | ||||
|     }> | ||||
|       <Navbar /> | ||||
|       <main class="h-[calc(100vh-64px)] mt-[64px]">{props.children}</main> | ||||
|       <Show when={!searchParams["noTitle"]}> | ||||
|         <Navbar /> | ||||
|       </Show> | ||||
|  | ||||
|       <main class={mainContentStyles()}>{props.children}</main> | ||||
|     </Show> | ||||
|   ); | ||||
| } | ||||
		Reference in New Issue
	
	Block a user