✨ Embeddable
This commit is contained in:
		
							
								
								
									
										27
									
								
								pkg/view/embed.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								pkg/view/embed.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | <!doctype html> | ||||||
|  | <html lang="en"> | ||||||
|  | <head> | ||||||
|  |   <meta charset="UTF-8"> | ||||||
|  |   <meta name="viewport" | ||||||
|  |         content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> | ||||||
|  |   <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||||||
|  |   <title>Embedded Interactive</title> | ||||||
|  |  | ||||||
|  |   <style> | ||||||
|  |       body, html { | ||||||
|  |           padding: 0; | ||||||
|  |           margin: 0; | ||||||
|  |       } | ||||||
|  |  | ||||||
|  |       iframe { | ||||||
|  |           width: 100vw; | ||||||
|  |           height: 100vh; | ||||||
|  |           display: block; | ||||||
|  |           border: 0; | ||||||
|  |       } | ||||||
|  |   </style> | ||||||
|  | </head> | ||||||
|  | <body> | ||||||
|  | <iframe src="http://localhost:8445/realms/1?noTitle=1"></iframe> | ||||||
|  | </body> | ||||||
|  | </html> | ||||||
| @@ -11,6 +11,10 @@ | |||||||
|   "dependencies": { |   "dependencies": { | ||||||
|     "@fortawesome/fontawesome-free": "^6.5.1", |     "@fortawesome/fontawesome-free": "^6.5.1", | ||||||
|     "@solidjs/router": "^0.10.10", |     "@solidjs/router": "^0.10.10", | ||||||
|  |     "aplayer": "^1.10.1", | ||||||
|  |     "artplayer": "^5.1.1", | ||||||
|  |     "flv.js": "^1.6.2", | ||||||
|  |     "hls.js": "^1.5.3", | ||||||
|     "medium-zoom": "^1.1.0", |     "medium-zoom": "^1.1.0", | ||||||
|     "solid-js": "^1.8.7", |     "solid-js": "^1.8.7", | ||||||
|     "universal-cookie": "^7.0.2" |     "universal-cookie": "^7.0.2" | ||||||
|   | |||||||
| @@ -3,6 +3,93 @@ import mediumZoom from "medium-zoom"; | |||||||
|  |  | ||||||
| import styles from "./PostAttachments.module.css"; | 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[] }) { | export default function PostAttachments(props: { attachments: any[] }) { | ||||||
|   if (props.attachments.length <= 0) return null; |   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} /> |               <img class="object-cover" src={getUrl(item())} alt={item().filename} /> | ||||||
|             </figure> |             </figure> | ||||||
|           </Match> |           </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> |         </Switch> | ||||||
|  |  | ||||||
|         <div id="attachments-control" class="flex justify-between border-t border-base-200"> |         <div id="attachments-control" class="flex justify-between border-t border-base-200"> | ||||||
|   | |||||||
| @@ -1,8 +1,8 @@ | |||||||
| import Navbar from "./shared/Navbar.tsx"; | import Navbar from "./shared/Navbar.tsx"; | ||||||
| import { readProfiles, useUserinfo } from "../stores/userinfo.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 { 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) { | export default function RootLayout(props: any) { | ||||||
|   const [ready, setReady] = createSignal(false); |   const [ready, setReady] = createSignal(false); | ||||||
| @@ -12,6 +12,7 @@ export default function RootLayout(props: any) { | |||||||
|   const navigate = useNavigate(); |   const navigate = useNavigate(); | ||||||
|   const userinfo = useUserinfo(); |   const userinfo = useUserinfo(); | ||||||
|  |  | ||||||
|  |   const [searchParams] = useSearchParams(); | ||||||
|   const location = useLocation(); |   const location = useLocation(); | ||||||
|  |  | ||||||
|   createEffect(() => { |   createEffect(() => { | ||||||
| @@ -31,6 +32,14 @@ export default function RootLayout(props: any) { | |||||||
|  |  | ||||||
|   useBeforeLeave((e: BeforeLeaveEventArgs) => keepGate(e.to.toString().split("?")[0], e)); |   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 ( |   return ( | ||||||
|     <Show when={ready()} fallback={ |     <Show when={ready()} fallback={ | ||||||
|       <div class="h-screen w-screen flex justify-center items-center"> |       <div class="h-screen w-screen flex justify-center items-center"> | ||||||
| @@ -39,8 +48,11 @@ export default function RootLayout(props: any) { | |||||||
|         </div> |         </div> | ||||||
|       </div> |       </div> | ||||||
|     }> |     }> | ||||||
|  |       <Show when={!searchParams["noTitle"]}> | ||||||
|         <Navbar /> |         <Navbar /> | ||||||
|       <main class="h-[calc(100vh-64px)] mt-[64px]">{props.children}</main> |       </Show> | ||||||
|  |  | ||||||
|  |       <main class={mainContentStyles()}>{props.children}</main> | ||||||
|     </Show> |     </Show> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
		Reference in New Issue
	
	Block a user