mirror of
https://github.com/DorkSquadRR/DorkNet.git
synced 2026-10-26 15:38:45 -07:00
Import march-2020-03-10 from private repo (scrubbed 2026-05-27)
Targets Rec Room 2020.03.10 client (also serves 2020.03.06).
Re-import after adding:
- DorkNet.ClientMod/dorknet-clientmod.json.template — config schema
the launcher's manifest-driven patcher renders into UserData/.
- tools/build-patcher-zip.ps1 — produces dorknet-clientpatch-{key}.zip
for v1-march-* Release uploads.
- .github/workflows/release.yml — on tag push publishes both
dorknet-server-march_2020_03_10-win-x64.zip and
dorknet-clientpatch-march_2020_03_10.zip as Release assets.
Same scrub rules as december; tools/build-patcher-zip.ps1 added to
the maintainer-side allow-list so it survives.
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
|
||||
|
||||
type Kind = 'info' | 'success' | 'error';
|
||||
interface ToastMsg { id: number; kind: Kind; text: string }
|
||||
|
||||
interface Ctx { push: (text: string, kind?: Kind) => void }
|
||||
const ToastCtx = createContext<Ctx | null>(null);
|
||||
|
||||
export function useToast(): Ctx {
|
||||
const ctx = useContext(ToastCtx);
|
||||
if (!ctx) throw new Error('useToast must be used inside <ToastProvider>');
|
||||
return ctx;
|
||||
}
|
||||
|
||||
export function ToastProvider({ children }: { children: React.ReactNode }) {
|
||||
const [items, setItems] = useState<ToastMsg[]>([]);
|
||||
const push = useCallback((text: string, kind: Kind = 'info') => {
|
||||
const id = Date.now() + Math.random();
|
||||
setItems(prev => [...prev, { id, kind, text }]);
|
||||
setTimeout(() => setItems(prev => prev.filter(t => t.id !== id)), 4000);
|
||||
}, []);
|
||||
|
||||
return (
|
||||
<ToastCtx.Provider value={{ push }}>
|
||||
{children}
|
||||
<div className="pointer-events-none fixed bottom-6 right-6 z-50 flex flex-col gap-2">
|
||||
{items.map(t => (
|
||||
<ToastItem key={t.id} msg={t} />
|
||||
))}
|
||||
</div>
|
||||
</ToastCtx.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
function ToastItem({ msg }: { msg: ToastMsg }) {
|
||||
const [open, setOpen] = useState(false);
|
||||
useEffect(() => { requestAnimationFrame(() => setOpen(true)); }, []);
|
||||
const colors =
|
||||
msg.kind === 'success' ? 'bg-success/15 text-success border-success/30'
|
||||
: msg.kind === 'error' ? 'bg-danger/15 text-danger border-danger/30'
|
||||
: 'bg-ink-800 text-ink-100 border-ink-700';
|
||||
return (
|
||||
<div
|
||||
className={`pointer-events-auto min-w-[240px] max-w-sm rounded-lg border px-3.5 py-2 text-sm shadow-card transition-all duration-200 ${colors} ${open ? 'translate-x-0 opacity-100' : 'translate-x-2 opacity-0'}`}
|
||||
role="status"
|
||||
>
|
||||
{msg.text}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user