feat(frontend): add stealth overlay
This commit is contained in:
52
frontend/src/lib/components/StealthOverlay.svelte
Normal file
52
frontend/src/lib/components/StealthOverlay.svelte
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<script lang="ts">
|
||||||
|
let stealthMode = $state(false);
|
||||||
|
let lastTap = $state({ time: 0, x: 0, y: 0 });
|
||||||
|
|
||||||
|
function isInCenterZone(x: number, y: number): boolean {
|
||||||
|
const w = window.innerWidth;
|
||||||
|
const h = window.innerHeight;
|
||||||
|
return x > w * 0.3 && x < w * 0.7 && y > h * 0.3 && y < h * 0.7;
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleTouchEnd(e: TouchEvent) {
|
||||||
|
if (e.touches.length > 0) return;
|
||||||
|
|
||||||
|
const touch = e.changedTouches[0];
|
||||||
|
const now = Date.now();
|
||||||
|
const x = touch.clientX;
|
||||||
|
const y = touch.clientY;
|
||||||
|
|
||||||
|
if (!isInCenterZone(x, y)) {
|
||||||
|
lastTap = { time: 0, x: 0, y: 0 };
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const timeDiff = now - lastTap.time;
|
||||||
|
const distX = Math.abs(x - lastTap.x);
|
||||||
|
const distY = Math.abs(y - lastTap.y);
|
||||||
|
|
||||||
|
if (timeDiff < 300 && distX < 50 && distY < 50) {
|
||||||
|
stealthMode = !stealthMode;
|
||||||
|
lastTap = { time: 0, x: 0, y: 0 };
|
||||||
|
e.preventDefault();
|
||||||
|
} else {
|
||||||
|
lastTap = { time: now, x, y };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<svelte:document ontouchend={handleTouchEnd} />
|
||||||
|
|
||||||
|
{#if stealthMode}
|
||||||
|
<div class="stealth-overlay" ontouchend={handleTouchEnd}></div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.stealth-overlay {
|
||||||
|
position: fixed;
|
||||||
|
inset: 0;
|
||||||
|
z-index: 9999;
|
||||||
|
background: #000;
|
||||||
|
touch-action: manipulation;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
import ChatMessage from '$lib/components/ChatMessage.svelte';
|
import ChatMessage from '$lib/components/ChatMessage.svelte';
|
||||||
import ChatInput from '$lib/components/ChatInput.svelte';
|
import ChatInput from '$lib/components/ChatInput.svelte';
|
||||||
import FollowUpButtons from '$lib/components/FollowUpButtons.svelte';
|
import FollowUpButtons from '$lib/components/FollowUpButtons.svelte';
|
||||||
|
import StealthOverlay from '$lib/components/StealthOverlay.svelte';
|
||||||
|
|
||||||
const usePolling = getContext<boolean>('convex-use-polling') ?? false;
|
const usePolling = getContext<boolean>('convex-use-polling') ?? false;
|
||||||
let mnemonic = $derived(page.params.mnemonic);
|
let mnemonic = $derived(page.params.mnemonic);
|
||||||
@@ -185,4 +186,6 @@
|
|||||||
↓
|
↓
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<StealthOverlay />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user