✨ 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