Merge branch 'placed-pixels' into 'main'
Pixel pulses & whois display name fix See merge request sc07/canvas!21
This commit is contained in:
commit
95b61fa050
|
@ -13,6 +13,7 @@ import { KeybindManager } from "../lib/keybinds";
|
|||
import { BlankOverlay } from "./Overlay/BlankOverlay";
|
||||
import { HeatmapOverlay } from "./Overlay/HeatmapOverlay";
|
||||
import { useTemplateContext } from "../contexts/TemplateContext";
|
||||
import { PixelPulses } from "./Overlay/PixelPulses";
|
||||
|
||||
export const CanvasWrapper = () => {
|
||||
const { config } = useAppContext();
|
||||
|
@ -23,6 +24,7 @@ export const CanvasWrapper = () => {
|
|||
<PanZoomWrapper>
|
||||
<BlankOverlay />
|
||||
<HeatmapOverlay />
|
||||
<PixelPulses />
|
||||
{config && <Template />}
|
||||
<CanvasInner />
|
||||
<Cursor />
|
||||
|
|
|
@ -7,7 +7,7 @@ export const User = () => {
|
|||
return user ? (
|
||||
<Card>
|
||||
<UserElement
|
||||
name={user.user.username}
|
||||
name={user.user.display_name || user.user.username}
|
||||
description={user.service.instance.hostname}
|
||||
avatarProps={{
|
||||
showFallback: true,
|
||||
|
|
|
@ -2,7 +2,7 @@ import { Slider, Spinner, Switch } from "@nextui-org/react";
|
|||
import { useAppContext } from "../../contexts/AppContext";
|
||||
|
||||
export const OverlaySettings = () => {
|
||||
const { blankOverlay, setBlankOverlay, heatmapOverlay, setHeatmapOverlay } =
|
||||
const { blankOverlay, setBlankOverlay, heatmapOverlay, setHeatmapOverlay, pixelPulses, setPixelPulses } =
|
||||
useAppContext();
|
||||
|
||||
return (
|
||||
|
@ -56,6 +56,15 @@ export const OverlaySettings = () => {
|
|||
getValue={(v) => (v as number) * 100 + "%"}
|
||||
/>
|
||||
)}
|
||||
|
||||
<Switch
|
||||
isSelected={pixelPulses}
|
||||
onValueChange={(v) =>
|
||||
setPixelPulses(v)
|
||||
}
|
||||
>
|
||||
New Pixel Pulses
|
||||
</Switch>
|
||||
</section>
|
||||
</div>
|
||||
);
|
||||
|
|
|
@ -0,0 +1,59 @@
|
|||
import { CSSProperties, useEffect, useState } from "react";
|
||||
import { useAppContext } from "../../contexts/AppContext";
|
||||
import network from "../../lib/network";
|
||||
import { Pixel } from "@sc07-canvas/lib/src/net";
|
||||
import { Canvas } from "../../lib/canvas";
|
||||
|
||||
export const PixelPulses = () => {
|
||||
const { pixelPulses } = useAppContext();
|
||||
const [pulses, setPulses] = useState<JSX.Element[]>([]);
|
||||
|
||||
useEffect(() => {
|
||||
function handlePixel({ x, y, color }: Pixel) {
|
||||
if (!pixelPulses) {
|
||||
return;
|
||||
}
|
||||
|
||||
const paletteColor = Canvas.instance?.Pallete.getColor(color);
|
||||
|
||||
const pulseStyle: CSSProperties = {
|
||||
position: "absolute",
|
||||
zIndex: "100",
|
||||
left: x + "px",
|
||||
top: y + "px",
|
||||
width: "50px",
|
||||
height: "50px",
|
||||
border: `1px solid #${paletteColor?.hex || "000"}`, // default to black in the case it fails to load, but that shouldn't happen
|
||||
borderRadius: "100px",
|
||||
transform: "translate(-24.5px, -24.5px)",
|
||||
animationName: "pixel-pulse",
|
||||
animationTimingFunction: "ease-in-out",
|
||||
animationDuration: "2s",
|
||||
animationFillMode: "forwards",
|
||||
};
|
||||
|
||||
// used in the case of two pixels coming through for the same position
|
||||
// rare, but causes issues with react
|
||||
// even if the pixels are close to eachother, the ms will be different
|
||||
const timestamp = Date.now();
|
||||
|
||||
const pulseElement = (
|
||||
<div key={`${x}-${y}-${timestamp}`} style={pulseStyle}></div>
|
||||
);
|
||||
|
||||
setPulses((prevPulses) => [...prevPulses, pulseElement]);
|
||||
|
||||
setTimeout(() => {
|
||||
setPulses((prevPulses) => prevPulses.slice(1)); // Remove the oldest pulse after 3700ms
|
||||
}, 2500);
|
||||
}
|
||||
|
||||
network.on("pixel", handlePixel);
|
||||
|
||||
return () => {
|
||||
network.off("pixel", handlePixel);
|
||||
};
|
||||
}, [pixelPulses]);
|
||||
|
||||
return <div>{pulses}</div>;
|
||||
};
|
|
@ -2,7 +2,7 @@ import { faMessage, faWarning } from "@fortawesome/free-solid-svg-icons";
|
|||
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
||||
import { Avatar, Button, Link, Spinner, User } from "@nextui-org/react";
|
||||
import { ClientConfig } from "@sc07-canvas/lib/src/net";
|
||||
import { MouseEvent, useEffect, useState } from "react";
|
||||
import { MouseEvent, useEffect, useMemo, useState } from "react";
|
||||
import { toast } from "react-toastify";
|
||||
import { useAppContext } from "../../contexts/AppContext";
|
||||
|
||||
|
@ -72,11 +72,26 @@ export const UserCard = ({ user }: { user: IUser }) => {
|
|||
setProfile(user.sub);
|
||||
};
|
||||
|
||||
const name = useMemo(() => {
|
||||
if (!user || !user.sub) {
|
||||
return 'Unknown'
|
||||
}
|
||||
|
||||
const regex = /^(.*)@/;
|
||||
const match = user.sub.match(regex);
|
||||
|
||||
if (match) {
|
||||
return match[1];
|
||||
}
|
||||
|
||||
return 'Unknown'
|
||||
}, [user])
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-1">
|
||||
<div className="flex flex-row space-between p-2">
|
||||
<User
|
||||
name={user?.display_name || 'Unknown'}
|
||||
name={user?.display_name || name}
|
||||
description={user?.sub || 'Unknown'}
|
||||
avatarProps={{
|
||||
showFallback: true,
|
||||
|
|
|
@ -15,7 +15,7 @@ export const SidebarBase = ({children, shown, icon, setSidebarShown, title, desc
|
|||
return (
|
||||
<div>
|
||||
<motion.div
|
||||
className={`absolute w-screen h-screen z-50 left-0 top-0 bg-black`}
|
||||
className={`absolute w-screen h-screen z-50 left-0 top-0 bg-black pointer-events-none`}
|
||||
initial={{ opacity: 0, visibility: 'hidden' }}
|
||||
animate={{ opacity: shown ? 0.25 : 0, visibility: shown ? 'visible' : 'hidden' }}
|
||||
transition={{ type: 'spring', stiffness: 50 }}
|
||||
|
|
|
@ -38,6 +38,8 @@ interface IAppContext {
|
|||
setBlankOverlay: React.Dispatch<React.SetStateAction<IMapOverlay>>;
|
||||
heatmapOverlay: IMapOverlay;
|
||||
setHeatmapOverlay: React.Dispatch<React.SetStateAction<IMapOverlay>>;
|
||||
pixelPulses: boolean;
|
||||
setPixelPulses: (state: boolean) => void
|
||||
|
||||
profile?: string; // sub
|
||||
setProfile: (v?: string) => void;
|
||||
|
@ -123,6 +125,7 @@ export const AppContext = ({ children }: PropsWithChildren) => {
|
|||
opacity: 1,
|
||||
loading: false,
|
||||
});
|
||||
const [pixelPulses, setPixelPulses] = useState<boolean>(false)
|
||||
|
||||
const [profile, setProfile] = useState<string>();
|
||||
|
||||
|
@ -229,6 +232,8 @@ export const AppContext = ({ children }: PropsWithChildren) => {
|
|||
setBlankOverlay,
|
||||
heatmapOverlay,
|
||||
setHeatmapOverlay,
|
||||
pixelPulses,
|
||||
setPixelPulses,
|
||||
profile,
|
||||
setProfile,
|
||||
infoSidebar,
|
||||
|
|
|
@ -201,6 +201,19 @@ main {
|
|||
}
|
||||
}
|
||||
|
||||
@keyframes pixel-pulse {
|
||||
from {
|
||||
width: 50px;
|
||||
height: 50px;
|
||||
transform: translate(-24.5px, -24.5px);
|
||||
}
|
||||
to {
|
||||
width: 10px;
|
||||
height: 10px;
|
||||
transform: translate(-4.5px, -4.5px);
|
||||
}
|
||||
}
|
||||
|
||||
@import "./components/Toolbar/Palette.scss";
|
||||
@import "./components/Templating/Template.scss";
|
||||
@import "./board.scss";
|
||||
|
|
|
@ -227,6 +227,7 @@ export type AuthSession = {
|
|||
};
|
||||
user: {
|
||||
username: string;
|
||||
display_name?: string;
|
||||
picture_url?: string;
|
||||
};
|
||||
};
|
||||
|
|
Loading…
Reference in New Issue