rc-1
This commit is contained in:
@@ -0,0 +1,199 @@
|
||||
import { type MouseEventHandler, forwardRef, useEffect, useMemo, useState } from 'react'
|
||||
import type { BackendArt } from '../../functions/BackendTypes'
|
||||
import { WEB_BASE } from '../../functions/Backend'
|
||||
import { wtEvent } from '../../functions/Watchtower'
|
||||
import { toast } from '../../functions/Context'
|
||||
import './styles/ModalEmbed.css'
|
||||
|
||||
import VectorBackgroundEmbed from '../../vectors/background-embed.svg'
|
||||
import HeaderMessage from './HeaderMessage'
|
||||
import InputButtonRow from '../inputs/ButtonRow'
|
||||
import InputButton from '../inputs/Button'
|
||||
import InputDescription from '../inputs/Description'
|
||||
import InputLabel from '../inputs/Label'
|
||||
|
||||
interface PropsForModalEmbed {
|
||||
item: BackendArt
|
||||
onClose: MouseEventHandler<HTMLButtonElement>
|
||||
}
|
||||
|
||||
export default forwardRef<HTMLDialogElement, PropsForModalEmbed>(function ModalEmbed(
|
||||
{ item, onClose }: PropsForModalEmbed,
|
||||
ref,
|
||||
) {
|
||||
// Keep User Preferences
|
||||
const KEY_QUALITY = 'preference_embed_quality'
|
||||
const KEY_SCALE = 'preference_embed_scale'
|
||||
|
||||
const [preferQuality, setQuality] = useState<'standard' | 'transparent'>(
|
||||
(() => {
|
||||
let raw = localStorage.getItem(KEY_QUALITY) ?? 'standard'
|
||||
if (raw !== 'standard' && raw !== 'transparent') {
|
||||
return 'standard'
|
||||
} else {
|
||||
return raw
|
||||
}
|
||||
})(),
|
||||
)
|
||||
|
||||
const [preferScale, setScale] = useState<number>(
|
||||
(() => {
|
||||
let raw = localStorage.getItem(KEY_SCALE) ?? String('1')
|
||||
let val = parseFloat(raw)
|
||||
if (isNaN(val) || val < 0 || val > 1) return 1
|
||||
return val
|
||||
})(),
|
||||
)
|
||||
|
||||
useEffect(() => localStorage.setItem(KEY_QUALITY, String(preferQuality)), [preferQuality])
|
||||
useEffect(() => localStorage.setItem(KEY_SCALE, String(preferScale)), [preferScale])
|
||||
|
||||
// Calculate Embed Values
|
||||
const embedScale = useMemo(() => {
|
||||
const maxDim = Math.max(item.width, item.height)
|
||||
const baseScale = maxDim > 640 ? 640 / maxDim : 1
|
||||
return baseScale * preferScale
|
||||
}, [item.width, item.height, preferScale])
|
||||
|
||||
const embedHeight = useMemo(() => (item.height * embedScale) | 0, [embedScale])
|
||||
const embedWidth = useMemo(() => (item.width * embedScale) | 0, [embedScale])
|
||||
|
||||
// const embedQuality = useMemo(() => {
|
||||
// if (preferQuality === 'standard.avif') return 'standard'
|
||||
// return 'transparent'
|
||||
// }, [preferQuality])
|
||||
|
||||
const embedHTML = useMemo(
|
||||
() =>
|
||||
`<iframe src="${WEB_BASE}/embed.html?id=${item.id}&quality=${preferQuality}" width="${embedWidth}" height="${embedHeight}" style="border:none; background: transparent" allowtransparency="true"></iframe>`,
|
||||
[preferQuality, embedScale],
|
||||
)
|
||||
|
||||
function onCopy() {
|
||||
navigator.clipboard.writeText(embedHTML)
|
||||
toast('action-copy', 'Copied Code to Clipboard!')
|
||||
wtEvent('action_animation_embed_copy', {
|
||||
id: item.id,
|
||||
height: embedHeight,
|
||||
width: embedWidth,
|
||||
scale: (embedScale * 100) | 0,
|
||||
quality: preferQuality,
|
||||
})
|
||||
}
|
||||
|
||||
return (
|
||||
<dialog ref={ref} className="modal-embed animation-fall-in animation-caution">
|
||||
<HeaderMessage label="MENU: Embed Generator" />
|
||||
<div className="wrapper">
|
||||
{/* Left-Pane */}
|
||||
<div className="preview">
|
||||
<img className="background animation-fade-in" src={VectorBackgroundEmbed} />
|
||||
<iframe
|
||||
className="animation-fall-in"
|
||||
style={{ border: 'none', background: 'transparent' }}
|
||||
src={`${WEB_BASE}/embed.html?id=${item.id}&quality=${preferQuality}`}
|
||||
width={embedWidth}
|
||||
height={embedHeight}
|
||||
allowTransparency
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Right-Pane */}
|
||||
<div className="toggles">
|
||||
<InputLabel for="" label="Quality" />
|
||||
<InputDescription>
|
||||
We recommend using Standard quality, if you require transparency use Alpha quality.
|
||||
</InputDescription>
|
||||
<InputDescription>
|
||||
Using more than three Alpha embeds may slow down your site, and up to twelve can be displayed at
|
||||
any given time.
|
||||
</InputDescription>
|
||||
<InputButtonRow split={false}>
|
||||
<InputButton
|
||||
id="quality-alpha"
|
||||
label="Alpha"
|
||||
onClick={() => setQuality('transparent')}
|
||||
selected={preferQuality === 'transparent'}
|
||||
disabled={false}
|
||||
rainbow={false}
|
||||
/>
|
||||
<InputButton
|
||||
id="quality-standard"
|
||||
label="Standard"
|
||||
onClick={() => setQuality('standard')}
|
||||
selected={preferQuality === 'standard'}
|
||||
disabled={false}
|
||||
rainbow={false}
|
||||
/>
|
||||
</InputButtonRow>
|
||||
|
||||
<InputLabel for="" label="Scale" />
|
||||
<InputDescription>
|
||||
Sizing is as follows: Small @ 320px; Medium @ 480px; Large @ 640px.
|
||||
</InputDescription>
|
||||
<InputDescription>If an image is too small, it wont get any larger.</InputDescription>
|
||||
<InputButtonRow split={false}>
|
||||
<InputButton
|
||||
id="size-small"
|
||||
label="Small"
|
||||
selected={preferScale < 0.6}
|
||||
onClick={() => setScale(0.5)}
|
||||
disabled={false}
|
||||
rainbow={false}
|
||||
/>
|
||||
<InputButton
|
||||
id="size-medium"
|
||||
label="Medium"
|
||||
selected={preferScale > 0.6 && preferScale < 0.9}
|
||||
onClick={() => setScale(0.75)}
|
||||
disabled={false}
|
||||
rainbow={false}
|
||||
/>
|
||||
<InputButton
|
||||
id="size-large"
|
||||
label="Large"
|
||||
selected={preferScale > 0.9}
|
||||
onClick={() => setScale(1)}
|
||||
disabled={false}
|
||||
rainbow={false}
|
||||
/>
|
||||
</InputButtonRow>
|
||||
|
||||
<InputLabel for="" label="Code" />
|
||||
<InputDescription>
|
||||
Use this code snippet to display this {item.sticker ? 'sticker' : 'animation'} on your website.
|
||||
</InputDescription>
|
||||
<InputDescription>Clicking on the embed will direct users to gifuu in a new tab.</InputDescription>
|
||||
|
||||
<textarea
|
||||
id="input-url"
|
||||
className="input-url"
|
||||
value={embedHTML}
|
||||
onKeyDown={(e) => e.preventDefault()}
|
||||
/>
|
||||
|
||||
<InputLabel for="" label="" /* lazy divider */ />
|
||||
|
||||
<InputButtonRow split={true}>
|
||||
<InputButton
|
||||
id="action-copy"
|
||||
label="Copy HTML"
|
||||
onClick={onCopy}
|
||||
selected={false}
|
||||
disabled={false}
|
||||
rainbow={false}
|
||||
/>
|
||||
<InputButton
|
||||
id="action-exit"
|
||||
label="Exit"
|
||||
onClick={onClose}
|
||||
selected={false}
|
||||
disabled={false}
|
||||
rainbow={false}
|
||||
/>
|
||||
</InputButtonRow>
|
||||
</div>
|
||||
</div>
|
||||
</dialog>
|
||||
)
|
||||
})
|
||||
Reference in New Issue
Block a user