Skip to content

Instantly share code, notes, and snippets.

@mike-at-redspace
Last active March 5, 2023 11:30
Show Gist options
  • Save mike-at-redspace/7cb1a23b7c3ed64319e48c641dda7035 to your computer and use it in GitHub Desktop.
Save mike-at-redspace/7cb1a23b7c3ed64319e48c641dda7035 to your computer and use it in GitHub Desktop.
VotingApp
async function getWebGLContext(canvas) {
try {
return canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
} catch (e) {
return null;
}
}
async function getCanvasFingerprint() {
const canvas = document.createElement('canvas');
canvas.width = 200;
canvas.height = 200;
let hash = '';
const signals = {
pixelRatio: window.devicePixelRatio || 1,
userAgent: window.navigator.userAgent,
// Add more signals here
};
const gl = await getWebGLContext(canvas);
if (gl) {
const regl = Regl(canvas);
const drawCircle = regl({
frag: `
precision mediump float;
varying vec4 color;
void main() {
gl_FragColor = color;
}
`,
vert: `
precision mediump float;
attribute vec2 position;
attribute vec4 color;
varying vec4 vColor;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
vColor = color;
}
`,
attributes: {
position: [
[-1, -1],
[1, -1],
[1, 1],
[-1, 1],
],
color: [
[1, 0, 0, 1],
[0, 1, 0, 1],
[0, 0, 1, 1],
[1, 1, 1, 1],
],
},
elements: [
[0, 1, 2],
[0, 2, 3],
],
});
drawCircle();
const drawGradient = regl({
frag: `
precision mediump float;
varying vec2 uv;
void main() {
gl_FragColor = vec4(uv, 0.0, 1.0);
}
`,
vert: `
precision mediump float;
attribute vec2 position;
varying vec2 uv;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
uv = position * 0.5 + 0.5;
}
`,
attributes: {
position: [
[-1, -1],
[1, -1],
[1, 1],
[-1, 1],
],
},
elements: [
[0, 1, 2],
[0, 2, 3],
],
});
drawGradient();
const dataURL = canvas.toDataURL();
hash = sha256(dataURL).toString();
} else {
const ctx = canvas.getContext('2d');
ctx.fillStyle = 'white';
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.fillStyle = 'black';
ctx.font = '20px sans-serif';
ctx.fillText('Hello, world!', 50, 50);
const gradient = ctx.createLinearGradient(0, 0, canvas.width, canvas.height);
gradient.addColorStop(0, 'red');
gradient.addColorStop(1, 'blue');
ctx.fillStyle = gradient;
const dataURL = canvas.toDataURL();
hash = sha256(dataURL).toString();
}
return hash;
}
function ResultsChart({ votes }) {
// Use a charting library or create your own chart component
return (
<div>
<h2>Results:</h2>
<p>Option 1: {votes.option1}</p>
<p>Option 2: {votes.option2}</p>
<p>Option 3: {votes.option3}</p>
</div>
);
}
import { useState } from 'react';
import getCanvasFingerprint from './getCanvasFingerprint';
function useVote() {
const [isLoading, setIsLoading] = useState(false);
const [error, setError] = useState(null);
async function sendVote(vote) {
setIsLoading(true);
setError(null);
const fingerprint = getCanvasFingerprint();
try {
const response = await fetch('/votes', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ vote, fingerprint }),
});
if (!response.ok) {
throw new Error('Failed to send vote');
}
setIsLoading(false);
} catch (err) {
setError(err.message);
setIsLoading(false);
}
}
return {
isLoading,
error,
sendVote,
};
}
export default useVote;
function VotingApp() {
const [hasVoted, setHasVoted] = useState(false);
const [votes, setVotes] = useState({
option1: 0,
option2: 0,
option3: 0,
});
const { isLoading, error, sendVote } = useVote();
async function handleVote(option) {
setVotes((prevVotes) => ({
...prevVotes,
[option]: prevVotes[option] + 1,
}));
try {
await sendVote(option);
setHasVoted(true);
} catch (err) {
console.error(err);
}
}
return (
<div>
{isLoading && <p>Loading...</p>}
{error && <p>Error: {error}</p>}
{hasVoted ? (
<ResultsChart votes={votes} />
) : (
<VotingOptions onVote={handleVote} />
)}
</div>
);
}
function VotingOptions({ onVote }) {
return (
<div>
<h2>Vote for your favorite option:</h2>
<button onClick={() => onVote('option1')}>Option 1</button>
<button onClick={() => onVote('option2')}>Option 2</button>
<button onClick={() => onVote('option3')}>Option 3</button>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment