Added code sharing into editor
This commit is contained in:
250
index.html
250
index.html
@@ -165,6 +165,110 @@
|
|||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Share Modal */
|
||||||
|
.modal-overlay {
|
||||||
|
display: none;
|
||||||
|
position: fixed;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-color: rgba(0, 0, 0, 0.7);
|
||||||
|
z-index: 1000;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-overlay.active {
|
||||||
|
display: flex;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-content {
|
||||||
|
background-color: #2c292d;
|
||||||
|
border-radius: 8px;
|
||||||
|
padding: 24px;
|
||||||
|
max-width: 500px;
|
||||||
|
width: 90%;
|
||||||
|
box-shadow: 0 4px 20px rgba(0, 0, 0, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-header {
|
||||||
|
font-size: 20px;
|
||||||
|
font-weight: 600;
|
||||||
|
margin-bottom: 16px;
|
||||||
|
color: #f0f0f0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-body {
|
||||||
|
margin-bottom: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-container {
|
||||||
|
display: flex;
|
||||||
|
gap: 8px;
|
||||||
|
margin-top: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.link-input {
|
||||||
|
flex: 1;
|
||||||
|
padding: 10px 12px;
|
||||||
|
background-color: #1e1e1e;
|
||||||
|
border: 1px solid #444;
|
||||||
|
border-radius: 4px;
|
||||||
|
color: #f0f0f0;
|
||||||
|
font-family: 'Consolas', monospace;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #4CAF50;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-btn:hover {
|
||||||
|
background-color: #45a049;
|
||||||
|
}
|
||||||
|
|
||||||
|
.copy-btn.copied {
|
||||||
|
background-color: #2196F3;
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal-footer {
|
||||||
|
display: flex;
|
||||||
|
justify-content: flex-end;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn {
|
||||||
|
padding: 10px 20px;
|
||||||
|
background-color: #555;
|
||||||
|
color: white;
|
||||||
|
border: none;
|
||||||
|
border-radius: 4px;
|
||||||
|
cursor: pointer;
|
||||||
|
font-weight: 600;
|
||||||
|
transition: background-color 0.2s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.close-btn:hover {
|
||||||
|
background-color: #666;
|
||||||
|
}
|
||||||
|
|
||||||
|
.loading-text {
|
||||||
|
color: #aaa;
|
||||||
|
font-style: italic;
|
||||||
|
}
|
||||||
|
|
||||||
|
.error-text {
|
||||||
|
color: #ff6b6b;
|
||||||
|
margin-top: 8px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
<header>
|
<header>
|
||||||
@@ -184,6 +288,12 @@
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="header-right">
|
<div class="header-right">
|
||||||
|
<button class="icon-btn" title="Share Code" onclick="shareCode()">
|
||||||
|
<svg viewBox="0 0 24 24">
|
||||||
|
<path
|
||||||
|
d="M18 16.08c-.76 0-1.44.3-1.96.77L8.91 12.7c.05-.23.09-.46.09-.7s-.04-.47-.09-.7l7.05-4.11c.54.5 1.25.81 2.04.81 1.66 0 3-1.34 3-3s-1.34-3-3-3-3 1.34-3 3c0 .24.04.47.09.7L8.04 9.81C7.5 9.31 6.79 9 6 9c-1.66 0-3 1.34-3 3s1.34 3 3 3c.79 0 1.5-.31 2.04-.81l7.12 4.16c-.05.21-.08.43-.08.65 0 1.61 1.31 2.92 2.92 2.92 1.61 0 2.92-1.31 2.92-2.92s-1.31-2.92-2.92-2.92z" />
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
<button class="icon-btn" title="Open File" onclick="openFile()">
|
<button class="icon-btn" title="Open File" onclick="openFile()">
|
||||||
<svg viewBox="0 0 24 24">
|
<svg viewBox="0 0 24 24">
|
||||||
<path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" />
|
<path d="M10 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2h-8l-2-2z" />
|
||||||
@@ -210,6 +320,31 @@
|
|||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
|
<!-- Share Modal -->
|
||||||
|
<div id="shareModal" class="modal-overlay">
|
||||||
|
<div class="modal-content">
|
||||||
|
<div class="modal-header">Share Your Code</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<div id="modalMessage">
|
||||||
|
<p class="loading-text">Uploading code...</p>
|
||||||
|
</div>
|
||||||
|
<div id="linkSection" style="display: none;">
|
||||||
|
<p>Your code has been shared! Use this link:</p>
|
||||||
|
<div class="link-container">
|
||||||
|
<input type="text" id="shareLink" class="link-input" readonly>
|
||||||
|
<button class="copy-btn" onclick="copyShareLink()">Copy</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div id="errorSection" style="display: none;">
|
||||||
|
<p class="error-text" id="errorMessage"></p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button class="close-btn" onclick="closeShareModal()">Close</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js" crossorigin="anonymous"></script>
|
<script src="https://www.unpkg.com/ace-builds@latest/src-noconflict/ace.js" crossorigin="anonymous"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
@@ -452,8 +587,121 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
async function shareCode() {
|
||||||
|
const modal = document.getElementById('shareModal');
|
||||||
|
const modalMessage = document.getElementById('modalMessage');
|
||||||
|
const linkSection = document.getElementById('linkSection');
|
||||||
|
const errorSection = document.getElementById('errorSection');
|
||||||
|
const errorMessage = document.getElementById('errorMessage');
|
||||||
|
|
||||||
|
modalMessage.style.display = 'block';
|
||||||
|
modalMessage.innerHTML = '<p class="loading-text">Uploading code...</p>';
|
||||||
|
linkSection.style.display = 'none';
|
||||||
|
errorSection.style.display = 'none';
|
||||||
|
|
||||||
|
modal.classList.add('active');
|
||||||
|
|
||||||
|
try {
|
||||||
|
const code = codeEditor.getValue();
|
||||||
|
|
||||||
|
const response = await fetch('/codestorage', {
|
||||||
|
method: 'POST',
|
||||||
|
headers: {
|
||||||
|
'Content-Type': 'text/plain'
|
||||||
|
},
|
||||||
|
body: code
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await response.json();
|
||||||
|
|
||||||
|
if (data.status === 'success' && data.id) {
|
||||||
|
const url = new URL(window.location.href);
|
||||||
|
url.searchParams.set('id', data.id);
|
||||||
|
const shareableLink = url.toString();
|
||||||
|
|
||||||
|
modalMessage.style.display = 'none';
|
||||||
|
linkSection.style.display = 'block';
|
||||||
|
document.getElementById('shareLink').value = shareableLink;
|
||||||
|
|
||||||
|
term.write('\r\n✓ Code shared successfully! ID: ' + data.id + '\r\n');
|
||||||
|
} else {
|
||||||
|
throw new Error('Invalid response from server');
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Share failed:', error);
|
||||||
|
modalMessage.style.display = 'none';
|
||||||
|
errorSection.style.display = 'block';
|
||||||
|
errorMessage.textContent = 'Failed to share code: ' + error.message;
|
||||||
|
term.write('\r\n✗ Share failed: ' + error.message + '\r\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function copyShareLink() {
|
||||||
|
const linkInput = document.getElementById('shareLink');
|
||||||
|
const copyBtn = event.target;
|
||||||
|
|
||||||
|
linkInput.select();
|
||||||
|
linkInput.setSelectionRange(0, 99999);
|
||||||
|
|
||||||
|
navigator.clipboard.writeText(linkInput.value).then(() => {
|
||||||
|
const originalText = copyBtn.textContent;
|
||||||
|
copyBtn.textContent = 'Copied!';
|
||||||
|
copyBtn.classList.add('copied');
|
||||||
|
|
||||||
|
setTimeout(() => {
|
||||||
|
copyBtn.textContent = originalText;
|
||||||
|
copyBtn.classList.remove('copied');
|
||||||
|
}, 2000);
|
||||||
|
|
||||||
|
term.write('\r\n✓ Link copied to clipboard\r\n');
|
||||||
|
}).catch(err => {
|
||||||
|
console.error('Copy failed:', err);
|
||||||
|
term.write('\r\n✗ Failed to copy link\r\n');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function closeShareModal() {
|
||||||
|
const modal = document.getElementById('shareModal');
|
||||||
|
modal.classList.remove('active');
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('shareModal').addEventListener('click', function (e) {
|
||||||
|
if (e.target === this) {
|
||||||
|
closeShareModal();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
async function loadSharedCode() {
|
||||||
|
const urlParams = new URLSearchParams(window.location.search);
|
||||||
|
const id = urlParams.get('id');
|
||||||
|
|
||||||
|
if (id) {
|
||||||
|
try {
|
||||||
|
const response = await fetch(`/codestorage?id=${id}`);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(`HTTP error! status: ${response.status}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const code = await response.text();
|
||||||
|
codeEditor.setValue(code, -1);
|
||||||
|
|
||||||
|
term.write('\r\n✓ Loaded shared code (ID: ' + id + ')\r\n');
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to load shared code:', error);
|
||||||
|
term.write('\r\n✗ Failed to load shared code: ' + error.message + '\r\n');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
window.addEventListener('load', () => {
|
window.addEventListener('load', () => {
|
||||||
setTimeout(runCurrentCode, 100);
|
loadSharedCode().then(() => {
|
||||||
|
setTimeout(runCurrentCode, 100);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
window.addEventListener('resize', () => {
|
window.addEventListener('resize', () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user