diff --git a/components/ghost.js b/components/ghost.js deleted file mode 100644 index b09934be..00000000 --- a/components/ghost.js +++ /dev/null @@ -1,603 +0,0 @@ -import React, { useRef, useEffect, useContext } from 'react' - -export const GhostContext = React.createContext(() => {}) - -export class GhostProvider extends React.Component { - state = { - ghosts: [] - } - - strike = () => { - const should = window.localStorage.getItem('lnAnimate') || 'yes' - if (should === 'yes') { - this.setState(state => { - return { - ghosts: [...state.ghosts, this.unstrike(state.ghosts.length)} />] - } - }) - return true - } - return false - } - - unstrike = (index) => { - this.setState(state => { - const ghosts = [...state.ghosts] - ghosts[index] = null - return { ghosts } - }) - } - - render () { - const { props: { children } } = this - return ( - - {this.state.ghosts} - {children} - - ) - } -} - -export const GhostConsumer = GhostContext.Consumer -export function useGhost () { - return useContext(GhostContext) -} - -function getRandom (min, max) { - return Math.random() * (max - min) + min -} - -export function Ghost ({ onDone }) { - const canvasRef = useRef(null) - const textureRef = useRef(null) - - useEffect(() => { - const canvas = canvasRef.current - const texture = textureRef.current - if (canvas.ghost) return - - canvas.ghost = new GhostCanvas(canvas, texture, { - size: getRandom(0.025, 0.075), - tail: { - dotsNumber: 25, // Math.floor(getRandom(10, 50)), - spring: 1.4, // getRandom(1, 1.8), - friction: 0.25, // getRandom(0.1, 0.25), - maxGravity: 250, - gravity: getRandom(5, 250) - }, - smile: 1, - mainColor: [getRandom(0.8, 1), getRandom(0.8, 1), getRandom(0.8, 1)], - borderColor: [getRandom(0, 0.2), getRandom(0, 0.2), getRandom(0, 0.2)], // [0.2, 0.5, 0.7], - isFlatColor: false, - onDone - }) - }, []) - - return ( - <> - - - - ) -} - -const GhostCanvas = (canvas, texture, params) => { - const mouseThreshold = 1 - const devicePixelRatio = Math.min(window.devicePixelRatio, 2) - - function getRandomOffscreen () { - return Math.random() > 0.5 - ? { - x: getRandom(0, window.innerWidth), - y: Math.random() > 0.5 ? getRandom(-200, -100) : getRandom(window.innerHeight + 100, window.innerHeight + 200) - } - : { - x: Math.random() > 0.5 ? getRandom(-200, -100) : getRandom(window.innerWidth + 100, window.innerWidth + 200), - y: getRandom(0, window.innerHeight) - } - } - - function getRandomOnScreen () { - return { - x: getRandom(0.1 * window.innerWidth, 0.9 * window.innerWidth), - y: getRandom(0.1 * window.innerHeight, 0.9 * window.innerHeight) - } - } - - const mouse = { - ...getRandomOffscreen(), - tX: 0, - tY: 0, - moving: false - } - - const textureCtx = texture.getContext('2d') - const pointerTrail = new Array(params.tail.dotsNumber) - const dotSize = (i) => - params.size * - window.innerHeight * - (1 - 0.2 * Math.pow((3 * i) / params.tail.dotsNumber - 1, 2)) - for (let i = 0; i < params.tail.dotsNumber; i++) { - pointerTrail[i] = { - x: mouse.x, - y: mouse.y, - vx: 0, - vy: 0, - opacity: 0.04 + getRandom(0.25, 0.35) * Math.pow(1 - i / params.tail.dotsNumber, 4), - bordered: 0.6 * Math.pow(1 - i / pointerTrail.length, 1), - r: dotSize(i) - } - } - - let uniforms - const gl = initShader() - - function generateRandomPath () { - const startPoint = { - x: mouse.x, - y: mouse.y - } - - const numSegments = 1 // Adjust for more or fewer segments - const path = [] - - let lastEndPoint = startPoint - for (let i = 0; i < numSegments; i++) { - const controlPoint1 = getRandomOnScreen() - // const controlPoint2 = getRandomOnScreen() - const endPoint = getRandomOnScreen() - - path.push({ bezier: [lastEndPoint, controlPoint1, endPoint, endPoint] }) - lastEndPoint = endPoint - } - - path.push({ pause: getRandom(500, 2000) }) - const finalPoint = getRandomOffscreen() - path.push(finalPoint) - - return path - } - - const path = generateRandomPath() - let currentPathIndex = 0 - let pathStartTime = null - const segmentDuration = getRandom(750, 3000) // How long each Bezier segment should take - - function evaluateBezier (bezier, t) { - const [p0, p1, p2, p3] = bezier - - const oneMinusT = 1 - t - const x = Math.pow(oneMinusT, 3) * p0.x + - 3 * Math.pow(oneMinusT, 2) * t * p1.x + - 3 * oneMinusT * t * t * p2.x + - t * t * t * p3.x - - const y = Math.pow(oneMinusT, 3) * p0.y + - 3 * Math.pow(oneMinusT, 2) * t * p1.y + - 3 * oneMinusT * t * t * p2.y + - t * t * t * p3.y - - return { x, y } - } - - function interpolate (start, end, factor) { - return start + (end - start) * factor - } - - function updateMousePositionBasedOnPath (currentTime) { - if (!pathStartTime) { - pathStartTime = currentTime - } - - const currentSegment = path[currentPathIndex] - - if (currentSegment.pause) { - mouse.moving = false - if (currentTime - pathStartTime > currentSegment.pause) { - mouse.moving = true - currentPathIndex++ - pathStartTime = null - } - return - } - - if (currentSegment.bezier) { - const t = (currentTime - pathStartTime) / segmentDuration - if (t <= 1) { - const position = evaluateBezier(currentSegment.bezier, t) - mouse.tX = position.x - mouse.tY = position.y - } else { - currentPathIndex++ - pathStartTime = null - } - return - } - - // Linear segment - const factor = (currentTime - pathStartTime) / segmentDuration - if (factor < 1) { - mouse.tX = interpolate(mouse.x, currentSegment.x, factor) - mouse.tY = interpolate(mouse.y, currentSegment.y, factor) - } else { - currentPathIndex++ - pathStartTime = null - } - } - - resizeCanvas() - render() - mouse.moving = true - - function initShader () { - const vsSource = vertShader - const fsSource = fragShader - - const gl = - canvas.getContext('webgl') || - canvas.getContext('experimental-webgl') - - if (!gl) { - console.log('WebGL is not supported by your browser.') - return - } - - function createShader (gl, sourceCode, type) { - const shader = gl.createShader(type) - gl.shaderSource(shader, sourceCode) - gl.compileShader(shader) - - if (!gl.getShaderParameter(shader, gl.COMPILE_STATUS)) { - console.error( - 'An error occurred compiling the shaders: ' + - gl.getShaderInfoLog(shader) - ) - gl.deleteShader(shader) - return null - } - - return shader - } - - const vertexShader = createShader(gl, vsSource, gl.VERTEX_SHADER) - const fragmentShader = createShader(gl, fsSource, gl.FRAGMENT_SHADER) - - function createShaderProgram (gl, vertexShader, fragmentShader) { - const program = gl.createProgram() - gl.attachShader(program, vertexShader) - gl.attachShader(program, fragmentShader) - gl.linkProgram(program) - - if (!gl.getProgramParameter(program, gl.LINK_STATUS)) { - console.error( - 'Unable to initialize the shader program: ' + - gl.getProgramInfoLog(program) - ) - return null - } - - return program - } - - const shaderProgram = createShaderProgram( - gl, - vertexShader, - fragmentShader - ) - uniforms = getUniforms(shaderProgram) - - function getUniforms (program) { - const uniforms = [] - const uniformCount = gl.getProgramParameter( - program, - gl.ACTIVE_UNIFORMS - ) - for (let i = 0; i < uniformCount; i++) { - const uniformName = gl.getActiveUniform(program, i).name - uniforms[uniformName] = gl.getUniformLocation(program, uniformName) - } - return uniforms - } - - const vertices = new Float32Array([-1, -1, 1, -1, -1, 1, 1, 1]) - - const vertexBuffer = gl.createBuffer() - gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer) - gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW) - - gl.useProgram(shaderProgram) - - const positionLocation = gl.getAttribLocation( - shaderProgram, - 'a_position' - ) - gl.enableVertexAttribArray(positionLocation) - - gl.bindBuffer(gl.ARRAY_BUFFER, vertexBuffer) - gl.vertexAttribPointer(positionLocation, 2, gl.FLOAT, false, 0, 0) - - const canvasTexture = gl.createTexture() - gl.bindTexture(gl.TEXTURE_2D, canvasTexture) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MIN_FILTER, gl.LINEAR) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_MAG_FILTER, gl.LINEAR) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE) - gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE) - gl.texImage2D( - gl.TEXTURE_2D, - 0, - gl.RGBA, - gl.RGBA, - gl.UNSIGNED_BYTE, - texture - ) - gl.uniform1i(uniforms.u_texture, 0) - - gl.uniform1f(uniforms.u_size, params.size) - gl.uniform3f( - uniforms.u_main_color, - params.mainColor[0], - params.mainColor[1], - params.mainColor[2] - ) - gl.uniform3f( - uniforms.u_border_color, - params.borderColor[0], - params.borderColor[1], - params.borderColor[2] - ) - - return gl - } - - function updateTexture () { - textureCtx.fillStyle = 'black' - textureCtx.fillRect(0, 0, texture.width, texture.height) - - pointerTrail.forEach((p, pIdx) => { - if (Number.isNaN(mouse.x) || Number.isNaN(mouse.y)) { - return - } - - if (pIdx === 0) { - p.x = mouse.x - p.y = mouse.y - } else { - p.vx += (pointerTrail[pIdx - 1].x - p.x) * params.tail.spring - p.vx *= params.tail.friction - - p.vy += (pointerTrail[pIdx - 1].y - p.y) * params.tail.spring - p.vy *= params.tail.friction - p.vy += params.tail.gravity - p.x += p.vx - p.y += p.vy - } - - const grd = textureCtx.createRadialGradient( - p.x, - p.y, - p.r * p.bordered, - p.x, - p.y, - p.r - ) - grd.addColorStop( - 0, - 'rgba(255, 255, 255, ' + p.opacity + ')' - ) - grd.addColorStop(1, 'rgba(255, 255, 255, 0)') - - textureCtx.beginPath() - textureCtx.fillStyle = grd - textureCtx.arc(p.x, p.y, p.r, 0, Math.PI * 2) - textureCtx.fill() - }) - } - - function render () { - if (currentPathIndex > path.length - 1) { - params.onDone() - return - } - const currentTime = performance.now() - updateMousePositionBasedOnPath(currentTime) - gl.uniform1f(uniforms.u_time, currentTime) - - gl.clearColor(0.0, 0.0, 0.0, 1.0) - gl.clear(gl.COLOR_BUFFER_BIT) - gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4) - - if (mouse.moving) { - params.smile -= 0.05 - params.smile = Math.max(params.smile, -0.1) - params.tail.gravity -= 10 * params.size - params.tail.gravity = Math.max(params.tail.gravity, 0) - } else { - params.smile += 0.01 - params.smile = Math.min(params.smile, 1) - if (params.tail.gravity > 30 * params.size) { - params.tail.gravity = - (30 + 9 * (1 + Math.sin(0.002 * currentTime))) * params.size - } else { - params.tail.gravity += params.size - } - } - - mouse.x += (mouse.tX - mouse.x) * mouseThreshold - mouse.y += (mouse.tY - mouse.y) * mouseThreshold - - gl.uniform1f(uniforms.u_smile, params.smile) - gl.uniform2f( - uniforms.u_pointer, - mouse.x / window.innerWidth, - 1 - mouse.y / window.innerHeight - ) - gl.uniform2f( - uniforms.u_target_pointer, - mouse.tX / window.innerWidth, - 1 - mouse.tY / window.innerHeight - ) - - updateTexture() - - gl.texImage2D( - gl.TEXTURE_2D, - 0, - gl.RGBA, - gl.RGBA, - gl.UNSIGNED_BYTE, - texture - ) - window.requestAnimationFrame(render) - } - - function resizeCanvas () { - canvas.width = window.innerWidth * devicePixelRatio - canvas.height = window.innerHeight * devicePixelRatio - texture.width = window.innerWidth - texture.height = window.innerHeight - gl.viewport(0, 0, canvas.width, canvas.height) - gl.uniform1f(uniforms.u_ratio, canvas.width / canvas.height) - for (let i = 0; i < params.tail.dotsNumber; i++) { - pointerTrail[i].r = dotSize(i) - } - } -} - -const vertShader = ` - precision mediump float; - - varying vec2 vUv; - attribute vec2 a_position; - - void main() { - vUv = .5 * (a_position + 1.); - gl_Position = vec4(a_position, 0.0, 1.0); - }` - -const fragShader = ` -precision mediump float; - -varying vec2 vUv; -uniform float u_time; -uniform float u_ratio; -uniform float u_size; -uniform vec2 u_pointer; -uniform float u_smile; -uniform vec2 u_target_pointer; -uniform vec3 u_main_color; -uniform vec3 u_border_color; -uniform float u_flat_color; -uniform sampler2D u_texture; - -#define TWO_PI 6.28318530718 -#define PI 3.14159265358979323846 - -vec3 mod289(vec3 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } -vec2 mod289(vec2 x) { return x - floor(x * (1.0 / 289.0)) * 289.0; } -vec3 permute(vec3 x) { return mod289(((x*34.0)+1.0)*x); } -float snoise(vec2 v) { - const vec4 C = vec4(0.211324865405187, 0.366025403784439, -0.577350269189626, 0.024390243902439); - vec2 i = floor(v + dot(v, C.yy)); - vec2 x0 = v - i + dot(i, C.xx); - vec2 i1; - i1 = (x0.x > x0.y) ? vec2(1.0, 0.0) : vec2(0.0, 1.0); - vec4 x12 = x0.xyxy + C.xxzz; - x12.xy -= i1; - i = mod289(i); - vec3 p = permute(permute(i.y + vec3(0.0, i1.y, 1.0)) + i.x + vec3(0.0, i1.x, 1.0)); - vec3 m = max(0.5 - vec3(dot(x0, x0), dot(x12.xy, x12.xy), dot(x12.zw, x12.zw)), 0.0); - m = m*m; - m = m*m; - vec3 x = 2.0 * fract(p * C.www) - 1.0; - vec3 h = abs(x) - 0.5; - vec3 ox = floor(x + 0.5); - vec3 a0 = x - ox; - m *= 1.79284291400159 - 0.85373472095314 * (a0*a0 + h*h); - vec3 g; - g.x = a0.x * x0.x + h.x * x0.y; - g.yz = a0.yz * x12.xz + h.yz * x12.yw; - return 130.0 * dot(m, g); -} -vec2 rotate(vec2 v, float angle) { - float r_sin = sin(angle); - float r_cos = cos(angle); - return vec2(v.x * r_cos - v.y * r_sin, v.x * r_sin + v.y * r_cos); -} - -float eyes(vec2 uv) { - uv.y -= .5; - uv.x *= 1.; - uv.y *= .8; - uv.x = abs(uv.x); - uv.y += u_smile * .3 * pow(uv.x, 1.3); - uv.x -= (.6 + .2 * u_smile); - - float d = clamp(length(uv), 0., 1.); - return 1. - pow(d, .08); -} - -float mouth(vec2 uv) { - uv.y += 1.5; - - uv.x *= (.5 + .5 * abs(1. - u_smile)); - uv.y *= (3. - 2. * abs(1. - u_smile)); - uv.y -= u_smile * 4. * pow(uv.x, 2.); - - float d = clamp(length(uv), 0., 1.); - return 1. - pow(d, .07); -} - -float face(vec2 uv, float rotation) { - uv = rotate(uv, rotation); - uv /= (.27 * u_size); - - float eyes_shape = 10. * eyes(uv); - float mouth_shape = 20. * mouth(uv); - - float col = 0.; - col = mix(col, 1., eyes_shape); - col = mix(col, 1., mouth_shape); - - return col; -} - -void main() { - - vec2 point = u_pointer; - point.x *= u_ratio; - - vec2 uv = vUv; - uv.x *= u_ratio; - uv -= point; - - float texture = texture2D(u_texture, vec2(vUv.x, 1. - vUv.y)).r; - float shape = texture; - - float noise = snoise(uv * vec2(.7 / u_size, .6 / u_size) + vec2(0., .0015 * u_time)); - noise += 1.2; - noise *= 2.1; - noise += smoothstep(-.8, -.2, (uv.y) / u_size); - - float face = face(uv, 5. * (u_target_pointer.x - u_pointer.x)); - shape -= face; - - shape *= noise; - - vec3 border = (1. - u_border_color); - border.g += .2 * sin(.005 * u_time); - border *= .5; - - vec3 color = u_main_color; - color -= (1. - u_flat_color) * border * smoothstep(.0, .01, shape); - - shape = u_flat_color * smoothstep(.8, 1., shape) + (1. - u_flat_color) * shape; - color *= shape; - - gl_FragColor = vec4(color, shape); -}` diff --git a/components/header.js b/components/header.js index f04943c8..f92bb617 100644 --- a/components/header.js +++ b/components/header.js @@ -20,7 +20,7 @@ import { Select } from './form' import SearchIcon from '../svgs/search-line.svg' import BackArrow from '../svgs/arrow-left-line.svg' import { SSR, SUBS } from '../lib/constants' -import { useGhost } from './ghost' +import { useLightning } from './lightning' import { HAS_NOTIFICATIONS } from '../fragments/notifications' import AnonIcon from '../svgs/spy-fill.svg' import Hat from './hat' @@ -147,7 +147,7 @@ function StackerCorner ({ dropNavKey }) { function LurkerCorner ({ path }) { const router = useRouter() - const strike = useGhost() + const strike = useLightning() useEffect(() => { if (!window.localStorage.getItem('striked')) { diff --git a/components/lightning.js b/components/lightning.js index 44202d04..948abf56 100644 --- a/components/lightning.js +++ b/components/lightning.js @@ -44,8 +44,8 @@ export class LightningProvider extends React.Component { } } -export const GhostConsumer = LightningContext.Consumer -export function useGhost () { +export const LightningConsumer = LightningContext.Consumer +export function useLightning () { return useContext(LightningContext) } diff --git a/components/upvote.js b/components/upvote.js index 56e34bb1..34ec25e5 100644 --- a/components/upvote.js +++ b/components/upvote.js @@ -10,7 +10,7 @@ import LongPressable from 'react-longpressable' import Overlay from 'react-bootstrap/Overlay' import Popover from 'react-bootstrap/Popover' import { useShowModal } from './modal' -import { GhostConsumer, useGhost } from './ghost' +import { LightningConsumer, useLightning } from './lightning' import { numWithUnits } from '../lib/format' import { payOrLoginError, useInvoiceModal } from './invoice' import useDebounceCallback from './use-debounce-callback' @@ -71,7 +71,7 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats } const [tipShow, _setTipShow] = useState(false) const ref = useRef() const me = useMe() - const strike = useGhost() + const strike = useLightning() const [setWalkthrough] = useMutation( gql` mutation setWalkthrough($upvotePopover: Boolean, $tipPopover: Boolean) { @@ -202,7 +202,7 @@ export default function UpVote ({ item, className, pendingSats, setPendingSats } }, [item?.meSats, item?.meAnonSats, pendingSats, me?.tipDefault, me?.turboDefault]) return ( - + {(strike) =>
setTipShow(false)} /> setVoteShow(false)} />
} -
+ ) } diff --git a/pages/_app.js b/pages/_app.js index 2836d1ef..e41b9c18 100644 --- a/pages/_app.js +++ b/pages/_app.js @@ -10,7 +10,7 @@ import { useRouter } from 'next/dist/client/router' import { useEffect } from 'react' import { ShowModalProvider } from '../components/modal' import ErrorBoundary from '../components/error-boundary' -import { GhostProvider } from '../components/ghost' +import { LightningProvider } from '../components/lightning' import { ToastProvider } from '../components/toast' import { ServiceWorkerProvider } from '../components/serviceworker' import { SSR } from '../lib/constants' @@ -92,7 +92,7 @@ export default function MyApp ({ Component, pageProps: { ...props } }) { - + @@ -100,7 +100,7 @@ export default function MyApp ({ Component, pageProps: { ...props } }) { - + diff --git a/pages/rewards/index.js b/pages/rewards/index.js index 680420bd..6d833130 100644 --- a/pages/rewards/index.js +++ b/pages/rewards/index.js @@ -15,7 +15,7 @@ import { useShowModal } from '../../components/modal' import dynamic from 'next/dynamic' import { SSR } from '../../lib/constants' import { useToast } from '../../components/toast' -import { useGhost } from '../../components/ghost' +import { useLightning } from '../../components/lightning' const GrowthPieChart = dynamic(() => import('../../components/charts').then(mod => mod.GrowthPieChart), { loading: () =>
Loading...
@@ -91,7 +91,7 @@ export default function Rewards ({ ssrData }) { export function DonateButton () { const showModal = useShowModal() const toaster = useToast() - const strike = useGhost() + const strike = useLightning() const [donateToRewards] = useMutation( gql` mutation donateToRewards($sats: Int!, $hash: String, $hmac: String) {