Implemented cryptomining, although its extremely bad optimized.

This commit is contained in:
2025-12-03 18:20:02 +01:00
commit c2d6d0b096
308 changed files with 56964 additions and 0 deletions
+19
View File
@@ -0,0 +1,19 @@
import * as React from "react";
const MOBILE_BREAKPOINT = 768;
export function useIsMobile() {
const [isMobile, setIsMobile] = React.useState<boolean | undefined>(undefined);
React.useEffect(() => {
const mql = window.matchMedia(`(max-width: ${MOBILE_BREAKPOINT - 1}px)`);
const onChange = () => {
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
};
mql.addEventListener("change", onChange);
setIsMobile(window.innerWidth < MOBILE_BREAKPOINT);
return () => mql.removeEventListener("change", onChange);
}, []);
return !!isMobile;
}
+186
View File
@@ -0,0 +1,186 @@
import * as React from "react";
import type { ToastActionElement, ToastProps } from "@/components/ui/toast";
const TOAST_LIMIT = 1;
const TOAST_REMOVE_DELAY = 1000000;
type ToasterToast = ToastProps & {
id: string;
title?: React.ReactNode;
description?: React.ReactNode;
action?: ToastActionElement;
};
const actionTypes = {
ADD_TOAST: "ADD_TOAST",
UPDATE_TOAST: "UPDATE_TOAST",
DISMISS_TOAST: "DISMISS_TOAST",
REMOVE_TOAST: "REMOVE_TOAST",
} as const;
let count = 0;
function genId() {
count = (count + 1) % Number.MAX_SAFE_INTEGER;
return count.toString();
}
type ActionType = typeof actionTypes;
type Action =
| {
type: ActionType["ADD_TOAST"];
toast: ToasterToast;
}
| {
type: ActionType["UPDATE_TOAST"];
toast: Partial<ToasterToast>;
}
| {
type: ActionType["DISMISS_TOAST"];
toastId?: ToasterToast["id"];
}
| {
type: ActionType["REMOVE_TOAST"];
toastId?: ToasterToast["id"];
};
interface State {
toasts: ToasterToast[];
}
const toastTimeouts = new Map<string, ReturnType<typeof setTimeout>>();
const addToRemoveQueue = (toastId: string) => {
if (toastTimeouts.has(toastId)) {
return;
}
const timeout = setTimeout(() => {
toastTimeouts.delete(toastId);
dispatch({
type: "REMOVE_TOAST",
toastId: toastId,
});
}, TOAST_REMOVE_DELAY);
toastTimeouts.set(toastId, timeout);
};
export const reducer = (state: State, action: Action): State => {
switch (action.type) {
case "ADD_TOAST":
return {
...state,
toasts: [action.toast, ...state.toasts].slice(0, TOAST_LIMIT),
};
case "UPDATE_TOAST":
return {
...state,
toasts: state.toasts.map((t) => (t.id === action.toast.id ? { ...t, ...action.toast } : t)),
};
case "DISMISS_TOAST": {
const { toastId } = action;
// ! Side effects ! - This could be extracted into a dismissToast() action,
// but I'll keep it here for simplicity
if (toastId) {
addToRemoveQueue(toastId);
} else {
state.toasts.forEach((toast) => {
addToRemoveQueue(toast.id);
});
}
return {
...state,
toasts: state.toasts.map((t) =>
t.id === toastId || toastId === undefined
? {
...t,
open: false,
}
: t,
),
};
}
case "REMOVE_TOAST":
if (action.toastId === undefined) {
return {
...state,
toasts: [],
};
}
return {
...state,
toasts: state.toasts.filter((t) => t.id !== action.toastId),
};
}
};
const listeners: Array<(state: State) => void> = [];
let memoryState: State = { toasts: [] };
function dispatch(action: Action) {
memoryState = reducer(memoryState, action);
listeners.forEach((listener) => {
listener(memoryState);
});
}
type Toast = Omit<ToasterToast, "id">;
function toast({ ...props }: Toast) {
const id = genId();
const update = (props: ToasterToast) =>
dispatch({
type: "UPDATE_TOAST",
toast: { ...props, id },
});
const dismiss = () => dispatch({ type: "DISMISS_TOAST", toastId: id });
dispatch({
type: "ADD_TOAST",
toast: {
...props,
id,
open: true,
onOpenChange: (open) => {
if (!open) dismiss();
},
},
});
return {
id: id,
dismiss,
update,
};
}
function useToast() {
const [state, setState] = React.useState<State>(memoryState);
React.useEffect(() => {
listeners.push(setState);
return () => {
const index = listeners.indexOf(setState);
if (index > -1) {
listeners.splice(index, 1);
}
};
}, [state]);
return {
...state,
toast,
dismiss: (toastId?: string) => dispatch({ type: "DISMISS_TOAST", toastId }),
};
}
export { useToast, toast };
+118
View File
@@ -0,0 +1,118 @@
import { useState, useEffect, useCallback } from 'react';
interface GameDimensions {
cellSize: number;
canvasWidth: number;
canvasHeight: number;
isMobile: boolean;
}
interface UseGameDimensionsOptions {
gridWidth: number;
gridHeight: number;
minCellSize?: number;
maxCellSize?: number;
padding?: number;
}
export const useGameDimensions = ({
gridWidth,
gridHeight,
minCellSize = 12,
maxCellSize = 40,
padding = 120, // Space for controls and UI
}: UseGameDimensionsOptions): GameDimensions => {
const calculateDimensions = useCallback((): GameDimensions => {
const isMobile = window.innerWidth < 768;
const availableWidth = window.innerWidth - (isMobile ? 32 : padding);
const availableHeight = window.innerHeight - (isMobile ? 200 : padding);
// Calculate cell size based on available space
const cellFromWidth = Math.floor(availableWidth / gridWidth);
const cellFromHeight = Math.floor(availableHeight / gridHeight);
// Use the smaller of the two to ensure it fits
let cellSize = Math.min(cellFromWidth, cellFromHeight);
// Clamp to min/max
cellSize = Math.max(minCellSize, Math.min(maxCellSize, cellSize));
return {
cellSize,
canvasWidth: cellSize * gridWidth,
canvasHeight: cellSize * gridHeight,
isMobile,
};
}, [gridWidth, gridHeight, minCellSize, maxCellSize, padding]);
const [dimensions, setDimensions] = useState<GameDimensions>(calculateDimensions);
useEffect(() => {
const handleResize = () => {
setDimensions(calculateDimensions());
};
window.addEventListener('resize', handleResize);
// Also handle orientation change on mobile
window.addEventListener('orientationchange', handleResize);
return () => {
window.removeEventListener('resize', handleResize);
window.removeEventListener('orientationchange', handleResize);
};
}, [calculateDimensions]);
return dimensions;
};
// Hook to handle browser fullscreen API
export const useBrowserFullscreen = () => {
const [isBrowserFullscreen, setIsBrowserFullscreen] = useState(false);
const enterFullscreen = useCallback(async (element?: HTMLElement) => {
const target = element || document.documentElement;
try {
if (target.requestFullscreen) {
await target.requestFullscreen();
} else if ((target as any).webkitRequestFullscreen) {
await (target as any).webkitRequestFullscreen();
} else if ((target as any).msRequestFullscreen) {
await (target as any).msRequestFullscreen();
}
setIsBrowserFullscreen(true);
} catch (err) {
console.log('Fullscreen not supported or denied');
}
}, []);
const exitFullscreen = useCallback(async () => {
try {
if (document.exitFullscreen) {
await document.exitFullscreen();
} else if ((document as any).webkitExitFullscreen) {
await (document as any).webkitExitFullscreen();
} else if ((document as any).msExitFullscreen) {
await (document as any).msExitFullscreen();
}
setIsBrowserFullscreen(false);
} catch (err) {
console.log('Exit fullscreen failed');
}
}, []);
useEffect(() => {
const handleChange = () => {
setIsBrowserFullscreen(!!document.fullscreenElement);
};
document.addEventListener('fullscreenchange', handleChange);
document.addEventListener('webkitfullscreenchange', handleChange);
return () => {
document.removeEventListener('fullscreenchange', handleChange);
document.removeEventListener('webkitfullscreenchange', handleChange);
};
}, []);
return { isBrowserFullscreen, enterFullscreen, exitFullscreen };
};
+64
View File
@@ -0,0 +1,64 @@
import { useState, useEffect, useCallback } from 'react';
const KONAMI_CODE = [
'ArrowUp', 'ArrowUp',
'ArrowDown', 'ArrowDown',
'ArrowLeft', 'ArrowRight',
'ArrowLeft', 'ArrowRight',
'KeyB', 'KeyA'
];
interface UseKonamiCodeReturn {
activated: boolean;
reset: () => void;
}
export const useKonamiCode = (): UseKonamiCodeReturn => {
const [keysPressed, setKeysPressed] = useState<string[]>([]);
const [activated, setActivated] = useState(false);
const [lastKeyTime, setLastKeyTime] = useState(0);
const reset = useCallback(() => {
setActivated(false);
setKeysPressed([]);
}, []);
useEffect(() => {
const handleKeyDown = (e: KeyboardEvent) => {
const now = Date.now();
// Reset if more than 2 seconds between keys
if (now - lastKeyTime > 2000) {
setKeysPressed([]);
}
setLastKeyTime(now);
const key = e.code;
setKeysPressed(prev => {
const newKeys = [...prev, key];
// Check if the sequence matches so far
const expectedKey = KONAMI_CODE[newKeys.length - 1];
if (key !== expectedKey) {
// Wrong key, reset
return [];
}
// Check if complete
if (newKeys.length === KONAMI_CODE.length) {
setActivated(true);
return [];
}
return newKeys;
});
};
window.addEventListener('keydown', handleKeyDown);
return () => window.removeEventListener('keydown', handleKeyDown);
}, [lastKeyTime]);
return { activated, reset };
};
+60
View File
@@ -0,0 +1,60 @@
import { useRef, useCallback } from 'react';
/**
* Hook for handling press-and-hold touch interactions
* Fires the callback continuously while the button is held
*/
export const useTouchHold = (
callback: () => void,
interval = 100,
initialDelay = 150
) => {
const intervalRef = useRef<NodeJS.Timeout | null>(null);
const timeoutRef = useRef<NodeJS.Timeout | null>(null);
const start = useCallback(() => {
// Fire immediately on touch
callback();
// Start repeating after initial delay
timeoutRef.current = setTimeout(() => {
intervalRef.current = setInterval(() => {
callback();
}, interval);
}, initialDelay);
}, [callback, interval, initialDelay]);
const stop = useCallback(() => {
if (timeoutRef.current) {
clearTimeout(timeoutRef.current);
timeoutRef.current = null;
}
if (intervalRef.current) {
clearInterval(intervalRef.current);
intervalRef.current = null;
}
}, []);
const handlers = {
onTouchStart: (e: React.TouchEvent) => {
e.preventDefault();
start();
},
onTouchEnd: (e: React.TouchEvent) => {
e.preventDefault();
stop();
},
onTouchCancel: (e: React.TouchEvent) => {
e.preventDefault();
stop();
},
// Also support mouse for testing on desktop
onMouseDown: start,
onMouseUp: stop,
onMouseLeave: stop,
};
return handlers;
};
export default useTouchHold;