Embeddable

This commit is contained in:
LittleSheep 2024-02-05 20:31:37 +08:00
parent 8cb6b699e5
commit ee4562648e
4 changed files with 140 additions and 4 deletions

27
pkg/view/embed.html Normal file
View 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>

View File

@ -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"

View File

@ -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">

View File

@ -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>
}> }>
<Navbar /> <Show when={!searchParams["noTitle"]}>
<main class="h-[calc(100vh-64px)] mt-[64px]">{props.children}</main> <Navbar />
</Show>
<main class={mainContentStyles()}>{props.children}</main>
</Show> </Show>
); );
} }