243 lines
9.2 KiB
HTML
243 lines
9.2 KiB
HTML
{% extends "base.html" %}
|
|
|
|
{% block title %}Paste {{ paste.id }}{% endblock %}
|
|
|
|
{% block content %}
|
|
<!-- Modal de compartir (fuera del container para no afectar layout) -->
|
|
{% if paste.owner_id == current_user.id %}
|
|
<div class="modal fade" id="shareModal" tabindex="-1" aria-labelledby="shareModalLabel" aria-hidden="true">
|
|
<div class="modal-dialog">
|
|
<div class="modal-content">
|
|
<div class="modal-header">
|
|
<h5 class="modal-title">Share Paste</h5>
|
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
</div>
|
|
<div class="modal-body">
|
|
<div class="mb-3">
|
|
<input type="text" id="share-username" placeholder="Username" class="form-control">
|
|
<div id="user-suggestions" class="list-group position-absolute d-none" style="z-index: 1050;"></div>
|
|
</div>
|
|
<div class="form-check">
|
|
<input type="checkbox" id="share-can-edit" class="form-check-input" checked>
|
|
<label class="form-check-label" for="share-can-edit">Allow Edit</label>
|
|
</div>
|
|
</div>
|
|
<div class="modal-footer">
|
|
<button type="button" id="share-submit" class="btn btn-success">Share Paste</button>
|
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<!-- Contenido principal -->
|
|
<div class="container mt-4">
|
|
<h1 class="paste-title">Paste {{ paste.id }}</h1>
|
|
|
|
<p class="text-muted small">
|
|
{% if paste.filename and '.' in paste.filename %}
|
|
<strong>Extension:</strong> {{ paste.filename.split('.')[-1] }} |
|
|
{% endif %}
|
|
<strong>MIME Type:</strong> {{ paste.content_type }} |
|
|
<strong>Language:</strong> {{ paste.language }} |
|
|
<strong>Size:</strong>
|
|
{% if paste.size < 1024 %}
|
|
{{ paste.size }} bytes
|
|
{% elif paste.size < 1024 * 1024 %}
|
|
{{ '%.2f' | format(paste.size / 1024) }} KB
|
|
{% else %}
|
|
{{ '%.2f' | format(paste.size / (1024 * 1024)) }} MB
|
|
{% endif %}
|
|
</p>
|
|
|
|
<!-- Botones principales -->
|
|
<div class="d-flex flex-wrap gap-2 mb-2">
|
|
{% if paste.owner_id == current_user.id %}
|
|
<button id="share-button" class="btn btn-sm btn-primary" data-bs-toggle="modal" data-bs-target="#shareModal" title="Share Paste">
|
|
<i class="fas fa-share-alt"></i>
|
|
</button>
|
|
{% endif %}
|
|
|
|
{% if current_user.is_authenticated %}
|
|
<button id="favorite-button" class="btn btn-sm btn-secondary" title="Toggle Favorite">
|
|
<i class="fas fa-heart"></i>
|
|
</button>
|
|
{% endif %}
|
|
|
|
{% if can_edit %}
|
|
<a id="edit-button" href="{{ url_for('edit_paste_web', id=paste.id) }}" class="btn btn-sm btn-warning" title="Edit Paste">
|
|
<i class="fas fa-edit"></i>
|
|
</a>
|
|
{% endif %}
|
|
|
|
{% if current_user.is_authenticated %}
|
|
<button id="ai-generate-code" class="btn btn-sm btn-secondary" title="AI Suggestions">✨</button>
|
|
{% endif %}
|
|
</div>
|
|
|
|
<!-- Resultado generado por IA -->
|
|
<div id="generated-code-container" class="d-none mt-3">
|
|
<pre id="generated-code-box" class="highlight">
|
|
<code id="generated-code" class="language-markdown"></code>
|
|
</pre>
|
|
</div>
|
|
|
|
<style>
|
|
/* Estilos para el contenedor generado */
|
|
#generated-code-container {
|
|
position: relative;
|
|
z-index: 1;
|
|
max-width: 100%;
|
|
overflow-x: auto;
|
|
margin-bottom: 1rem;
|
|
}
|
|
|
|
/* Caja del código generado */
|
|
#generated-code-box {
|
|
font-family: "Fira Code", monospace;
|
|
font-size: 14px;
|
|
border: 1px solid #444;
|
|
padding: 10px;
|
|
max-height: 300px;
|
|
overflow-y: auto;
|
|
border-radius: 8px;
|
|
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.2);
|
|
white-space: pre-wrap;
|
|
word-wrap: break-word;
|
|
background-color: #f8f9fa;
|
|
color: #212529;
|
|
}
|
|
|
|
/* Tema oscuro */
|
|
body.dark-mode #generated-code-box {
|
|
background-color: #1e1e1e;
|
|
color: #c9d1d9;
|
|
border-color: #444;
|
|
}
|
|
|
|
/* Tema claro */
|
|
body.light-mode #generated-code-box {
|
|
background-color: #f8f9fa;
|
|
color: #212529;
|
|
border-color: #ccc;
|
|
}
|
|
</style>
|
|
|
|
<div class="mb-3">
|
|
<div class="d-flex justify-content-between align-items-center mb-2 flex-wrap">
|
|
<div class="mb-2">
|
|
{% if not is_markdown %}
|
|
<button id="copy-button" class="btn btn-sm btn-secondary me-2" title="Copy Content">
|
|
<i class="fas fa-clipboard"></i>
|
|
</button>
|
|
{% endif %}
|
|
<a class="btn btn-sm btn-primary" href="{{ url_for('download_paste', id=paste.id) }}" download title="Download Paste">
|
|
<i class="fas fa-download"></i>
|
|
</a>
|
|
<button id="copy-url-button" class="btn btn-sm btn-secondary" title="Copy URL">
|
|
<i class="fas fa-link"></i>
|
|
</button>
|
|
</div>
|
|
<div>
|
|
<label for="pygments-style" class="form-label me-2 mb-0">Style:</label>
|
|
<select id="pygments-style" class="form-select form-select-sm style-selector d-inline-block w-auto">
|
|
{% for style in pygments_styles %}
|
|
<option value="{{ style }}" {% if style == default_pygments_style %}selected{% endif %}>{{ style.replace('-', ' ').capitalize() }}</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
{% if is_markdown %}
|
|
<div class="markdown-body">{{ md_html_code|safe }}</div>
|
|
{% else %}
|
|
<div class="highlight"><code class="language-{{ paste.language|lower }}">{{ html_code|safe }}</code></div>
|
|
{% endif %}
|
|
|
|
<p class="mt-3">View the raw version <a href="{{ url_for('get_paste_raw', id=paste.id) }}">here</a>.</p>
|
|
</div>
|
|
</div>
|
|
{% endblock %}
|
|
|
|
{% block scripts %}
|
|
{{ super() }}
|
|
<script src="{{ url_for('static', filename='js/share-paste.js') }}" defer></script>
|
|
<script src="{{ url_for('static', filename='js/share-autocomplete.js') }}" defer></script>
|
|
<script src="{{ url_for('static', filename='js/copy-paste.js') }}" defer></script>
|
|
<script src="{{ url_for('static', filename='js/pygments-style.js') }}" defer></script>
|
|
<script src="{{ url_for('static', filename='js/unshare.js') }}" defer></script>
|
|
|
|
<script>
|
|
document.addEventListener("DOMContentLoaded", function () {
|
|
// Verificar autenticación
|
|
const isAuthenticated = {{ "true" if current_user.is_authenticated else "false" }};
|
|
const aiButton = document.getElementById("ai-generate-code");
|
|
const aiContainer = document.getElementById("generated-code-container");
|
|
const outputElement = document.getElementById("generated-code");
|
|
|
|
if (!isAuthenticated) {
|
|
if (aiButton) aiButton.style.display = "none";
|
|
if (aiContainer) aiContainer.style.display = "none";
|
|
return;
|
|
}
|
|
|
|
if (aiButton && outputElement && aiContainer) {
|
|
aiButton.addEventListener("click", function () {
|
|
outputElement.textContent = "";
|
|
aiContainer.classList.remove("d-none");
|
|
|
|
fetch("{{ url_for('generate_code_from_paste', id=paste.id) }}")
|
|
.then(response => {
|
|
const reader = response.body.getReader();
|
|
const decoder = new TextDecoder();
|
|
let text = "";
|
|
|
|
function readChunk() {
|
|
reader.read().then(({ done, value }) => {
|
|
if (done) return;
|
|
let chunkText = decoder.decode(value, { stream: true });
|
|
chunkText = chunkText.replace(/data: \{"id":.*?"choices":\[\{"delta":\{"content":"(.*?)"\}\}\]\}/g, "$1");
|
|
text += chunkText;
|
|
outputElement.textContent = text;
|
|
outputElement.scrollTop = outputElement.scrollHeight;
|
|
readChunk();
|
|
});
|
|
}
|
|
|
|
readChunk();
|
|
})
|
|
.catch(error => alert("Error generando código: " + error));
|
|
});
|
|
}
|
|
|
|
// Tema claro/oscuro
|
|
function updateCodeTheme() {
|
|
const codeBox = document.getElementById("generated-code-box");
|
|
if (!codeBox) return;
|
|
const body = document.body;
|
|
|
|
if (body.classList.contains("dark-mode")) {
|
|
codeBox.classList.remove("light-mode");
|
|
codeBox.classList.add("dark-mode");
|
|
} else {
|
|
codeBox.classList.remove("dark-mode");
|
|
codeBox.classList.add("light-mode");
|
|
}
|
|
}
|
|
|
|
updateCodeTheme();
|
|
|
|
const themeToggle = document.getElementById("theme-toggle");
|
|
if (themeToggle) {
|
|
themeToggle.addEventListener("click", function () {
|
|
document.body.classList.toggle("dark-mode");
|
|
document.body.classList.toggle("light-mode");
|
|
updateCodeTheme();
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
{% endblock %}
|
|
|