rc-1
This commit is contained in:
@@ -0,0 +1,88 @@
|
||||
import { useEffect, useMemo, useState } from 'react'
|
||||
import type { BackendArt } from '../../functions/BackendTypes'
|
||||
import { KEY_PREFIX_UPLOAD, setTitle, stateRecover } from '../../functions/Route'
|
||||
import { BackendFetch } from '../../functions/Backend'
|
||||
import { wtEvent } from '../../functions/Watchtower'
|
||||
|
||||
import LayoutBrowser, { type RecoverForLayoutBrowser } from '../layout/LayoutBrowser'
|
||||
import HeaderMessage from '../layout/HeaderMessage'
|
||||
import HeaderLoading from '../layout/HeaderLoading'
|
||||
import HeaderError from '../layout/HeaderError'
|
||||
|
||||
export default function ViewPersonal() {
|
||||
const recovered = stateRecover<RecoverForLayoutBrowser>()
|
||||
const [isLoading, setLoading] = useState(true)
|
||||
const [items, setItems] = useState(recovered?.items ?? [])
|
||||
const message = useMemo(() => `View: Personal <Count: ${items.length}>`, [items])
|
||||
|
||||
useEffect(() => {
|
||||
Promise.allSettled(
|
||||
Object.keys(localStorage)
|
||||
.filter((key) => key.startsWith(KEY_PREFIX_UPLOAD))
|
||||
.map((key) => key.slice(KEY_PREFIX_UPLOAD.length))
|
||||
.sort((a, b) => Number(BigInt(b) - BigInt(a)))
|
||||
.map(
|
||||
(id) =>
|
||||
new Promise<BackendArt>(async (resolve, reject) => {
|
||||
// Check Caches
|
||||
const item = recovered?.items.find((i) => i.id === id)
|
||||
if (item) {
|
||||
return resolve(item)
|
||||
}
|
||||
|
||||
// Fetch from API
|
||||
const resp = await BackendFetch<BackendArt>(`/art/${id}`)
|
||||
if (!resp.success) {
|
||||
if (resp.status === 404) {
|
||||
// Was probably deleted, remove from storage so
|
||||
// this client can stop spamming the backend.
|
||||
localStorage.removeItem(KEY_PREFIX_UPLOAD + id)
|
||||
}
|
||||
console.error(`Request for Animation (${id}) failed:`, resp)
|
||||
return reject()
|
||||
}
|
||||
resolve(resp.json)
|
||||
}),
|
||||
),
|
||||
).then((p) => {
|
||||
const items = p.filter((p) => p.status === 'fulfilled').map((p) => p.value)
|
||||
setItems(items)
|
||||
setLoading(false)
|
||||
|
||||
wtEvent('view_personal', {
|
||||
ids: items.map((i) => i.id),
|
||||
item_total: items.length,
|
||||
item_error: p.filter((p) => p.status === 'rejected').length,
|
||||
item_count: p.filter((p) => p.status === 'fulfilled').length,
|
||||
nsfw_count: items.filter((i) => i.rating >= 0.8).length,
|
||||
nsfw_rating: items.reduce((sum, i) => sum + i.rating, 0) / items.length || 0,
|
||||
})
|
||||
})
|
||||
}, [])
|
||||
|
||||
if (isLoading) {
|
||||
return (
|
||||
<>
|
||||
<HeaderMessage label="Retrieving Uploads" />
|
||||
<HeaderLoading reason="" />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
if (!items.length) {
|
||||
return (
|
||||
<>
|
||||
<HeaderMessage label={message} />
|
||||
<HeaderError reason="No past uploads were found on this device. <br> Expecting something? Restore your lost data in Settings." />
|
||||
</>
|
||||
)
|
||||
}
|
||||
|
||||
setTitle('Personal')
|
||||
return (
|
||||
<>
|
||||
<HeaderMessage label={message} />
|
||||
<LayoutBrowser items={items} position={recovered?.position ?? 0} />
|
||||
</>
|
||||
)
|
||||
}
|
||||
Reference in New Issue
Block a user