v1.8.1: allow media-only beeps (image/GIF/voice/quote/poll without text)
- PHP: submit_beep accepts empty content when any attachment flag is set - JS: composer button enables when text is empty but media is attached - JS: button refreshes on every media state change via custom event - Version bump + readme changelog
This commit is contained in:
+52
-2
@@ -88,26 +88,53 @@
|
||||
var button = compose.querySelector('[data-beep-submit]');
|
||||
if (!input || !button) return;
|
||||
|
||||
function hasAttachments() {
|
||||
var pendingImages = compose._beepPendingImages;
|
||||
var pendingVoice = compose._beepPendingVoice;
|
||||
var hasGif = !!compose._beepGifUrl;
|
||||
var hasQuote = !!(compose._beepQuotedPost && compose._beepQuotedPost.id);
|
||||
var hasPoll = !!collectPollData(compose);
|
||||
return (
|
||||
(pendingImages && pendingImages.length) ||
|
||||
pendingVoice ||
|
||||
hasGif ||
|
||||
hasQuote ||
|
||||
hasPoll
|
||||
);
|
||||
}
|
||||
|
||||
function refresh() {
|
||||
autosize(input);
|
||||
var remaining = limit - countChars(input.value);
|
||||
counter.textContent = remaining;
|
||||
counter.classList.toggle('beep-counter-warn', remaining < 20 && remaining >= 0);
|
||||
counter.classList.toggle('beep-counter-bad', remaining < 0);
|
||||
button.disabled = input.value.trim() === '' || remaining < 0;
|
||||
// Button is enabled when there's text OR any attachment (images, voice, GIF, quote, poll).
|
||||
button.disabled = !(input.value.trim() !== '' || hasAttachments()) || remaining < 0;
|
||||
}
|
||||
input.addEventListener('input', refresh);
|
||||
// Media / GIF / quote / poll changes also affect whether the button should be enabled.
|
||||
compose.addEventListener('beep:attachments-changed', refresh);
|
||||
refresh();
|
||||
|
||||
button.addEventListener('click', function () {
|
||||
var content = input.value.trim();
|
||||
if (!content) return;
|
||||
// Allow image-only / media-only posts. Gate is "must have text OR an attachment".
|
||||
if (!content && !hasAttachments()) return;
|
||||
button.disabled = true;
|
||||
var quotedPost = compose._beepQuotedPost;
|
||||
var gifUrl = compose._beepGifUrl;
|
||||
var pending = compose._beepPendingImages;
|
||||
var pendingVoice = compose._beepPendingVoice;
|
||||
var poll = collectPollData(compose);
|
||||
|
||||
var payload = { content: content };
|
||||
if (quotedPost && quotedPost.id) payload.quote_id = quotedPost.id;
|
||||
if (gifUrl) payload.gif_url = gifUrl;
|
||||
// Tell the server what attachments are coming so it can accept empty content.
|
||||
if (pending && pending.length) payload.has_images = 1;
|
||||
if (pendingVoice) payload.has_voice = 1;
|
||||
if (poll) payload.has_poll = 1;
|
||||
|
||||
fetch(config.restUrl + 'post', {
|
||||
method: 'POST',
|
||||
@@ -128,6 +155,7 @@
|
||||
clearQuotePreview(compose);
|
||||
if (compose._beepGifUrl) {
|
||||
compose._beepGifUrl = null;
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
var gifPrev = compose.querySelector('[data-beep-gif-preview]');
|
||||
if (gifPrev) { gifPrev.innerHTML = ''; gifPrev.hidden = true; }
|
||||
}
|
||||
@@ -308,6 +336,7 @@
|
||||
if (compose) {
|
||||
compose._beepQuotedPost = { id: quoted.id, data: quoted };
|
||||
showQuotePreview(compose, quoted);
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
})
|
||||
.catch(function() { showToast('Beep not found.', 'error'); });
|
||||
@@ -344,6 +373,7 @@
|
||||
var compose = gifRemoveBtn.closest('[data-beep-compose]');
|
||||
if (compose) {
|
||||
compose._beepGifUrl = null;
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
var preview = compose.querySelector('[data-beep-gif-preview]');
|
||||
if (preview) { preview.innerHTML = ''; preview.hidden = true; }
|
||||
}
|
||||
@@ -695,6 +725,7 @@
|
||||
compose._beepPendingVoice = pendingVoice;
|
||||
voicePreview.innerHTML = '<div class="beep-voice-preview-card"><svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M12 14c1.66 0 3-1.34 3-3V5c0-1.66-1.34-3-3-3S9 3.34 9 5v6c0 1.66 1.34 3 3 3zm-1-9c0-.55.45-1 1-1s1 .45 1 1v6c0 .55-.45 1-1 1s-1-.45-1-1V5zm6 6c0 2.76-2.24 5-5 5s-5-2.24-5-5H5c0 3.53 2.61 6.43 6 6.92V21h2v-3.08C16.39 17.43 19 14.53 19 11h-2z"/></svg><span>Voice note ready</span><button class="beep-voice-remove" data-beep-voice-remove type="button" title="Remove">×</button></div>';
|
||||
voicePreview.hidden = false;
|
||||
if (compose) compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
voiceInput.value = '';
|
||||
@@ -710,6 +741,7 @@
|
||||
if (compose) compose._beepPendingVoice = null;
|
||||
voicePreview.innerHTML = '';
|
||||
voicePreview.hidden = true;
|
||||
if (compose) compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -731,6 +763,7 @@
|
||||
var id = 'pending-' + Date.now() + '-' + Math.random().toString(36).substr(2, 6);
|
||||
pendingImages.push({ file: file, previewUrl: url, id: id });
|
||||
renderPreviews();
|
||||
if (compose) compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
};
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
@@ -766,6 +799,7 @@
|
||||
pendingImages = pendingImages.filter(function (img) { return img.id !== id; });
|
||||
compose._beepPendingImages = pendingImages;
|
||||
renderPreviews();
|
||||
if (compose) compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -773,6 +807,15 @@
|
||||
compose._beepPendingImages = pendingImages;
|
||||
compose._beepPendingVoice = pendingVoice;
|
||||
}
|
||||
|
||||
// Poll input changes also affect "has attachments" (poll becomes valid mid-typing).
|
||||
if (compose) {
|
||||
compose.addEventListener('input', function (e) {
|
||||
if (e.target.matches('[data-beep-poll-question], [data-beep-poll-option]')) {
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function uploadPendingImages(postId, pendingImages, compose) {
|
||||
@@ -886,6 +929,7 @@
|
||||
.then(function(quoted) {
|
||||
compose._beepQuotedPost = { id: quotedId, data: quoted };
|
||||
showQuotePreview(compose, quoted);
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
})
|
||||
.catch(function(err) { console.warn('Could not load quoted beep:', err); });
|
||||
}
|
||||
@@ -919,6 +963,7 @@
|
||||
var removeBtn = compose.querySelector('[data-beep-quote-remove]');
|
||||
if (preview) { preview.innerHTML = ''; preview.hidden = true; }
|
||||
if (removeBtn) removeBtn.hidden = true;
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
|
||||
/* ---------- GIF Picker (Giphy) ---------- */
|
||||
@@ -989,6 +1034,7 @@
|
||||
preview.hidden = false;
|
||||
}
|
||||
closeGifPicker();
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
|
||||
/* ---------- Poll helpers ---------- */
|
||||
@@ -1005,6 +1051,7 @@
|
||||
options = pollSection.querySelectorAll('[data-beep-poll-option]');
|
||||
}
|
||||
}
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
|
||||
function addPollOption(compose) {
|
||||
@@ -1019,6 +1066,7 @@
|
||||
newRow.innerHTML = '<input type="text" class="beep-poll-option-input" data-beep-poll-option placeholder="Option ' + (optionCount + 1) + '" maxlength="100">';
|
||||
optionsContainer.appendChild(newRow);
|
||||
updatePollButtons(compose);
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
|
||||
function removePollOption(compose) {
|
||||
@@ -1029,6 +1077,7 @@
|
||||
var lastOption = options[options.length - 1];
|
||||
if (lastOption) lastOption.parentElement.remove();
|
||||
updatePollButtons(compose);
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
|
||||
function updatePollButtons(compose) {
|
||||
@@ -1060,6 +1109,7 @@
|
||||
options[j].value = '';
|
||||
}
|
||||
}
|
||||
compose.dispatchEvent(new CustomEvent('beep:attachments-changed'));
|
||||
}
|
||||
|
||||
function collectPollData(compose) {
|
||||
|
||||
Reference in New Issue
Block a user