commit 8d3e3d8e24fa6d52ce1716d7173e523c16bf77cd
parent ff2036a74fa37a5ac41dad18c6cf14163065229b
Author: Amit Dutta <amitdutta4255@gmail.com>
Date: Mon, 12 Jan 2026 19:27:55 +0530
new sharing logic (firebase) added
Diffstat:
| M | public/c.html | | | 206 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
| M | public/cpp.html | | | 201 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
| M | public/docs.html | | | 61 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
| M | public/index.html | | | 3 | ++- |
| M | public/python.html | | | 200 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
5 files changed, 549 insertions(+), 122 deletions(-)
diff --git a/public/c.html b/public/c.html
@@ -243,7 +243,42 @@ int main() {
</div>
</div>
- <script>
+ <script type="module">
+ import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js";
+ import { getFirestore, doc, getDoc, setDoc } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js";
+ import { getAuth, signInAnonymously } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js";
+
+ // --- Firebase Config ---
+ const firebaseConfig = {
+ apiKey: "AIzaSyC8U49NgW7EtYBeKL0Sw08-QvM_Bl59zDw",
+ authDomain: "compiler-aranag-site.firebaseapp.com",
+ projectId: "compiler-aranag-site",
+ storageBucket: "compiler-aranag-site.firebasestorage.app",
+ messagingSenderId: "558890639400",
+ appId: "1:558890639400:web:125525d10ab51696a5951d",
+ measurementId: "G-KH9BGSRRGY"
+ };
+
+ // Initialize Firebase
+ const app = initializeApp(firebaseConfig);
+ const db = getFirestore(app);
+ const auth = getAuth(app);
+
+ // Attempt initial sign-in, but don't crash if it fails (restricted op)
+ signInAnonymously(auth).catch((error) => {
+ console.warn("Auto-Auth failed (likely disabled in console). App will try unauthenticated access.", error.code);
+ });
+
+ // --- Helper: Generate ID ---
+ function generateId(length = 7) {
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ let result = '';
+ for (let i = 0; i < length; i++) {
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
+ }
+ return result;
+ }
+
// --- DOM Elements ---
const runBtn = document.getElementById('run-btn');
const resetBtn = document.getElementById('reset-btn');
@@ -293,13 +328,52 @@ int main() {
}
});
- window.addEventListener('load', () => {
+ window.addEventListener('load', async () => {
const params = new URLSearchParams(window.location.search);
- const sharedCode = params.get('code');
- if (sharedCode) {
- try { codeInput.value = atob(sharedCode); }
+ const shareId = params.get('share');
+ const sharedCodeOld = params.get('code');
+
+ if (shareId) {
+ // Fetch from Firebase
+ try {
+ toast.textContent = "Loading shared code...";
+ toast.classList.add('show');
+
+ const docRef = doc(db, "shares", shareId);
+ const docSnap = await getDoc(docRef);
+
+ if (docSnap.exists()) {
+ const data = docSnap.data();
+ codeInput.value = data.code;
+
+ // Restore Output if it exists
+ if (data.output && term) {
+ term.write('\r\n\x1b[38;2;115;115;115m> PREVIOUS OUTPUT:\x1b[0m\r\n');
+ term.write(data.output.replace(/\n/g, '\r\n'));
+ term.write('\r\n\x1b[38;2;115;115;115m> ----------------\x1b[0m\r\n');
+ }
+
+ toast.textContent = "Code loaded successfully";
+ } else {
+ toast.textContent = "Shared code not found";
+ }
+ setTimeout(() => toast.classList.remove('show'), 3000);
+ } catch (e) {
+ console.error("Fetch error:", e);
+ // More descriptive error for user
+ if (e.code === 'permission-denied') {
+ toast.textContent = "Error: Database Access Denied";
+ } else {
+ toast.textContent = "Error loading code";
+ }
+ setTimeout(() => toast.classList.remove('show'), 3000);
+ }
+ } else if (sharedCodeOld) {
+ // Fallback for Base64
+ try { codeInput.value = atob(sharedCodeOld); }
catch(e) {}
}
+
setTimeout(connect, 500);
});
@@ -326,6 +400,32 @@ int main() {
fitAddon.fit();
window.addEventListener('resize', () => fitAddon.fit());
+ // Helper: Get Clean Terminal Output
+ function getTerminalContent() {
+ if (!term) return "";
+ const buffer = term.buffer.active;
+ let text = "";
+ for (let i = 0; i < buffer.length; i++) {
+ const line = buffer.getLine(i);
+ if (line) {
+ let lineText = line.translateToString(true);
+ // Filter system messages
+ if(lineText.trim().startsWith("> [") ||
+ lineText.trim().startsWith("> ./a.out") ||
+ lineText.includes("SYSTEM READY") ||
+ lineText.includes("ATTEMPTING") ||
+ lineText.includes("CONNECTION") ||
+ lineText.includes("PREVIOUS OUTPUT") ||
+ lineText.includes("> ----------------")
+ ) {
+ continue;
+ }
+ text += lineText + "\n";
+ }
+ }
+ return text.trim();
+ }
+
// Custom Key Handler for Ctrl+C Copy
term.attachCustomKeyEventHandler((arg) => {
if (arg.ctrlKey && arg.code === "KeyC" && arg.type === "keydown") {
@@ -433,28 +533,70 @@ int main() {
term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> ./a.out\r\n`);
});
- // --- Share Functionality with Native Share API ---
+ // --- Share Functionality (Firebase) ---
shareBtn.addEventListener('click', async () => {
- const code = codeInput.value;
- const encoded = btoa(code);
- const url = new URL(window.location.href);
- url.searchParams.set('code', encoded);
- const shareUrl = url.toString();
-
- // Try native sharing first (Mobile/Supported Browsers)
- if (navigator.share) {
- try {
- await navigator.share({
- title: document.title,
- text: 'Check out my C code!',
- url: shareUrl
- });
- } catch (err) {
- // Ignore cancellation or errors, no fallback needed if cancelled
+ // Original Share icon animation
+ const originalIcon = shareBtn.innerHTML;
+ shareBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
+ shareBtn.disabled = true;
+
+ try {
+ // Robust Auth Check:
+ // 1. If not logged in, try to log in.
+ // 2. If login fails (restricted), proceed anyway (swallow error).
+ // 3. This allows "Test Mode" (open DB) to work even if Auth is disabled.
+ if (!auth.currentUser) {
+ try {
+ await signInAnonymously(auth);
+ } catch (authError) {
+ console.warn("Anonymous auth failed (proceeding to unauthenticated write attempt):", authError.code);
+ }
+ }
+
+ const code = codeInput.value;
+ const output = getTerminalContent(); // Capture output
+ const shareId = generateId();
+
+ // Save to Firestore
+ await setDoc(doc(db, "shares", shareId), {
+ code: code,
+ language: 'c',
+ output: output, // Store output
+ createdAt: new Date().toISOString()
+ });
+
+ // Generate URL
+ const url = new URL(window.location.href);
+ url.searchParams.delete('code'); // Remove legacy param
+ url.searchParams.set('share', shareId);
+ const shareUrl = url.toString();
+
+ // Share or Copy
+ if (navigator.share) {
+ try {
+ await navigator.share({
+ title: document.title,
+ text: 'Check out my C code!',
+ url: shareUrl
+ });
+ } catch (err) {
+ // If canceled, still copy to clipboard as fallback
+ fallbackCopyTextToClipboard(shareUrl);
+ }
+ } else {
+ fallbackCopyTextToClipboard(shareUrl);
+ }
+ } catch (error) {
+ console.error("Share failed:", error);
+ if (error.code === 'permission-denied') {
+ showToast("Share Failed: Access Denied");
+ console.log("Tip: Enable Anonymous Auth in Firebase Console OR set Firestore rules to public.");
+ } else {
+ showToast("Share Failed: " + error.message);
}
- } else {
- // Fallback to clipboard copy
- fallbackCopyTextToClipboard(shareUrl);
+ } finally {
+ shareBtn.innerHTML = originalIcon;
+ shareBtn.disabled = false;
}
});
@@ -466,19 +608,7 @@ int main() {
// --- Smart Copy Function ---
copyBtn.addEventListener('click', () => {
- const buffer = term.buffer.active;
- let text = "";
- for (let i = 0; i < buffer.length; i++) {
- const line = buffer.getLine(i);
- if (line) {
- let lineText = line.translateToString(true);
- if(lineText.trim().startsWith("> [") || lineText.trim().startsWith("> ./a.out") || lineText.includes("SYSTEM READY") || lineText.includes("ATTEMPTING") || lineText.includes("CONNECTION")) {
- continue;
- }
- text += lineText + "\n";
- }
- }
- text = text.trim();
+ const text = getTerminalContent();
fallbackCopyTextToClipboard(text);
});
diff --git a/public/cpp.html b/public/cpp.html
@@ -241,7 +241,42 @@ int main() {
</div>
</div>
- <script>
+ <script type="module">
+ import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js";
+ import { getFirestore, doc, getDoc, setDoc } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js";
+ import { getAuth, signInAnonymously } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js";
+
+ // --- Firebase Config ---
+ const firebaseConfig = {
+ apiKey: "AIzaSyC8U49NgW7EtYBeKL0Sw08-QvM_Bl59zDw",
+ authDomain: "compiler-aranag-site.firebaseapp.com",
+ projectId: "compiler-aranag-site",
+ storageBucket: "compiler-aranag-site.firebasestorage.app",
+ messagingSenderId: "558890639400",
+ appId: "1:558890639400:web:125525d10ab51696a5951d",
+ measurementId: "G-KH9BGSRRGY"
+ };
+
+ // Initialize Firebase
+ const app = initializeApp(firebaseConfig);
+ const db = getFirestore(app);
+ const auth = getAuth(app);
+
+ // Attempt initial sign-in, but don't crash if it fails (restricted op)
+ signInAnonymously(auth).catch((error) => {
+ console.warn("Auto-Auth failed (likely disabled in console). App will try unauthenticated access.", error.code);
+ });
+
+ // --- Helper: Generate ID ---
+ function generateId(length = 7) {
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ let result = '';
+ for (let i = 0; i < length; i++) {
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
+ }
+ return result;
+ }
+
// --- DOM Elements ---
const runBtn = document.getElementById('run-btn');
const resetBtn = document.getElementById('reset-btn');
@@ -291,13 +326,52 @@ int main() {
}
});
- window.addEventListener('load', () => {
+ window.addEventListener('load', async () => {
const params = new URLSearchParams(window.location.search);
- const sharedCode = params.get('code');
- if (sharedCode) {
- try { codeInput.value = atob(sharedCode); }
+ const shareId = params.get('share');
+ const sharedCodeOld = params.get('code');
+
+ if (shareId) {
+ // Fetch from Firebase
+ try {
+ toast.textContent = "Loading shared code...";
+ toast.classList.add('show');
+
+ const docRef = doc(db, "shares", shareId);
+ const docSnap = await getDoc(docRef);
+
+ if (docSnap.exists()) {
+ const data = docSnap.data();
+ codeInput.value = data.code;
+
+ // Restore Output if it exists
+ if (data.output && term) {
+ term.write('\r\n\x1b[38;2;115;115;115m> PREVIOUS OUTPUT:\x1b[0m\r\n');
+ term.write(data.output.replace(/\n/g, '\r\n'));
+ term.write('\r\n\x1b[38;2;115;115;115m> ----------------\x1b[0m\r\n');
+ }
+
+ toast.textContent = "Code loaded successfully";
+ } else {
+ toast.textContent = "Shared code not found";
+ }
+ setTimeout(() => toast.classList.remove('show'), 3000);
+ } catch (e) {
+ console.error("Fetch error:", e);
+ // More descriptive error for user
+ if (e.code === 'permission-denied') {
+ toast.textContent = "Error: Database Access Denied";
+ } else {
+ toast.textContent = "Error loading code";
+ }
+ setTimeout(() => toast.classList.remove('show'), 3000);
+ }
+ } else if (sharedCodeOld) {
+ // Fallback for Base64
+ try { codeInput.value = atob(sharedCodeOld); }
catch(e) {}
}
+
setTimeout(connect, 500);
});
@@ -324,6 +398,32 @@ int main() {
fitAddon.fit();
window.addEventListener('resize', () => fitAddon.fit());
+ // Helper: Get Clean Terminal Output
+ function getTerminalContent() {
+ if (!term) return "";
+ const buffer = term.buffer.active;
+ let text = "";
+ for (let i = 0; i < buffer.length; i++) {
+ const line = buffer.getLine(i);
+ if (line) {
+ let lineText = line.translateToString(true);
+ // Filter system messages
+ if(lineText.trim().startsWith("> [") ||
+ lineText.trim().startsWith("> ./a.out") ||
+ lineText.includes("SYSTEM READY") ||
+ lineText.includes("ATTEMPTING") ||
+ lineText.includes("CONNECTION") ||
+ lineText.includes("PREVIOUS OUTPUT") ||
+ lineText.includes("> ----------------")
+ ) {
+ continue;
+ }
+ text += lineText + "\n";
+ }
+ }
+ return text.trim();
+ }
+
// Custom Key Handler for Ctrl+C Copy
term.attachCustomKeyEventHandler((arg) => {
if (arg.ctrlKey && arg.code === "KeyC" && arg.type === "keydown") {
@@ -431,28 +531,65 @@ int main() {
term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> ./a.out\r\n`);
});
- // --- Share Functionality with Native Share API ---
+ // --- Share Functionality with Firebase ---
shareBtn.addEventListener('click', async () => {
- const code = codeInput.value;
- const encoded = btoa(code);
- const url = new URL(window.location.href);
- url.searchParams.set('code', encoded);
- const shareUrl = url.toString();
-
- // Try native sharing first (Mobile/Supported Browsers)
- if (navigator.share) {
- try {
- await navigator.share({
- title: document.title,
- text: 'Check out my C++ code!',
- url: shareUrl
- });
- } catch (err) {
- // Ignore cancellation or errors
+ // Original Share icon animation
+ const originalIcon = shareBtn.innerHTML;
+ shareBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
+ shareBtn.disabled = true;
+
+ try {
+ // Robust Auth Check
+ if (!auth.currentUser) {
+ try {
+ await signInAnonymously(auth);
+ } catch (authError) {
+ console.warn("Anonymous auth failed (proceeding to unauthenticated write attempt):", authError.code);
+ }
+ }
+
+ const code = codeInput.value;
+ const output = getTerminalContent();
+ const shareId = generateId();
+
+ // Save to Firestore
+ await setDoc(doc(db, "shares", shareId), {
+ code: code,
+ language: 'cpp',
+ output: output,
+ createdAt: new Date().toISOString()
+ });
+
+ // Generate URL
+ const url = new URL(window.location.href);
+ url.searchParams.delete('code');
+ url.searchParams.set('share', shareId);
+ const shareUrl = url.toString();
+
+ // Share or Copy
+ if (navigator.share) {
+ try {
+ await navigator.share({
+ title: document.title,
+ text: 'Check out my C++ code!',
+ url: shareUrl
+ });
+ } catch (err) {
+ fallbackCopyTextToClipboard(shareUrl);
+ }
+ } else {
+ fallbackCopyTextToClipboard(shareUrl);
+ }
+ } catch (error) {
+ console.error("Share failed:", error);
+ if (error.code === 'permission-denied') {
+ showToast("Share Failed: Access Denied");
+ } else {
+ showToast("Share Failed: " + error.message);
}
- } else {
- // Fallback to clipboard copy
- fallbackCopyTextToClipboard(shareUrl);
+ } finally {
+ shareBtn.innerHTML = originalIcon;
+ shareBtn.disabled = false;
}
});
@@ -464,19 +601,7 @@ int main() {
// --- Smart Copy Function ---
copyBtn.addEventListener('click', () => {
- const buffer = term.buffer.active;
- let text = "";
- for (let i = 0; i < buffer.length; i++) {
- const line = buffer.getLine(i);
- if (line) {
- let lineText = line.translateToString(true);
- if(lineText.trim().startsWith("> [") || lineText.trim().startsWith("> ./a.out") || lineText.includes("SYSTEM READY") || lineText.includes("ATTEMPTING") || lineText.includes("CONNECTION")) {
- continue;
- }
- text += lineText + "\n";
- }
- }
- text = text.trim();
+ const text = getTerminalContent();
fallbackCopyTextToClipboard(text);
});
diff --git a/public/docs.html b/public/docs.html
@@ -99,6 +99,7 @@
<a href="#communication" class="nav-link font-mono text-sm">WebSocket Protocol</a>
<a href="#python-engine" class="nav-link font-mono text-sm">Python Engine</a>
<a href="#cpp-engine" class="nav-link font-mono text-sm">C / C++ Engine</a>
+ <a href="#sharing" class="nav-link font-mono text-sm">Sharing & Persistence</a>
<a href="#security" class="nav-link font-mono text-sm">Security & Sandbox</a>
<a href="#privacy" class="nav-link font-mono text-sm">Privacy & Data</a>
<a href="#disclaimer" class="nav-link font-mono text-sm">Legal & Disclaimer</a>
@@ -108,7 +109,7 @@
<p class="text-xs text-neutral-400 mb-2">Powered by</p>
<div class="flex flex-wrap gap-2">
<span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">aiohttp</span>
- <span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">Python 3.10</span>
+ <span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">Firebase</span>
<span class="text-xs px-2 py-1 rounded bg-black border border-white/10 text-lime-300 font-mono">GCC 11</span>
</div>
</div>
@@ -236,11 +237,57 @@ def check_and_install_packages(code):
Standard Input buffer flushing is handled automatically to ensure prompts (like <code>cin >> var</code>) appear immediately in the terminal before blocking for input.
</p>
</section>
+
+ <!-- Sharing & Persistence -->
+ <section id="sharing" class="doc-section">
+ <h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center">
+ <span class="mr-3">05.</span> Sharing & Persistence
+ </h2>
+ <p class="text-neutral-300 mb-4">
+ The sharing functionality leverages <strong>Firebase Firestore</strong> to provide persistent access to code and execution results. This ensures that sharing a link not only loads the correct source code but also restores the exact terminal state seen at the moment of sharing.
+ </p>
+
+ <h3 class="text-lg font-bold text-white mt-6 mb-2">How Sharing Works</h3>
+ <div class="grid grid-cols-1 md:grid-cols-2 gap-6 my-4">
+ <div class="p-6 rounded-xl bg-white/5 border border-white/10">
+ <h4 class="text-white font-bold mb-2">1. Snapshot Creation</h4>
+ <p class="text-sm text-neutral-400 mb-2">
+ When the "Share" button is clicked, the system captures:
+ </p>
+ <ul class="list-disc list-inside text-xs text-neutral-500 space-y-1">
+ <li>The complete source code from the editor.</li>
+ <li>The current terminal output (stripped of system messages).</li>
+ <li>Metadata (language, timestamp).</li>
+ </ul>
+ </div>
+ <div class="p-6 rounded-xl bg-white/5 border border-white/10">
+ <h4 class="text-white font-bold mb-2">2. Storage & Retrieval</h4>
+ <p class="text-sm text-neutral-400 mb-2">
+ This data is stored in a Firestore document under a unique 7-character ID.
+ </p>
+ <ul class="list-disc list-inside text-xs text-neutral-500 space-y-1">
+ <li><strong>Write:</strong> Uses Anonymous Auth to securely write to the DB.</li>
+ <li><strong>Read:</strong> The URL `?share=ID` fetches this document.</li>
+ <li><strong>Restore:</strong> The editor fills with code, and the terminal replays the saved output.</li>
+ </ul>
+ </div>
+ </div>
+
+ <div class="code-block">
+ <pre><code class="language-javascript">// Data Structure in Firestore
+{
+ "code": "#include <stdio.h>\n...",
+ "language": "c",
+ "output": "Enter count: 5\nCounting to 5:\n1 2 3 4 5 \nDone.",
+ "createdAt": "2023-10-27T10:00:00.000Z"
+}</code></pre>
+ </div>
+ </section>
<!-- Security -->
<section id="security" class="doc-section">
<h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center">
- <span class="mr-3">05.</span> Security & Limitations
+ <span class="mr-3">06.</span> Security & Limitations
</h2>
<p class="text-neutral-300 mb-4">
The current implementation runs code directly on the host instance. While effective for a portfolio demonstration or trusted environment, this setup is <strong>not sandboxed</strong>.
@@ -268,16 +315,16 @@ def check_and_install_packages(code):
<!-- Privacy & Data Handling -->
<section id="privacy" class="doc-section">
<h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center">
- <span class="mr-3">06.</span> Privacy & Data Handling
+ <span class="mr-3">07.</span> Privacy & Data Handling
</h2>
<p class="text-neutral-300 mb-4">
We believe in complete transparency regarding how your data is handled. As a demonstration platform, we prioritize privacy and ephemeral execution.
</p>
<div class="grid grid-cols-1 md:grid-cols-3 gap-6 my-8">
<div class="p-6 rounded-xl bg-white/5 border border-white/10">
- <h3 class="text-white font-bold mb-2"><i class="fas fa-trash-alt text-lime-300 mr-2"></i> No Storage</h3>
+ <h3 class="text-white font-bold mb-2"><i class="fas fa-trash-alt text-lime-300 mr-2"></i> Ephemeral Execution</h3>
<p class="text-sm text-neutral-400">
- Your code is processed in volatile memory or temporary files that are <strong>immediately deleted</strong> after execution. We do not maintain a database of user code.
+ By default, your code is processed in volatile memory and <strong>immediately deleted</strong> after execution. Code is stored in our database <strong>only</strong> when you explicitly click "Share".
</p>
</div>
<div class="p-6 rounded-xl bg-white/5 border border-white/10">
@@ -289,7 +336,7 @@ def check_and_install_packages(code):
<div class="p-6 rounded-xl bg-white/5 border border-white/10">
<h3 class="text-white font-bold mb-2"><i class="fab fa-github text-lime-300 mr-2"></i> Open Source</h3>
<p class="text-sm text-neutral-400">
- The entire backend infrastructure is open source. You can audit the code yourself on <a href="https://github.com/notamitgamer" target="_blank" class="text-lime-300 hover:underline">GitHub</a>.
+ The entire backend infrastructure is open source. You can audit the code yourself on <a href="https://github.com/notamitgamer/cloud-compiler" target="_blank" class="text-lime-300 hover:underline">GitHub</a>.
</p>
</div>
</div>
@@ -298,7 +345,7 @@ def check_and_install_packages(code):
<!-- Legal & Disclaimer -->
<section id="disclaimer" class="doc-section">
<h2 class="text-2xl font-heading font-bold text-lime-300 mb-6 flex items-center">
- <span class="mr-3">07.</span> Legal & Disclaimer
+ <span class="mr-3">08.</span> Legal & Disclaimer
</h2>
<div class="p-6 rounded-xl border border-red-500/20 bg-red-500/5">
<p class="text-neutral-300 mb-4">
diff --git a/public/index.html b/public/index.html
@@ -355,4 +355,4 @@
});
</script>
</body>
-</html>
+</html>+
\ No newline at end of file
diff --git a/public/python.html b/public/python.html
@@ -232,7 +232,42 @@ print("Done.")</textarea>
</div>
</div>
- <script>
+ <script type="module">
+ import { initializeApp } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-app.js";
+ import { getFirestore, doc, getDoc, setDoc } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-firestore.js";
+ import { getAuth, signInAnonymously } from "https://www.gstatic.com/firebasejs/10.7.1/firebase-auth.js";
+
+ // --- Firebase Config ---
+ const firebaseConfig = {
+ apiKey: "AIzaSyC8U49NgW7EtYBeKL0Sw08-QvM_Bl59zDw",
+ authDomain: "compiler-aranag-site.firebaseapp.com",
+ projectId: "compiler-aranag-site",
+ storageBucket: "compiler-aranag-site.firebasestorage.app",
+ messagingSenderId: "558890639400",
+ appId: "1:558890639400:web:125525d10ab51696a5951d",
+ measurementId: "G-KH9BGSRRGY"
+ };
+
+ // Initialize Firebase
+ const app = initializeApp(firebaseConfig);
+ const db = getFirestore(app);
+ const auth = getAuth(app);
+
+ // Attempt initial sign-in
+ signInAnonymously(auth).catch((error) => {
+ console.warn("Auto-Auth failed. App will try unauthenticated access.", error.code);
+ });
+
+ // --- Helper: Generate ID ---
+ function generateId(length = 7) {
+ const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
+ let result = '';
+ for (let i = 0; i < length; i++) {
+ result += chars.charAt(Math.floor(Math.random() * chars.length));
+ }
+ return result;
+ }
+
// --- DOM Elements ---
const runBtn = document.getElementById('run-btn');
const resetBtn = document.getElementById('reset-btn');
@@ -274,11 +309,49 @@ print("Done.")</textarea>
}
});
- window.addEventListener('load', () => {
+ window.addEventListener('load', async () => {
const params = new URLSearchParams(window.location.search);
- const sharedCode = params.get('code');
- if (sharedCode) {
- try { codeInput.value = atob(sharedCode); }
+ const shareId = params.get('share');
+ const sharedCodeOld = params.get('code');
+
+ if (shareId) {
+ // Fetch from Firebase
+ try {
+ toast.textContent = "Loading shared code...";
+ toast.classList.add('show');
+
+ const docRef = doc(db, "shares", shareId);
+ const docSnap = await getDoc(docRef);
+
+ if (docSnap.exists()) {
+ const data = docSnap.data();
+ codeInput.value = data.code;
+
+ // Restore Output if it exists
+ if (data.output && term) {
+ term.write('\r\n\x1b[38;2;115;115;115m> PREVIOUS OUTPUT:\x1b[0m\r\n');
+ term.write(data.output.replace(/\n/g, '\r\n'));
+ term.write('\r\n\x1b[38;2;115;115;115m> ----------------\x1b[0m\r\n');
+ }
+
+ toast.textContent = "Code loaded successfully";
+ } else {
+ toast.textContent = "Shared code not found";
+ }
+ setTimeout(() => toast.classList.remove('show'), 3000);
+ } catch (e) {
+ console.error("Fetch error:", e);
+ // More descriptive error for user
+ if (e.code === 'permission-denied') {
+ toast.textContent = "Error: Database Access Denied";
+ } else {
+ toast.textContent = "Error loading code";
+ }
+ setTimeout(() => toast.classList.remove('show'), 3000);
+ }
+ } else if (sharedCodeOld) {
+ // Fallback for Base64
+ try { codeInput.value = atob(sharedCodeOld); }
catch(e) {}
}
setTimeout(connect, 500);
@@ -307,6 +380,32 @@ print("Done.")</textarea>
fitAddon.fit();
window.addEventListener('resize', () => fitAddon.fit());
+ // Helper: Get Clean Terminal Output
+ function getTerminalContent() {
+ if (!term) return "";
+ const buffer = term.buffer.active;
+ let text = "";
+ for (let i = 0; i < buffer.length; i++) {
+ const line = buffer.getLine(i);
+ if (line) {
+ let lineText = line.translateToString(true);
+ // Filter system messages
+ if(lineText.trim().startsWith("> [") ||
+ lineText.trim().startsWith("> python") ||
+ lineText.includes("SYSTEM READY") ||
+ lineText.includes("ATTEMPTING") ||
+ lineText.includes("CONNECTION") ||
+ lineText.includes("PREVIOUS OUTPUT") ||
+ lineText.includes("> ----------------")
+ ) {
+ continue;
+ }
+ text += lineText + "\n";
+ }
+ }
+ return text.trim();
+ }
+
// Custom Key Handler for Ctrl+C Copy
term.attachCustomKeyEventHandler((arg) => {
if (arg.ctrlKey && arg.code === "KeyC" && arg.type === "keydown") {
@@ -403,28 +502,65 @@ print("Done.")</textarea>
term.write(`\x1b[38;2;190;242;100m> CONNECTION ESTABLISHED.\x1b[0m\r\n> python3 main.py\r\n`);
});
- // --- Share Functionality with Native Share API ---
+ // --- Share Functionality with Firebase ---
shareBtn.addEventListener('click', async () => {
- const code = codeInput.value;
- const encoded = btoa(code);
- const url = new URL(window.location.href);
- url.searchParams.set('code', encoded);
- const shareUrl = url.toString();
-
- // Try native sharing first (Mobile/Supported Browsers)
- if (navigator.share) {
- try {
- await navigator.share({
- title: document.title,
- text: 'Check out my Python code!',
- url: shareUrl
- });
- } catch (err) {
- // Ignore cancellation or errors
+ // Original Share icon animation
+ const originalIcon = shareBtn.innerHTML;
+ shareBtn.innerHTML = '<i class="fas fa-spinner fa-spin"></i>';
+ shareBtn.disabled = true;
+
+ try {
+ // Robust Auth Check
+ if (!auth.currentUser) {
+ try {
+ await signInAnonymously(auth);
+ } catch (authError) {
+ console.warn("Anonymous auth failed (proceeding to unauthenticated write attempt):", authError.code);
+ }
+ }
+
+ const code = codeInput.value;
+ const output = getTerminalContent();
+ const shareId = generateId();
+
+ // Save to Firestore
+ await setDoc(doc(db, "shares", shareId), {
+ code: code,
+ language: 'python',
+ output: output,
+ createdAt: new Date().toISOString()
+ });
+
+ // Generate URL
+ const url = new URL(window.location.href);
+ url.searchParams.delete('code'); // Remove legacy param
+ url.searchParams.set('share', shareId);
+ const shareUrl = url.toString();
+
+ // Share or Copy
+ if (navigator.share) {
+ try {
+ await navigator.share({
+ title: document.title,
+ text: 'Check out my Python code!',
+ url: shareUrl
+ });
+ } catch (err) {
+ fallbackCopyTextToClipboard(shareUrl);
+ }
+ } else {
+ fallbackCopyTextToClipboard(shareUrl);
+ }
+ } catch (error) {
+ console.error("Share failed:", error);
+ if (error.code === 'permission-denied') {
+ showToast("Share Failed: Access Denied");
+ } else {
+ showToast("Share Failed: " + error.message);
}
- } else {
- // Fallback to clipboard copy
- fallbackCopyTextToClipboard(shareUrl);
+ } finally {
+ shareBtn.innerHTML = originalIcon;
+ shareBtn.disabled = false;
}
});
@@ -436,19 +572,7 @@ print("Done.")</textarea>
// --- Smart Copy Function ---
copyBtn.addEventListener('click', () => {
- const buffer = term.buffer.active;
- let text = "";
- for (let i = 0; i < buffer.length; i++) {
- const line = buffer.getLine(i);
- if (line) {
- let lineText = line.translateToString(true);
- if(lineText.trim().startsWith("> [") || lineText.trim().startsWith("> python") || lineText.includes("SYSTEM READY") || lineText.includes("ATTEMPTING") || lineText.includes("CONNECTION")) {
- continue;
- }
- text += lineText + "\n";
- }
- }
- text = text.trim();
+ const text = getTerminalContent();
fallbackCopyTextToClipboard(text);
});