💄 UX Optimized
This commit is contained in:
parent
8d1cb9d9c0
commit
86e184a803
@ -11,17 +11,18 @@
|
|||||||
"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",
|
"artplayer": "^5.1.1",
|
||||||
|
"dompurify": "^3.0.8",
|
||||||
"flv.js": "^1.6.2",
|
"flv.js": "^1.6.2",
|
||||||
"hls.js": "^1.5.3",
|
"hls.js": "^1.5.3",
|
||||||
|
"marked": "^12.0.0",
|
||||||
"medium-zoom": "^1.1.0",
|
"medium-zoom": "^1.1.0",
|
||||||
"solid-js": "^1.8.7",
|
"solid-js": "^1.8.7",
|
||||||
"solid-markdown": "^2.0.0",
|
|
||||||
"universal-cookie": "^7.0.2"
|
"universal-cookie": "^7.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/typography": "^0.5.10",
|
"@tailwindcss/typography": "^0.5.10",
|
||||||
|
"@types/dompurify": "^3.0.5",
|
||||||
"autoprefixer": "^10.4.17",
|
"autoprefixer": "^10.4.17",
|
||||||
"daisyui": "^4.6.1",
|
"daisyui": "^4.6.1",
|
||||||
"postcss": "^8.4.33",
|
"postcss": "^8.4.33",
|
||||||
|
@ -3,14 +3,10 @@ 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 Artplayer from "artplayer";
|
||||||
import HlsJs from "hls.js";
|
import HlsJs from "hls.js";
|
||||||
import FlvJs from "flv.js";
|
import FlvJs from "flv.js";
|
||||||
|
|
||||||
import "aplayer/dist/APlayer.min.css";
|
|
||||||
|
|
||||||
function Video({ url, ...rest }: any) {
|
function Video({ url, ...rest }: any) {
|
||||||
let container: any;
|
let container: any;
|
||||||
|
|
||||||
@ -21,24 +17,24 @@ function Video({ url, ...rest }: any) {
|
|||||||
hls.loadSource(url);
|
hls.loadSource(url);
|
||||||
hls.attachMedia(video);
|
hls.attachMedia(video);
|
||||||
art.hls = hls;
|
art.hls = hls;
|
||||||
art.on('destroy', () => hls.destroy());
|
art.on("destroy", () => hls.destroy());
|
||||||
} else if (video.canPlayType('application/vnd.apple.mpegurl')) {
|
} else if (video.canPlayType("application/vnd.apple.mpegurl")) {
|
||||||
video.src = url;
|
video.src = url;
|
||||||
} else {
|
} else {
|
||||||
art.notice.show = 'Unsupported playback format: m3u8';
|
art.notice.show = "Unsupported playback format: m3u8";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function playFlv(video: HTMLVideoElement, url: string, art: Artplayer) {
|
function playFlv(video: HTMLVideoElement, url: string, art: Artplayer) {
|
||||||
if (FlvJs.isSupported()) {
|
if (FlvJs.isSupported()) {
|
||||||
if (art.flv) art.flv.destroy();
|
if (art.flv) art.flv.destroy();
|
||||||
const flv = FlvJs.createPlayer({ type: 'flv', url });
|
const flv = FlvJs.createPlayer({ type: "flv", url });
|
||||||
flv.attachMediaElement(video);
|
flv.attachMediaElement(video);
|
||||||
flv.load();
|
flv.load();
|
||||||
art.flv = flv;
|
art.flv = flv;
|
||||||
art.on('destroy', () => flv.destroy());
|
art.on("destroy", () => flv.destroy());
|
||||||
} else {
|
} 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,
|
subtitleOffset: true,
|
||||||
fullscreen: true,
|
fullscreen: true,
|
||||||
fullscreenWeb: true,
|
fullscreenWeb: true,
|
||||||
screenshot: true,
|
|
||||||
autoPlayback: true,
|
|
||||||
airplay: true,
|
|
||||||
theme: "#49509e",
|
theme: "#49509e",
|
||||||
customType: {
|
customType: {
|
||||||
m3u8: playM3u8,
|
m3u8: playM3u8,
|
||||||
flv: playFlv,
|
flv: playFlv
|
||||||
},
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -71,21 +64,12 @@ function Video({ url, ...rest }: any) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Audio({ url, caption, ...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 (
|
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>
|
||||||
|
|
||||||
<div class="mt-5">
|
<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>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -140,7 +124,8 @@ export default function PostAttachments(props: { attachments: any[] }) {
|
|||||||
</figure>
|
</figure>
|
||||||
</Match>
|
</Match>
|
||||||
<Match when={getRenderType(item()) === "audio"}>
|
<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>
|
||||||
<Match when={getRenderType(item()) === "video"}>
|
<Match when={getRenderType(item()) === "video"}>
|
||||||
<Video class="h-[360px] w-full" url={getUrl(item())} caption={item().filename} />
|
<Video class="h-[360px] w-full" url={getUrl(item())} caption={item().filename} />
|
||||||
|
@ -1,7 +1,8 @@
|
|||||||
import { createSignal, For, Show } from "solid-js";
|
import { createSignal, For, Show } from "solid-js";
|
||||||
import { getAtk, useUserinfo } from "../stores/userinfo.tsx";
|
import { getAtk, useUserinfo } from "../stores/userinfo.tsx";
|
||||||
import PostAttachments from "./PostAttachments.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: {
|
export default function PostItem(props: {
|
||||||
post: any,
|
post: any,
|
||||||
@ -37,9 +38,7 @@ export default function PostItem(props: {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const content = (
|
const content = (
|
||||||
<article class="prose">
|
<article class="prose" innerHTML={DOMPurify.sanitize(marked.parse(props.post.content) as string)} />
|
||||||
<SolidMarkdown children={props.post.content} />
|
|
||||||
</article>
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@ -64,7 +63,7 @@ export default function PostItem(props: {
|
|||||||
</div>
|
</div>
|
||||||
</a>
|
</a>
|
||||||
</Show>
|
</Show>
|
||||||
<div class="px-7">
|
<div class="px-7 py-5">
|
||||||
<h2 class="card-title">{props.post.title}</h2>
|
<h2 class="card-title">{props.post.title}</h2>
|
||||||
|
|
||||||
<Show when={!props.noClick} fallback={content}>
|
<Show when={!props.noClick} fallback={content}>
|
||||||
@ -73,7 +72,7 @@ export default function PostItem(props: {
|
|||||||
</a>
|
</a>
|
||||||
</Show>
|
</Show>
|
||||||
|
|
||||||
<div class="mt-2 mb-5 flex gap-2">
|
<div class="mt-2 flex gap-2">
|
||||||
<For each={props.post.categories}>
|
<For each={props.post.categories}>
|
||||||
{item =>
|
{item =>
|
||||||
<a href={`/search?category=${item.alias}`} class="badge badge-primary">
|
<a href={`/search?category=${item.alias}`} class="badge badge-primary">
|
||||||
@ -93,7 +92,7 @@ export default function PostItem(props: {
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Show when={props.post.attachments?.length > 0}>
|
<Show when={props.post.attachments?.length > 0}>
|
||||||
<div class="pb-5">
|
<div>
|
||||||
<PostAttachments attachments={props.post.attachments ?? []} />
|
<PostAttachments attachments={props.post.attachments ?? []} />
|
||||||
</div>
|
</div>
|
||||||
</Show>
|
</Show>
|
||||||
|
@ -11,7 +11,7 @@ import { Route, Router } from "@solidjs/router";
|
|||||||
import "@fortawesome/fontawesome-free/css/all.css";
|
import "@fortawesome/fontawesome-free/css/all.css";
|
||||||
|
|
||||||
import RootLayout from "./layouts/RootLayout.tsx";
|
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 Global from "./pages/global.tsx";
|
||||||
import PostReference from "./pages/post.tsx";
|
import PostReference from "./pages/post.tsx";
|
||||||
import { UserinfoProvider } from "./stores/userinfo.tsx";
|
import { UserinfoProvider } from "./stores/userinfo.tsx";
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
.wrapper {
|
.wrapper {
|
||||||
display: grid;
|
display: grid;
|
||||||
grid-template-columns: fit-content(100%);
|
grid-template-columns: 1fr;
|
||||||
column-gap: 20px;
|
column-gap: 20px;
|
||||||
|
|
||||||
max-height: calc(100vh - 64px);
|
max-height: calc(100vh - 64px);
|
@ -1,4 +1,4 @@
|
|||||||
import styles from "./feed.module.css";
|
import styles from "./view.module.css";
|
||||||
|
|
||||||
export default function DashboardPage(props: any) {
|
export default function DashboardPage(props: any) {
|
||||||
return (
|
return (
|
Loading…
Reference in New Issue
Block a user