Skip to content

Commit 343cbb1

Browse files
committed
add: Iroh-based realtime channels, security hardening, Game Lobbies
1 parent dc6b9a7 commit 343cbb1

135 files changed

Lines changed: 2973 additions & 82 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

docs/miniapps/examples/build.sh

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
#!/bin/bash
2+
# Build script for Mini App examples
3+
4+
set -e
5+
6+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
7+
8+
echo "Building Mini App examples..."
9+
10+
# Build clicker game
11+
echo " Building clicker.xdc..."
12+
cd "$SCRIPT_DIR/clicker"
13+
zip -r ../clicker.xdc index.html manifest.toml icon.svg
14+
echo " ✓ clicker.xdc created"
15+
16+
echo ""
17+
echo "All Mini Apps built successfully!"
18+
echo "Output files are in: $SCRIPT_DIR/"
19+
ls -la "$SCRIPT_DIR"/*.xdc

docs/miniapps/examples/clicker.xdc

2.93 KB
Binary file not shown.
Lines changed: 25 additions & 0 deletions
Loading
Lines changed: 216 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,216 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8">
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
6+
<title>Vector Clicker</title>
7+
<script src="webxdc.js"></script>
8+
<style>
9+
* {
10+
margin: 0;
11+
padding: 0;
12+
box-sizing: border-box;
13+
}
14+
15+
body {
16+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
17+
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
18+
min-height: 100vh;
19+
display: flex;
20+
flex-direction: column;
21+
align-items: center;
22+
justify-content: center;
23+
padding: 20px;
24+
color: white;
25+
}
26+
27+
h1 {
28+
font-size: 2rem;
29+
margin-bottom: 10px;
30+
text-shadow: 2px 2px 4px rgba(0,0,0,0.3);
31+
}
32+
33+
.player-info {
34+
background: rgba(255,255,255,0.2);
35+
padding: 10px 20px;
36+
border-radius: 20px;
37+
margin-bottom: 20px;
38+
font-size: 0.9rem;
39+
}
40+
41+
.score-display {
42+
font-size: 3rem;
43+
font-weight: bold;
44+
margin: 20px 0;
45+
text-shadow: 3px 3px 6px rgba(0,0,0,0.3);
46+
}
47+
48+
.click-button {
49+
width: 200px;
50+
height: 200px;
51+
border-radius: 50%;
52+
border: none;
53+
background: linear-gradient(145deg, #ff6b6b, #ee5a5a);
54+
box-shadow:
55+
0 10px 30px rgba(0,0,0,0.3),
56+
inset 0 -5px 20px rgba(0,0,0,0.2),
57+
inset 0 5px 20px rgba(255,255,255,0.2);
58+
cursor: pointer;
59+
font-size: 4rem;
60+
color: white;
61+
transition: transform 0.1s, box-shadow 0.1s;
62+
user-select: none;
63+
}
64+
65+
.click-button:hover {
66+
transform: scale(1.05);
67+
}
68+
69+
.click-button:active {
70+
transform: scale(0.95);
71+
box-shadow:
72+
0 5px 15px rgba(0,0,0,0.3),
73+
inset 0 -2px 10px rgba(0,0,0,0.2),
74+
inset 0 2px 10px rgba(255,255,255,0.2);
75+
}
76+
77+
.click-effect {
78+
position: fixed;
79+
pointer-events: none;
80+
font-size: 1.5rem;
81+
font-weight: bold;
82+
color: #ffd700;
83+
text-shadow: 1px 1px 2px rgba(0,0,0,0.5);
84+
animation: floatUp 1s ease-out forwards;
85+
}
86+
87+
@keyframes floatUp {
88+
0% {
89+
opacity: 1;
90+
transform: translateY(0) scale(1);
91+
}
92+
100% {
93+
opacity: 0;
94+
transform: translateY(-100px) scale(1.5);
95+
}
96+
}
97+
98+
.stats {
99+
margin-top: 30px;
100+
font-size: 0.9rem;
101+
opacity: 0.8;
102+
}
103+
</style>
104+
</head>
105+
<body>
106+
<h1>🎮 Vector Clicker</h1>
107+
<div class="player-info" id="playerInfo">Loading...</div>
108+
109+
<div class="score-display" id="score">0</div>
110+
111+
<button class="click-button" id="clickBtn" onclick="handleClick(event)">
112+
👆
113+
</button>
114+
115+
<div class="stats" id="stats">
116+
Clicks per second: <span id="cps">0</span>
117+
</div>
118+
119+
<script>
120+
// Game state
121+
let myScore = 0;
122+
let clickTimes = [];
123+
let myAddr = 'unknown';
124+
let myName = 'Player';
125+
126+
// Initialize the game
127+
function init() {
128+
// Get player info from webxdc
129+
if (window.webxdc) {
130+
myAddr = window.webxdc.selfAddr || 'unknown';
131+
myName = window.webxdc.selfName || 'Player';
132+
133+
document.getElementById('playerInfo').textContent =
134+
`Playing as: ${myName}`;
135+
136+
// Set up update listener
137+
window.webxdc.setUpdateListener(function(update) {
138+
handleUpdate(update);
139+
}, 0);
140+
} else {
141+
document.getElementById('playerInfo').textContent =
142+
'Demo mode (webxdc not available)';
143+
}
144+
145+
// Update CPS every second
146+
setInterval(updateCPS, 1000);
147+
}
148+
149+
// Handle click on the button
150+
function handleClick(event) {
151+
myScore++;
152+
updateScoreDisplay();
153+
createClickEffect(event);
154+
155+
// Track click time for CPS calculation
156+
clickTimes.push(Date.now());
157+
158+
// Send update to other players
159+
if (window.webxdc) {
160+
window.webxdc.sendUpdate({
161+
payload: {
162+
type: 'score',
163+
addr: myAddr,
164+
name: myName,
165+
score: myScore
166+
}
167+
}, `${myName} clicked! Score: ${myScore}`);
168+
}
169+
}
170+
171+
// Handle updates from other players
172+
function handleUpdate(update) {
173+
if (update.payload && update.payload.type === 'score') {
174+
const { addr, name, score } = update.payload;
175+
176+
// If it's our own update coming back, sync the score
177+
if (addr === myAddr && score > myScore) {
178+
myScore = score;
179+
updateScoreDisplay();
180+
}
181+
}
182+
}
183+
184+
// Update the score display
185+
function updateScoreDisplay() {
186+
document.getElementById('score').textContent = myScore.toLocaleString();
187+
}
188+
189+
// Create floating +1 effect
190+
function createClickEffect(event) {
191+
const effect = document.createElement('div');
192+
effect.className = 'click-effect';
193+
effect.textContent = '+1';
194+
effect.style.left = (event.clientX - 15) + 'px';
195+
effect.style.top = (event.clientY - 15) + 'px';
196+
document.body.appendChild(effect);
197+
198+
setTimeout(() => effect.remove(), 1000);
199+
}
200+
201+
// Calculate and display clicks per second
202+
function updateCPS() {
203+
const now = Date.now();
204+
const oneSecondAgo = now - 1000;
205+
206+
// Filter to only clicks in the last second
207+
clickTimes = clickTimes.filter(t => t > oneSecondAgo);
208+
209+
document.getElementById('cps').textContent = clickTimes.length;
210+
}
211+
212+
// Start the game
213+
init();
214+
</script>
215+
</body>
216+
</html>
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
name = "Vector Clicker"
2+
description = "A fun multiplayer clicker game! Compete with friends to see who can click the most."
3+
version = "1.0.0"
4+
icon = "icon.svg"

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vector",
33
"private": true,
4-
"version": "0.2.3",
4+
"version": "0.3.0",
55
"type": "module",
66
"scripts": {
77
"tauri": "tauri",

src-tauri/Cargo.lock

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src-tauri/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "vector"
3-
version = "0.2.3"
3+
version = "0.3.0"
44
description = "A humble attempt at a modern, private, complete Nostr chat client."
55
authors = ["Formless Labs", "JSKitty", "YuurinBee"]
66
edition = "2021"

0 commit comments

Comments
 (0)