Skip to content

Commit 4959c00

Browse files
authored
feat: about
1 parent 5b2dea8 commit 4959c00

4 files changed

Lines changed: 240 additions & 14 deletions

File tree

web/src/About.jsx

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
import React from "react";
2+
import { useNavigate } from "react-router-dom";
3+
import { useAuth } from "./AuthContext";
4+
import { useConfig } from "./ConfigContext";
5+
6+
export default function About() {
7+
const navigate = useNavigate();
8+
const { isAuthenticated, logout } = useAuth();
9+
const { storageEnabled } = useConfig();
10+
11+
return (
12+
<div className="min-h-screen bg-white dark:bg-black text-black dark:text-white">
13+
{/* Sticky Navbar */}
14+
<div className="sticky top-0 z-50 bg-white dark:bg-black border-b-4 border-black dark:border-white">
15+
<div className="max-w-6xl mx-auto px-4 py-4 flex justify-between items-center">
16+
<h1 className="text-2xl sm:text-3xl font-black uppercase">About</h1>
17+
<div className="flex gap-2 sm:gap-3">
18+
<button
19+
onClick={() => navigate("/")}
20+
className="border-2 border-black dark:border-white bg-white dark:bg-black text-black dark:text-white px-3 py-2 sm:px-4 text-sm sm:text-base font-bold uppercase hover:bg-gray-100 dark:hover:bg-gray-900 transition-colors cursor-pointer"
21+
>
22+
<i className="fas fa-home"></i>
23+
<span className="hidden sm:inline sm:ml-2">Home</span>
24+
</button>
25+
{isAuthenticated ? (
26+
<>
27+
{storageEnabled && (
28+
<button
29+
onClick={() => navigate("/storage")}
30+
className="border-2 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-3 py-2 sm:px-4 text-sm sm:text-base font-bold uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer"
31+
>
32+
<i className="fas fa-hdd"></i>
33+
<span className="hidden sm:inline sm:ml-2">Storage</span>
34+
</button>
35+
)}
36+
<button
37+
onClick={logout}
38+
className="border-2 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-3 py-2 sm:px-4 text-sm sm:text-base font-bold uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer"
39+
>
40+
<i className="fas fa-sign-out-alt"></i>
41+
<span className="hidden sm:inline sm:ml-2">Logout</span>
42+
</button>
43+
</>
44+
) : (
45+
<>
46+
<button
47+
onClick={() => navigate("/login?mode=login")}
48+
className="border-2 border-black dark:border-white bg-white dark:bg-black text-black dark:text-white px-3 py-2 sm:px-4 text-sm sm:text-base font-bold uppercase hover:bg-gray-100 dark:hover:bg-gray-900 transition-colors cursor-pointer"
49+
>
50+
Sign In
51+
</button>
52+
<button
53+
onClick={() => navigate("/login?mode=signup")}
54+
className="border-2 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-3 py-2 sm:px-4 text-sm sm:text-base font-bold uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer"
55+
>
56+
Sign Up
57+
</button>
58+
</>
59+
)}
60+
</div>
61+
</div>
62+
</div>
63+
64+
{/* Content */}
65+
<div className="max-w-4xl mx-auto px-4 py-8 space-y-6">
66+
{/* What is E2ECP */}
67+
<div className="border-4 border-black dark:border-white p-6 bg-white dark:bg-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] dark:shadow-[8px_8px_0px_0px_rgba(255,255,255,1)]">
68+
<h2 className="text-3xl font-black uppercase mb-4">What is E2ECP?</h2>
69+
<p className="text-base sm:text-lg leading-relaxed mb-3">
70+
<strong>E2ECP (End-to-End Copy)</strong> is a secure, peer-to-peer file transfer tool that enables you to send files directly between devices.
71+
</p>
72+
<p className="text-base sm:text-lg leading-relaxed">
73+
Files are transferred securely between peers, where the server only facilitates the connection handshake, ensuring your data remains private and transfers happen at maximum speed.
74+
</p>
75+
</div>
76+
77+
{/* Browser Transfer */}
78+
<div className="border-4 border-black dark:border-white p-6 bg-white dark:bg-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] dark:shadow-[8px_8px_0px_0px_rgba(255,255,255,1)]">
79+
<h2 className="text-3xl font-black uppercase mb-4">Browser to Browser</h2>
80+
<p className="text-base sm:text-lg leading-relaxed mb-3">
81+
Transfer files between browsers instantly using a simple room code:
82+
</p>
83+
<ol className="list-decimal list-inside space-y-2 text-base sm:text-lg ml-4">
84+
<li>Open the home page and enter a room name (or use a random one)</li>
85+
<li>Share the room code with another person</li>
86+
<li>Both devices connect to the same room</li>
87+
<li>Drag and drop files or click to upload</li>
88+
<li>Files transfer directly with end-to-end encryption</li>
89+
</ol>
90+
<p className="text-base sm:text-lg leading-relaxed mt-3">
91+
<strong>No server storage</strong> - files go directly from one browser to another.
92+
</p>
93+
</div>
94+
95+
{/* CLI Usage */}
96+
<div className="border-4 border-black dark:border-white p-6 bg-white dark:bg-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] dark:shadow-[8px_8px_0px_0px_rgba(255,255,255,1)]">
97+
<h2 className="text-3xl font-black uppercase mb-4">Command Line Interface</h2>
98+
<p className="text-base sm:text-lg leading-relaxed mb-3">
99+
E2ECP includes a powerful CLI for terminal-based file transfers:
100+
</p>
101+
<div className="bg-black dark:bg-white text-white dark:text-black p-4 font-mono text-sm border-2 border-black dark:border-white mb-3 nocase">
102+
<div># send a file</div>
103+
<div>e2ecp send myfile.txt</div>
104+
<div className="mt-2"># receive a file with room code</div>
105+
<div>e2ecp receive room-code</div>
106+
</div>
107+
<p className="text-base sm:text-lg leading-relaxed">
108+
The CLI supports the same peer-to-peer transfer mechanism as the browser, making it perfect for server-to-server transfers or scripting automated file transfers.
109+
</p>
110+
</div>
111+
112+
{/* CLI + Browser */}
113+
<div className="border-4 border-black dark:border-white p-6 bg-white dark:bg-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] dark:shadow-[8px_8px_0px_0px_rgba(255,255,255,1)]">
114+
<h2 className="text-3xl font-black uppercase mb-4">CLI to Browser Transfer</h2>
115+
<p className="text-base sm:text-lg leading-relaxed mb-3">
116+
Seamlessly transfer files between the command line and browser:
117+
</p>
118+
<ul className="list-disc list-inside space-y-2 text-base sm:text-lg ml-4">
119+
<li><strong>CLI to Browser:</strong> Run <code className="bg-gray-200 dark:bg-gray-800 px-2 py-1 nocase">e2ecp send file.zip</code>, get a room code, then open that room in a browser to download</li>
120+
<li><strong>Browser to CLI:</strong> Create a room in the browser, upload files, then run <code className="nocase bg-gray-200 dark:bg-gray-800 px-2 py-1">e2ecp receive room-code</code> to download</li>
121+
<li>Perfect for transferring files between your laptop and server</li>
122+
<li>Works across different networks and NATs</li>
123+
</ul>
124+
</div>
125+
126+
{/* File Storage */}
127+
<div className="border-4 border-black dark:border-white p-6 bg-white dark:bg-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] dark:shadow-[8px_8px_0px_0px_rgba(255,255,255,1)]">
128+
<h2 className="text-3xl font-black uppercase mb-4">File Storage</h2>
129+
<p className="text-base sm:text-lg leading-relaxed mb-3">
130+
In addition to peer-to-peer transfers, E2ECP offers optional <strong>end-to-end encrypted storage</strong>:
131+
</p>
132+
<ul className="list-disc list-inside space-y-2 text-base sm:text-lg ml-4">
133+
<li>Create an account to store files temporarily</li>
134+
<li>All files are encrypted on your device before upload</li>
135+
<li>The server stores only encrypted data and cannot decrypt your files</li>
136+
<li>Filenames are also encrypted for maximum privacy</li>
137+
<li>Generate shareable links with encryption keys in the URL fragment</li>
138+
<li>Perfect for temporary file hosting or transferring files asynchronously</li>
139+
</ul>
140+
{storageEnabled ? (
141+
<button
142+
onClick={() => navigate("/login")}
143+
className="mt-4 border-2 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-6 py-3 font-black uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_0px_rgba(255,255,255,1)] hover:translate-x-1 hover:translate-y-1 hover:shadow-none active:translate-x-2 active:translate-y-2"
144+
>
145+
Get Started with Storage
146+
</button>
147+
) : (
148+
<p className="mt-4 text-sm text-gray-600 dark:text-gray-400">
149+
Storage is currently disabled on this server.
150+
</p>
151+
)}
152+
</div>
153+
154+
{/* How to Upload */}
155+
<div className="border-4 border-black dark:border-white p-6 bg-white dark:bg-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] dark:shadow-[8px_8px_0px_0px_rgba(255,255,255,1)]">
156+
<h2 className="text-3xl font-black uppercase mb-4">How to Upload Files</h2>
157+
<div className="space-y-4">
158+
<div>
159+
<h3 className="text-xl font-bold mb-2">For Peer-to-Peer Transfer:</h3>
160+
<ol className="list-decimal list-inside space-y-1 text-base sm:text-lg ml-4">
161+
<li>Enter or create a room on the home page</li>
162+
<li>Wait for both devices to connect</li>
163+
<li>Drag and drop files or click the upload area</li>
164+
<li>Files transfer instantly to connected peers</li>
165+
</ol>
166+
</div>
167+
<div>
168+
<h3 className="text-xl font-bold mb-2">For Encrypted Storage:</h3>
169+
<ol className="list-decimal list-inside space-y-1 text-base sm:text-lg ml-4">
170+
<li>Sign up or log in to your account</li>
171+
<li>Navigate to the Storage page</li>
172+
<li>Click "Choose File" to select files</li>
173+
<li>Files are encrypted locally and uploaded</li>
174+
<li>Generate share links or download later</li>
175+
</ol>
176+
</div>
177+
</div>
178+
</div>
179+
180+
{/* Source Code */}
181+
<div className="border-4 border-black dark:border-white p-6 bg-white dark:bg-black shadow-[8px_8px_0px_0px_rgba(0,0,0,1)] dark:shadow-[8px_8px_0px_0px_rgba(255,255,255,1)]">
182+
<h2 className="text-3xl font-black uppercase mb-4">Open Source</h2>
183+
<p className="text-base sm:text-lg leading-relaxed mb-3">
184+
E2ECP is free and open source software. You can view the code, contribute, or self-host your own instance.
185+
</p>
186+
<a
187+
href="https://github.com/schollz/e2ecp"
188+
target="_blank"
189+
rel="noopener noreferrer"
190+
className="inline-block border-2 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-6 py-3 font-black uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_0px_rgba(255,255,255,1)] hover:translate-x-1 hover:translate-y-1 hover:shadow-none active:translate-x-2 active:translate-y-2"
191+
>
192+
<i className="fab fa-github mr-2"></i>
193+
View on GitHub
194+
</a>
195+
</div>
196+
197+
{/* Footer */}
198+
<div className="text-center text-sm text-gray-600 dark:text-gray-400 py-4">
199+
Built with WebRTC, Go, and React
200+
</div>
201+
</div>
202+
</div>
203+
);
204+
}

web/src/App.jsx

Lines changed: 20 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2119,6 +2119,12 @@ export default function App() {
21192119
<i className="fas fa-hdd mr-2"></i>
21202120
Storage
21212121
</button>
2122+
<button
2123+
onClick={() => navigate("/about")}
2124+
className="border-2 sm:border-4 border-black dark:border-white bg-white dark:bg-black text-black dark:text-white px-4 py-2 sm:px-6 sm:py-3 font-black uppercase hover:bg-gray-100 dark:hover:bg-gray-900 transition-colors cursor-pointer shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_0px_rgba(255,255,255,1)] hover:translate-x-1 hover:translate-y-1 hover:shadow-none active:translate-x-2 active:translate-y-2 text-center"
2125+
>
2126+
More information
2127+
</button>
21222128
<button
21232129
onClick={logout}
21242130
className="border-2 sm:border-4 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-4 py-2 sm:px-6 sm:py-3 font-black uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_0px_rgba(255,255,255,1)] hover:translate-x-1 hover:translate-y-1 hover:shadow-none active:translate-x-2 active:translate-y-2 text-center"
@@ -2128,12 +2134,20 @@ export default function App() {
21282134
</button>
21292135
</div>
21302136
) : (
2131-
<button
2132-
onClick={() => navigate("/login")}
2133-
className="border-2 sm:border-4 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-4 py-3 sm:px-6 sm:py-3 font-black uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_0px_rgba(255,255,255,1)] hover:translate-x-1 hover:translate-y-1 hover:shadow-none active:translate-x-2 active:translate-y-2 w-full sm:w-auto text-center"
2134-
>
2135-
Sign in for storage
2136-
</button>
2137+
<div className="flex flex-col sm:flex-row gap-2 sm:gap-3">
2138+
<button
2139+
onClick={() => navigate("/login")}
2140+
className="border-2 sm:border-4 border-black dark:border-white bg-black dark:bg-white text-white dark:text-black px-4 py-3 sm:px-6 sm:py-3 font-black uppercase hover:bg-gray-900 dark:hover:bg-gray-300 transition-colors cursor-pointer shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_0px_rgba(255,255,255,1)] hover:translate-x-1 hover:translate-y-1 hover:shadow-none active:translate-x-2 active:translate-y-2 text-center"
2141+
>
2142+
Sign in for storage
2143+
</button>
2144+
<button
2145+
onClick={() => navigate("/about")}
2146+
className="border-2 sm:border-4 border-black dark:border-white bg-white dark:bg-black text-black dark:text-white px-4 py-3 sm:px-6 sm:py-3 font-black uppercase hover:bg-gray-100 dark:hover:bg-gray-900 transition-colors cursor-pointer shadow-[4px_4px_0px_0px_rgba(0,0,0,1)] dark:shadow-[4px_4px_0px_0px_rgba(255,255,255,1)] hover:translate-x-1 hover:translate-y-1 hover:shadow-none active:translate-x-2 active:translate-y-2 text-center"
2147+
>
2148+
More information
2149+
</button>
2150+
</div>
21372151
)}
21382152
</div>
21392153
)}

web/src/index.css

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
color utility to any element that depends on these defaults.
1616
*/
1717
@layer base {
18+
1819
*,
1920
::after,
2021
::before,
@@ -31,6 +32,7 @@
3132
font-family: "Monaspace Neon", monospace;
3233
text-transform: uppercase;
3334
}
35+
3436
button,
3537
input,
3638
select,
@@ -42,7 +44,7 @@
4244
textarea::placeholder {
4345
text-transform: uppercase;
4446
}
45-
47+
4648
/* Toast notification color variables */
4749
:root {
4850
--toast-bg: #fff;
@@ -51,24 +53,24 @@
5153
--toast-icon-primary: #000;
5254
--toast-icon-secondary: #fff;
5355
}
54-
56+
5557
:root.dark {
5658
--toast-bg: #000;
5759
--toast-text: #fff;
5860
--toast-border: 2px solid #fff;
5961
--toast-icon-primary: #fff;
6062
--toast-icon-secondary: #000;
6163
}
62-
64+
6365
/* Header box shadow for dark mode */
6466
.header-shadow {
6567
box-shadow: 4px 4px 0px 0px rgb(229, 231, 235), 0 0 0 4px black;
6668
}
67-
69+
6870
:root.dark .header-shadow {
6971
box-shadow: 4px 4px 0px 0px #fff, 0 0 0 4px #fff;
7072
}
71-
73+
7274
/* Override FontAwesome font-display from block to swap for better performance
7375
This prevents FOIT (Flash of Invisible Text) and improves FCP/LCP metrics */
7476
@font-face {
@@ -78,20 +80,24 @@
7880
font-display: swap;
7981
src: url(@fortawesome/fontawesome-free/webfonts/fa-brands-400.woff2) format("woff2");
8082
}
81-
83+
8284
@font-face {
8385
font-family: "Font Awesome 7 Free";
8486
font-style: normal;
8587
font-weight: 400;
8688
font-display: swap;
8789
src: url(@fortawesome/fontawesome-free/webfonts/fa-regular-400.woff2) format("woff2");
8890
}
89-
91+
9092
@font-face {
9193
font-family: "Font Awesome 7 Free";
9294
font-style: normal;
9395
font-weight: 900;
9496
font-display: swap;
9597
src: url(@fortawesome/fontawesome-free/webfonts/fa-solid-900.woff2) format("woff2");
9698
}
97-
}
99+
100+
.nocase {
101+
text-transform: none;
102+
}
103+
}

0 commit comments

Comments
 (0)