feat: scrollable view layout, discussions extend page, word wrap toggle, divider-style comments

This commit is contained in:
ComputerTech 2026-04-06 21:10:14 +01:00
parent 89e194a435
commit 24d70aeb08
3 changed files with 66 additions and 39 deletions

View File

@ -183,6 +183,14 @@ body {
min-height: 0; min-height: 0;
} }
/* On the view page, override to allow the discussions to extend below */
.full-page.view-page {
overflow: visible;
overflow-y: auto;
min-height: 0;
flex: 1;
}
/* ── Editor textarea ───────────────────────────────────────────────────── */ /* ── Editor textarea ───────────────────────────────────────────────────── */
.full-editor { .full-editor {
flex: 1; flex: 1;
@ -202,10 +210,8 @@ body {
/* ── View: full-page code ──────────────────────────────────────────────── */ /* ── View: full-page code ──────────────────────────────────────────────── */
.view-full { .view-full {
flex: 1; min-height: calc(100vh - 42px); /* at least full viewport below navbar */
overflow: auto;
background: var(--code-bg); background: var(--code-bg);
min-height: 0;
} }
.view-full pre { .view-full pre {
margin: 0; margin: 0;
@ -218,6 +224,12 @@ body {
font-size: 0.875rem; font-size: 0.875rem;
line-height: 1.6; line-height: 1.6;
} }
/* Word wrap toggle */
.view-full.wrap-lines pre,
.view-full.wrap-lines code {
white-space: pre-wrap;
word-break: break-all;
}
/* ── Inline error (view page) ──────────────────────────────────────────── */ /* ── Inline error (view page) ──────────────────────────────────────────── */
.error-inline { .error-inline {
@ -401,14 +413,10 @@ pre[class*="language-"], code[class*="language-"] {
/* ── Discussions panel ────────────────────────────────────────────────── */ /* ── Discussions panel ────────────────────────────────────────────────── */
.discussions-panel { .discussions-panel {
flex-shrink: 0;
flex-direction: column; flex-direction: column;
border-top: 1px solid var(--border); border-top: 2px solid var(--border);
background: var(--surface); background: var(--surface);
max-height: 45vh; /* no max-height — extends the page naturally */
}
.discussions-panel.collapsed {
max-height: none;
} }
.discussions-panel.collapsed .discussions-body { .discussions-panel.collapsed .discussions-body {
display: none; display: none;
@ -417,39 +425,40 @@ pre[class*="language-"], code[class*="language-"] {
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
padding: 0.35rem 1rem; padding: 0.5rem 1.5rem;
cursor: pointer; cursor: pointer;
font-size: 0.8rem; font-size: 0.85rem;
color: var(--text-sub); color: var(--text-sub);
flex-shrink: 0; flex-shrink: 0;
user-select: none; user-select: none;
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
position: sticky;
top: 42px; /* stick just below navbar */
background: var(--surface);
z-index: 5;
} }
.discussions-header:hover { background: var(--bg); } .discussions-header:hover { background: var(--bg); }
.discussions-title { font-weight: 600; } .discussions-title { font-weight: 600; }
.discussions-chevron { font-size: 0.7rem; color: var(--text-muted); } .discussions-chevron { font-size: 0.7rem; color: var(--text-muted); }
.discussions-body { .discussions-body {
flex: 1; padding: 0.5rem 0;
display: flex;
flex-direction: column;
overflow: hidden;
min-height: 0;
} }
.comments-list { .comments-list {
flex: 1; padding: 0 1.5rem;
overflow-y: auto;
padding: 0.25rem 1rem;
min-height: 0;
} }
.comment-item { .comment-item {
padding: 0.45rem 0; padding: 0.6rem 0;
border-bottom: 1px solid var(--border); border-bottom: 1px solid var(--border);
} }
.comment-item:last-child { border-bottom: none; } .comment-item:last-child { border-bottom: none; }
.comment-meta { .comment-meta {
font-size: 0.7rem; font-size: 0.72rem;
color: var(--text-muted); color: var(--text-muted);
margin-bottom: 0.2rem; margin-bottom: 0.3rem;
}
.comment-meta.has-nick {
color: var(--primary);
font-weight: 600;
} }
.comment-content { .comment-content {
font-size: 0.85rem; font-size: 0.85rem;
@ -460,22 +469,22 @@ pre[class*="language-"], code[class*="language-"] {
.comments-loading, .comments-empty { .comments-loading, .comments-empty {
font-size: 0.8rem; font-size: 0.8rem;
color: var(--text-muted); color: var(--text-muted);
padding: 0.5rem 0; padding: 0.75rem 0;
} }
.comment-form-wrap { .comment-form-wrap {
display: flex; display: flex;
gap: 0.5rem; gap: 0.5rem;
padding: 0.4rem 1rem; padding: 0.75rem 1.5rem 1rem;
border-top: 1px solid var(--border); border-top: 1px solid var(--border);
align-items: flex-start; align-items: flex-start;
flex-shrink: 0; margin-top: 0.25rem;
background: var(--surface); background: var(--surface);
} }
.comment-form-fields { .comment-form-fields {
flex: 1; flex: 1;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
gap: 0.3rem; gap: 0.35rem;
min-width: 0; min-width: 0;
} }
.comment-nick { .comment-nick {
@ -484,26 +493,24 @@ pre[class*="language-"], code[class*="language-"] {
border-radius: var(--radius); border-radius: var(--radius);
color: var(--text); color: var(--text);
font-family: inherit; font-family: inherit;
font-size: 0.78rem; font-size: 0.8rem;
padding: 0.25rem 0.6rem; padding: 0.3rem 0.6rem;
outline: none; outline: none;
width: 160px; width: 180px;
} }
.comment-nick:focus { border-color: var(--primary); } .comment-nick:focus { border-color: var(--primary); }
.comment-input { .comment-input {
flex: 1;
background: var(--bg); background: var(--bg);
border: 1px solid var(--border); border: 1px solid var(--border);
border-radius: var(--radius); border-radius: var(--radius);
color: var(--text); color: var(--text);
font-family: inherit; font-family: inherit;
font-size: 0.8rem; font-size: 0.85rem;
padding: 0.35rem 0.6rem; padding: 0.4rem 0.6rem;
resize: none; resize: vertical;
min-height: 2.2rem; min-height: 4rem;
max-height: 8rem;
outline: none; outline: none;
line-height: 1.4; line-height: 1.5;
width: 100%;
} }
.comment-input:focus { border-color: var(--primary); } .comment-input:focus { border-color: var(--primary); }
.comment-meta.has-nick { color: var(--primary); font-weight: 600; }

View File

@ -62,6 +62,7 @@ document.addEventListener('DOMContentLoaded', async () => {
initPasteActions(); initPasteActions();
initLineHighlight(); // register Prism hook before initLineNumbers triggers Prism initLineHighlight(); // register Prism hook before initLineNumbers triggers Prism
initLineNumbers(); initLineNumbers();
initWordWrap();
initDiscussions(); initDiscussions();
initDeletion(); initDeletion();
}); });
@ -340,6 +341,22 @@ function _updateLineUrl(start, end) {
// ── Discussions ─────────────────────────────────────────────────────────────── // ── Discussions ───────────────────────────────────────────────────────────────
function initWordWrap() {
const toggle = document.getElementById('wrapToggle');
const viewDiv = document.getElementById('viewFull');
if (!toggle || !viewDiv) return;
const stored = localStorage.getItem('wrap_lines');
const enabled = stored === null ? true : stored === 'true';
toggle.checked = enabled;
viewDiv.classList.toggle('wrap-lines', enabled);
toggle.addEventListener('change', () => {
viewDiv.classList.toggle('wrap-lines', toggle.checked);
localStorage.setItem('wrap_lines', toggle.checked);
});
}
function initDiscussions() { function initDiscussions() {
if (!_decryptedPaste?.discussions) return; if (!_decryptedPaste?.discussions) return;
const panel = document.getElementById('discussionsPanel'); const panel = document.getElementById('discussionsPanel');

View File

@ -1,13 +1,16 @@
{% extends "base.html" %} {% extends "base.html" %}
{% block title %}{{ cfg.site.name }}{% endblock %} {% block title %}{{ cfg.site.name }}{% endblock %}
{% block main_class %}full-page{% endblock %} {% block main_class %}full-page view-page{% endblock %}
{% block nav_actions %} {% block nav_actions %}
<span id="navPasteTitle" class="nav-paste-title"></span> <span id="navPasteTitle" class="nav-paste-title"></span>
<label class="nav-label" title="Toggle line numbers"> <label class="nav-label" title="Toggle line numbers">
<input type="checkbox" id="lineNoToggle" checked> Lines <input type="checkbox" id="lineNoToggle" checked> Lines
</label> </label>
<label class="nav-label" title="Toggle word wrap">
<input type="checkbox" id="wrapToggle" checked> Wrap
</label>
<button id="rawBtn" class="nav-btn">Raw</button> <button id="rawBtn" class="nav-btn">Raw</button>
<button id="copyBtn" class="nav-btn">Copy</button> <button id="copyBtn" class="nav-btn">Copy</button>
<button id="downloadBtn" class="nav-btn">Download</button> <button id="downloadBtn" class="nav-btn">Download</button>