attachment fix
This commit is contained in:
@@ -2447,6 +2447,38 @@ body.layout-legacy #comments-container.faded-out {
|
|||||||
font-size: 14px;
|
font-size: 14px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.cf-spoiler-btn {
|
||||||
|
background: none;
|
||||||
|
border: none;
|
||||||
|
color: #888;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 2px 4px;
|
||||||
|
font-size: 12px;
|
||||||
|
flex-shrink: 0;
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 2px;
|
||||||
|
transition: color 0.15s;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-spoiler-btn:hover,
|
||||||
|
.cf-is-spoiler .cf-spoiler-btn {
|
||||||
|
color: #f0a500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.cf-is-spoiler {
|
||||||
|
border-color: rgba(240, 165, 0, 0.4);
|
||||||
|
background: rgba(240, 165, 0, 0.06);
|
||||||
|
}
|
||||||
|
|
||||||
|
.spoiler-attach-badge {
|
||||||
|
font-size: 9px;
|
||||||
|
font-weight: 800;
|
||||||
|
line-height: 1;
|
||||||
|
color: #f0a500;
|
||||||
|
letter-spacing: 0.03em;
|
||||||
|
}
|
||||||
|
|
||||||
.comment-file-preview {
|
.comment-file-preview {
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-wrap: wrap;
|
flex-wrap: wrap;
|
||||||
|
|||||||
@@ -2326,10 +2326,15 @@ class CommentSystem {
|
|||||||
submitBtn.classList.add('uploading');
|
submitBtn.classList.add('uploading');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Insert placeholder at cursor position
|
// Use saved cursor position (set when attach btn was clicked, before file picker
|
||||||
const cursorPos = textarea.selectionStart;
|
// dismissed the keyboard on mobile causing selectionStart to become 0).
|
||||||
const before = textarea.value.substring(0, cursorPos);
|
const savedPos = wrap._savedCursorPos ?? textarea.selectionStart;
|
||||||
const after = textarea.value.substring(textarea.selectionEnd);
|
const savedEnd = wrap._savedCursorEnd ?? textarea.selectionEnd;
|
||||||
|
wrap._savedCursorPos = null;
|
||||||
|
wrap._savedCursorEnd = null;
|
||||||
|
|
||||||
|
const before = textarea.value.substring(0, savedPos);
|
||||||
|
const after = textarea.value.substring(savedEnd);
|
||||||
const placeholder = `[${uploadingText} ${file.name}]`;
|
const placeholder = `[${uploadingText} ${file.name}]`;
|
||||||
const sep = before.length > 0 && !/\s$/.test(before) ? ' ' : '';
|
const sep = before.length > 0 && !/\s$/.test(before) ? ' ' : '';
|
||||||
textarea.value = before + sep + placeholder + after;
|
textarea.value = before + sep + placeholder + after;
|
||||||
@@ -2358,13 +2363,14 @@ class CommentSystem {
|
|||||||
const json = await res.json();
|
const json = await res.json();
|
||||||
if (json.success && json.files && json.files.length > 0) {
|
if (json.success && json.files && json.files.length > 0) {
|
||||||
const fileData = json.files[0];
|
const fileData = json.files[0];
|
||||||
const url = `/c/${fileData.dest}${fileData.converted_gif ? '#gif' : ''}`;
|
const rawUrl = `/c/${fileData.dest}${fileData.converted_gif ? '#gif' : ''}`;
|
||||||
|
const url = rawUrl;
|
||||||
textarea.value = textarea.value.replace(placeholder, url);
|
textarea.value = textarea.value.replace(placeholder, url);
|
||||||
|
|
||||||
// Update preview with actual thumbnail
|
// Update preview with actual thumbnail
|
||||||
if (previewItem) {
|
if (previewItem) {
|
||||||
previewItem.classList.remove('cf-uploading');
|
previewItem.classList.remove('cf-uploading');
|
||||||
previewItem.dataset.url = url;
|
previewItem.dataset.url = rawUrl;
|
||||||
previewItem.dataset.fileId = fileData.id;
|
previewItem.dataset.fileId = fileData.id;
|
||||||
previewItem.dataset.dest = fileData.dest;
|
previewItem.dataset.dest = fileData.dest;
|
||||||
previewItem.dataset.mime = fileData.mime;
|
previewItem.dataset.mime = fileData.mime;
|
||||||
@@ -2373,12 +2379,12 @@ class CommentSystem {
|
|||||||
|
|
||||||
if (fileData.mime.startsWith('image/')) {
|
if (fileData.mime.startsWith('image/')) {
|
||||||
const img = document.createElement('img');
|
const img = document.createElement('img');
|
||||||
img.src = url;
|
img.src = rawUrl;
|
||||||
img.loading = 'lazy';
|
img.loading = 'lazy';
|
||||||
previewItem.appendChild(img);
|
previewItem.appendChild(img);
|
||||||
} else if (fileData.mime.startsWith('video/')) {
|
} else if (fileData.mime.startsWith('video/')) {
|
||||||
const vid = document.createElement('video');
|
const vid = document.createElement('video');
|
||||||
vid.src = url;
|
vid.src = rawUrl;
|
||||||
vid.muted = true;
|
vid.muted = true;
|
||||||
vid.preload = 'metadata';
|
vid.preload = 'metadata';
|
||||||
previewItem.appendChild(vid);
|
previewItem.appendChild(vid);
|
||||||
@@ -2393,10 +2399,18 @@ class CommentSystem {
|
|||||||
nameEl.textContent = file.name;
|
nameEl.textContent = file.name;
|
||||||
previewItem.appendChild(nameEl);
|
previewItem.appendChild(nameEl);
|
||||||
|
|
||||||
|
const spoilerBtn = document.createElement('button');
|
||||||
|
spoilerBtn.className = 'cf-spoiler-btn';
|
||||||
|
spoilerBtn.title = 'Toggle spoiler';
|
||||||
|
spoilerBtn.innerHTML = '<i class="fa-solid fa-paperclip"></i><span class="spoiler-attach-badge">S</span>';
|
||||||
|
spoilerBtn.type = 'button';
|
||||||
|
previewItem.appendChild(spoilerBtn);
|
||||||
|
|
||||||
const removeBtn = document.createElement('button');
|
const removeBtn = document.createElement('button');
|
||||||
removeBtn.className = 'cf-remove-btn';
|
removeBtn.className = 'cf-remove-btn';
|
||||||
removeBtn.title = removeLabel;
|
removeBtn.title = removeLabel;
|
||||||
removeBtn.innerHTML = '<i class="fa-solid fa-xmark"></i>';
|
removeBtn.innerHTML = '<i class="fa-solid fa-xmark"></i>';
|
||||||
|
removeBtn.type = 'button';
|
||||||
previewItem.appendChild(removeBtn);
|
previewItem.appendChild(removeBtn);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -2452,22 +2466,61 @@ class CommentSystem {
|
|||||||
// Attach file button
|
// Attach file button
|
||||||
if (target.matches('.comment-attach-btn') || target.closest('.comment-attach-btn')) {
|
if (target.matches('.comment-attach-btn') || target.closest('.comment-attach-btn')) {
|
||||||
const wrap = target.closest('.comment-input');
|
const wrap = target.closest('.comment-input');
|
||||||
|
const textarea = wrap?.querySelector('textarea');
|
||||||
|
if (textarea) {
|
||||||
|
wrap._savedCursorPos = textarea.selectionStart;
|
||||||
|
wrap._savedCursorEnd = textarea.selectionEnd;
|
||||||
|
}
|
||||||
const fileInput = wrap?.querySelector('.comment-file-input');
|
const fileInput = wrap?.querySelector('.comment-file-input');
|
||||||
if (fileInput) fileInput.click();
|
if (fileInput) fileInput.click();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Attach file as spoiler: toggle [spoiler] wrapping on a preview item
|
||||||
|
const spoilerToggle = target.closest('.cf-spoiler-btn');
|
||||||
|
if (spoilerToggle) {
|
||||||
|
const previewItem = spoilerToggle.closest('.cf-preview-item');
|
||||||
|
if (previewItem) {
|
||||||
|
const rawUrl = previewItem.dataset.url;
|
||||||
|
const wrap = previewItem.closest('.comment-input');
|
||||||
|
const textarea = wrap?.querySelector('textarea');
|
||||||
|
if (textarea && rawUrl) {
|
||||||
|
const escapedUrl = rawUrl.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&');
|
||||||
|
const spoilerPattern = new RegExp('\\[spoiler\\]' + escapedUrl + '\\[\/spoiler\\]', 'i');
|
||||||
|
if (spoilerPattern.test(textarea.value)) {
|
||||||
|
// Unwrap
|
||||||
|
textarea.value = textarea.value.replace(spoilerPattern, rawUrl);
|
||||||
|
previewItem.classList.remove('cf-is-spoiler');
|
||||||
|
spoilerToggle.title = 'Toggle spoiler';
|
||||||
|
} else {
|
||||||
|
// Wrap
|
||||||
|
textarea.value = textarea.value.replace(new RegExp(escapedUrl), `[spoiler]${rawUrl}[/spoiler]`);
|
||||||
|
previewItem.classList.add('cf-is-spoiler');
|
||||||
|
spoilerToggle.title = 'Remove spoiler';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Remove file preview + strip URL from textarea
|
// Remove file preview + strip URL from textarea
|
||||||
if (target.matches('.cf-remove-btn') || target.closest('.cf-remove-btn')) {
|
if (target.matches('.cf-remove-btn') || target.closest('.cf-remove-btn')) {
|
||||||
const previewItem = target.closest('.cf-preview-item');
|
const previewItem = target.closest('.cf-preview-item');
|
||||||
if (previewItem) {
|
if (previewItem) {
|
||||||
const url = previewItem.dataset.url;
|
const rawUrl = previewItem.dataset.url;
|
||||||
if (url) {
|
if (rawUrl) {
|
||||||
const wrap = previewItem.closest('.comment-input');
|
const wrap = previewItem.closest('.comment-input');
|
||||||
const textarea = wrap?.querySelector('textarea');
|
const textarea = wrap?.querySelector('textarea');
|
||||||
if (textarea) {
|
if (textarea) {
|
||||||
// Remove the URL and any surrounding newline
|
// Build patterns for both plain URL and spoiler-wrapped URL
|
||||||
textarea.value = textarea.value.replace(new RegExp('\\n?' + url.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&') + '\\n?'), '\n').replace(/^\n|\n$/g, '');
|
const escapedUrl = rawUrl.replace(/[.*+?^${}()|[\\]\\]/g, '\\$&');
|
||||||
|
const spoilerPattern = new RegExp('\\n?\\[spoiler\\]' + escapedUrl + '\\[\\/spoiler\\]\\n?', 'i');
|
||||||
|
const plainPattern = new RegExp('\\n?' + escapedUrl + '\\n?');
|
||||||
|
if (spoilerPattern.test(textarea.value)) {
|
||||||
|
textarea.value = textarea.value.replace(spoilerPattern, '\n').replace(/^\n|\n$/g, '');
|
||||||
|
} else {
|
||||||
|
textarea.value = textarea.value.replace(plainPattern, '\n').replace(/^\n|\n$/g, '');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
previewItem.remove();
|
previewItem.remove();
|
||||||
|
|||||||
Reference in New Issue
Block a user