💄 UX Optimized
This commit is contained in:
		| @@ -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> | ||||||
|   ); |   ); | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -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 ( | ||||||
		Reference in New Issue
	
	Block a user