Improve article

This commit is contained in:
2025-05-27 18:46:32 +08:00
parent 7bcae71495
commit c4c2d7d9f7
4 changed files with 98 additions and 81 deletions

View File

@@ -9,27 +9,27 @@ export default function Pagination({page, setPage, totalPages}: {
const items: ReactNode[] = []; const items: ReactNode[] = [];
if (page > 1) { if (page > 1) {
items.push(<button className="join-item btn" onClick={() => setPage(1)}>1</button>); items.push(<button key={"btn-1"} className="join-item btn" onClick={() => setPage(1)}>1</button>);
} }
if (page - 2 > 1) { if (page - 2 > 1) {
items.push(<button className="join-item btn">...</button>); items.push(<button key={"btn-2"} className="join-item btn">...</button>);
} }
if (page - 1 > 1) { if (page - 1 > 1) {
items.push(<button className="join-item btn" onClick={() => setPage(page - 1)}>{page - 1}</button>); items.push(<button key={"btn-3"} className="join-item btn" onClick={() => setPage(page - 1)}>{page - 1}</button>);
} }
items.push(<button className="join-item btn btn-active">{page}</button>); items.push(<button key={"btn-4"} className="join-item btn btn-active">{page}</button>);
if (page + 1 < totalPages) { if (page + 1 < totalPages) {
items.push(<button className="join-item btn" onClick={() => setPage(page + 1)}>{page + 1}</button>); items.push(<button key={"btn-5"} className="join-item btn" onClick={() => setPage(page + 1)}>{page + 1}</button>);
} }
if (page + 2 < totalPages) { if (page + 2 < totalPages) {
items.push(<button className="join-item btn">...</button>); items.push(<button key={"btn-6"} className="join-item btn">...</button>);
} }
if (page < totalPages) { if (page < totalPages) {
items.push(<button className="join-item btn" onClick={() => setPage(totalPages)}>{totalPages}</button>); items.push(<button key={"btn-7"} className="join-item btn" onClick={() => setPage(totalPages)}>{totalPages}</button>);
} }
return <div className="join shadow rounded-field"> return <div className="join shadow rounded-field">
<button className={`join-item btn`} onClick={() => { <button key={"btn-prev"} className={`join-item btn`} onClick={() => {
if (page > 1) { if (page > 1) {
setPage(page - 1); setPage(page - 1);
} }
@@ -37,7 +37,7 @@ export default function Pagination({page, setPage, totalPages}: {
<MdChevronLeft size={20} className="opacity-50"/> <MdChevronLeft size={20} className="opacity-50"/>
</button> </button>
{items} {items}
<button className={`join-item btn`} onClick={() => { <button key={"btn-next"} className={`join-item btn`} onClick={() => {
if (page < totalPages) { if (page < totalPages) {
setPage(page + 1); setPage(page + 1);
} }

View File

@@ -1,4 +1,8 @@
article { article {
& {
color: var(--color-base-content)
}
h1 { h1 {
font-size: 20px; font-size: 20px;
font-weight: bold; font-weight: bold;
@@ -91,6 +95,10 @@ article {
.line-break { .line-break {
white-space: pre-wrap; white-space: pre-wrap;
} }
iframe{
width: 100%;
height: 100%;
}
} }
a.no-underline { a.no-underline {

View File

@@ -60,7 +60,7 @@ class Network {
return; return;
} }
const res = await this.getMe() const res = await this.getMe()
if (!res.success && res.message.includes("Invalid token")) { if (!res.success && (res.message.includes("Invalid token") || res.message.includes("User not found"))) {
app.token = null; app.token = null;
app.user = null; app.user = null;
app.saveData(); app.saveData();

View File

@@ -241,34 +241,29 @@ function Article({resource}: { resource: ResourceDetails }) {
"p": ({node, ...props}) => { "p": ({node, ...props}) => {
if (typeof props.children === "object" && (props.children as ReactElement).type === "strong") { if (typeof props.children === "object" && (props.children as ReactElement).type === "strong") {
// @ts-ignore // @ts-ignore
const child = (props.children as ReactElement).props.children.toString() const child = (props.children as ReactElement).props.children.toString() as string
if (child.startsWith("<iframe")) { if (child.startsWith("<iframe")) {
return <div dangerouslySetInnerHTML={{
// @ts-ignore // @ts-ignore
__html: (props.children as ReactElement).props.children let html = child;
let splits = html.split(" ")
splits = splits.filter((s: string) => {
return !(s.startsWith("width") || s.startsWith("height") || s.startsWith("class") || s.startsWith("style"));
})
html = splits.join(" ")
return <div className={`w-full max-w-xl rounded-xl overflow-clip ${html.includes("youtube") ? "aspect-video" : "h-48 sm:h-64"}`} dangerouslySetInnerHTML={{
__html: html
}}></div> }}></div>
} }
} } else if (typeof props.children === "object" && (props.children as ReactElement).type === "a") {
return <p {...props}>{props.children}</p> const a = props.children as ReactElement
}, const childProps = a.props as any
"a": ({node, ...props}) => { const href = childProps.href as string
const href = props.href as string if (href.startsWith(window.location.origin) || href.startsWith("/")) {
if (href.startsWith("https://store.steampowered.com/app/")) {
const appId = href.substring("https://store.steampowered.com/app/".length).split("/")[0]
if (!Number.isNaN(Number(appId))) {
return <iframe
src={`https://store.steampowered.com/widget/${appId}/`}
width="100%"
height="190"
className={"max-w-xl my-2"}
></iframe>
}
} else if (href.startsWith(window.location.origin) || href.startsWith("/")) {
let path = href let path = href
if (path.startsWith(window.location.origin)) { if (path.startsWith(window.location.origin)) {
path = path.substring(window.location.origin.length) path = path.substring(window.location.origin.length)
} }
const content = props.children?.toString() const content = childProps.children?.toString()
if (path.startsWith("/resources/")) { if (path.startsWith("/resources/")) {
const id = path.substring("/resources/".length) const id = path.substring("/resources/".length)
for (const r of resource.related) { for (const r of resource.related) {
@@ -279,8 +274,11 @@ function Article({resource}: { resource: ResourceDetails }) {
}}> }}>
{r.image ? <figure> {r.image ? <figure>
<img <img
className="w-full h-40 sm:h-full sm:w-48 object-cover" className="w-full h-40 max-h-72 sm:h-full sm:w-48 md:w-58 lg:w-72 object-cover"
src={network.getImageUrl(r.image!.id)} src={network.getImageUrl(r.image!.id)}
style={{
boxShadow: "0 0 0 rgba(0, 0, 0)",
}}
alt="Cover"/> alt="Cover"/>
</figure> : null} </figure> : null}
<div className="card-body" style={{padding: "1rem"}}> <div className="card-body" style={{padding: "1rem"}}>
@@ -293,11 +291,11 @@ function Article({resource}: { resource: ResourceDetails }) {
} }
} }
// @ts-ignore // @ts-ignore
if (props.children?.length === 2) { if (childProps.children?.length === 2) {
// @ts-ignore // @ts-ignore
const first = props.children[0] as ReactNode const first = childProps.children[0] as ReactNode
// @ts-ignore // @ts-ignore
const second = props.children[1] as ReactNode const second = childProps.children[1] as ReactNode
if (typeof first === "object" && (typeof second === "string" || typeof second === "object")) { if (typeof first === "object" && (typeof second === "string" || typeof second === "object")) {
const img = first as ReactElement const img = first as ReactElement
@@ -316,8 +314,19 @@ function Article({resource}: { resource: ResourceDetails }) {
} }
} }
} }
return <a href={href} target={"_blank"}>{props.children}</a> if (href.startsWith("https://store.steampowered.com/app/")) {
const appId = href.substring("https://store.steampowered.com/app/".length).split("/")[0]
if (!Number.isNaN(Number(appId))) {
return <div className={"max-w-xl h-52 sm:h-48 my-2"}>
<iframe
src={`https://store.steampowered.com/widget/${appId}/`}
></iframe>
</div>
} }
}
}
return <p {...props}>{props.children}</p>
},
}}>{resource.article}</Markdown> }}>{resource.article}</Markdown>
</article> </article>
} }