💄 UX Optimized

This commit is contained in:
LittleSheep 2024-02-09 00:44:20 +08:00
parent 8d1cb9d9c0
commit 86e184a803
6 changed files with 27 additions and 42 deletions

View File

@ -11,17 +11,18 @@
"dependencies": {
"@fortawesome/fontawesome-free": "^6.5.1",
"@solidjs/router": "^0.10.10",
"aplayer": "^1.10.1",
"artplayer": "^5.1.1",
"dompurify": "^3.0.8",
"flv.js": "^1.6.2",
"hls.js": "^1.5.3",
"marked": "^12.0.0",
"medium-zoom": "^1.1.0",
"solid-js": "^1.8.7",
"solid-markdown": "^2.0.0",
"universal-cookie": "^7.0.2"
},
"devDependencies": {
"@tailwindcss/typography": "^0.5.10",
"@types/dompurify": "^3.0.5",
"autoprefixer": "^10.4.17",
"daisyui": "^4.6.1",
"postcss": "^8.4.33",

View File

@ -3,14 +3,10 @@ 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;
@ -21,24 +17,24 @@ function Video({ url, ...rest }: any) {
hls.loadSource(url);
hls.attachMedia(video);
art.hls = hls;
art.on('destroy', () => hls.destroy());
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
art.on("destroy", () => hls.destroy());
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
video.src = url;
} else {
art.notice.show = 'Unsupported playback format: m3u8';
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 });
const flv = FlvJs.createPlayer({ type: "flv", url });
flv.attachMediaElement(video);
flv.load();
art.flv = flv;
art.on('destroy', () => flv.destroy());
art.on("destroy", () => flv.destroy());
} else {
art.notice.show = 'Unsupported playback format: flv';
art.notice.show = "Unsupported playback format: flv";
}
}
@ -54,14 +50,11 @@ function Video({ url, ...rest }: any) {
subtitleOffset: true,
fullscreen: true,
fullscreenWeb: true,
screenshot: true,
autoPlayback: true,
airplay: true,
theme: "#49509e",
customType: {
m3u8: playM3u8,
flv: playFlv,
},
flv: playFlv
}
});
});
@ -71,21 +64,12 @@ function Video({ url, ...rest }: any) {
}
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>
<figure {...rest}>
<figcaption>{caption}</figcaption>
<audio controls src={url} />
</figure>
);
}
@ -129,7 +113,7 @@ export default function PostAttachments(props: { attachments: any[] }) {
</div>
<div class="mt-5">
<a class="link" href={getUrl(item())} target="_blank">Open in browser</a>
<a class="link" href={getUrl(item())} target="_blank">Open in browser</a>
</div>
</div>
</div>
@ -140,7 +124,8 @@ export default function PostAttachments(props: { attachments: any[] }) {
</figure>
</Match>
<Match when={getRenderType(item()) === "audio"}>
<Audio class="w-full" url={getUrl(item())} caption={item().filename} />
<Audio class="p-5 flex flex-col items-center justify-center gap-2 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} />

View File

@ -1,7 +1,8 @@
import { createSignal, For, Show } from "solid-js";
import { getAtk, useUserinfo } from "../stores/userinfo.tsx";
import PostAttachments from "./PostAttachments.tsx";
import { SolidMarkdown } from "solid-markdown";
import * as marked from "marked";
import DOMPurify from "dompurify";
export default function PostItem(props: {
post: any,
@ -37,9 +38,7 @@ export default function PostItem(props: {
}
const content = (
<article class="prose">
<SolidMarkdown children={props.post.content} />
</article>
<article class="prose" innerHTML={DOMPurify.sanitize(marked.parse(props.post.content) as string)} />
);
return (
@ -64,7 +63,7 @@ export default function PostItem(props: {
</div>
</a>
</Show>
<div class="px-7">
<div class="px-7 py-5">
<h2 class="card-title">{props.post.title}</h2>
<Show when={!props.noClick} fallback={content}>
@ -73,7 +72,7 @@ export default function PostItem(props: {
</a>
</Show>
<div class="mt-2 mb-5 flex gap-2">
<div class="mt-2 flex gap-2">
<For each={props.post.categories}>
{item =>
<a href={`/search?category=${item.alias}`} class="badge badge-primary">
@ -93,7 +92,7 @@ export default function PostItem(props: {
</div>
<Show when={props.post.attachments?.length > 0}>
<div class="pb-5">
<div>
<PostAttachments attachments={props.post.attachments ?? []} />
</div>
</Show>

View File

@ -11,7 +11,7 @@ import { Route, Router } from "@solidjs/router";
import "@fortawesome/fontawesome-free/css/all.css";
import RootLayout from "./layouts/RootLayout.tsx";
import Feed from "./pages/feed.tsx";
import Feed from "./pages/view.tsx";
import Global from "./pages/global.tsx";
import PostReference from "./pages/post.tsx";
import { UserinfoProvider } from "./stores/userinfo.tsx";

View File

@ -1,6 +1,6 @@
.wrapper {
display: grid;
grid-template-columns: fit-content(100%);
grid-template-columns: 1fr;
column-gap: 20px;
max-height: calc(100vh - 64px);

View File

@ -1,4 +1,4 @@
import styles from "./feed.module.css";
import styles from "./view.module.css";
export default function DashboardPage(props: any) {
return (