Add voice message support: audio upload (MP3/OGG/WAV/WebM/M4A), inline audio player in posts, voice note button + preview in composer
This commit is contained in:
+110
@@ -947,3 +947,113 @@
|
|||||||
justify-content: flex-end;
|
justify-content: flex-end;
|
||||||
gap: 8px;
|
gap: 8px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* ---------- Voice note button in composer ---------- */
|
||||||
|
.beep-voice-btn {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
width: 32px;
|
||||||
|
height: 32px;
|
||||||
|
border-radius: 50%;
|
||||||
|
color: var(--beep-accent);
|
||||||
|
cursor: pointer;
|
||||||
|
transition: background-color 0.15s ease, color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-btn:hover {
|
||||||
|
background: rgba(29, 155, 240, 0.10);
|
||||||
|
color: var(--beep-accent);
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-btn svg {
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Voice note preview in composer ---------- */
|
||||||
|
.beep-compose-voice-preview {
|
||||||
|
margin-top: 8px;
|
||||||
|
margin-bottom: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-compose-voice-preview[hidden] {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-preview-card {
|
||||||
|
display: inline-flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 8px;
|
||||||
|
background: var(--beep-hover);
|
||||||
|
border: 1px solid var(--beep-border);
|
||||||
|
border-radius: 9999px;
|
||||||
|
padding: 6px 12px 6px 10px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--beep-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-preview-card svg {
|
||||||
|
color: var(--beep-accent);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-remove {
|
||||||
|
background: transparent;
|
||||||
|
border: 0;
|
||||||
|
color: var(--beep-text-secondary);
|
||||||
|
font-size: 18px;
|
||||||
|
line-height: 1;
|
||||||
|
cursor: pointer;
|
||||||
|
padding: 0 0 0 4px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
transition: color 0.15s ease;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-remove:hover {
|
||||||
|
color: #F4212E;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ---------- Voice note player in posts ---------- */
|
||||||
|
.beep-voice-note {
|
||||||
|
margin: 6px 0 2px;
|
||||||
|
background: var(--beep-hover);
|
||||||
|
border: 1px solid var(--beep-border);
|
||||||
|
border-radius: 12px;
|
||||||
|
padding: 10px 14px;
|
||||||
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
|
gap: 6px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-note audio {
|
||||||
|
width: 100%;
|
||||||
|
height: 36px;
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Style the audio element across browsers */
|
||||||
|
.beep-voice-note audio::-webkit-media-controls-panel {
|
||||||
|
background: var(--beep-bg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-label {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
gap: 6px;
|
||||||
|
font-size: 13px;
|
||||||
|
color: var(--beep-text-secondary);
|
||||||
|
font-weight: 500;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-label svg {
|
||||||
|
color: var(--beep-accent);
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
.beep-voice-duration {
|
||||||
|
font-size: 12px;
|
||||||
|
color: var(--beep-text-secondary);
|
||||||
|
font-variant-numeric: tabular-nums;
|
||||||
|
}
|
||||||
|
|||||||
+88
-6
@@ -65,13 +65,23 @@
|
|||||||
input.value = '';
|
input.value = '';
|
||||||
refresh();
|
refresh();
|
||||||
|
|
||||||
// Upload pending images to this new beep
|
// Upload pending images and voice note to this new beep
|
||||||
var pending = compose._beepPendingImages;
|
var pending = compose._beepPendingImages;
|
||||||
|
var pendingVoice = compose._beepPendingVoice;
|
||||||
|
var uploadDone = function () {
|
||||||
|
reloadFeed(feed, 'recent');
|
||||||
|
};
|
||||||
|
|
||||||
|
var tasks = [];
|
||||||
if (pending && pending.length && data.id) {
|
if (pending && pending.length && data.id) {
|
||||||
uploadPendingImages(data.id, pending, compose).then(function () {
|
tasks.push(uploadPendingImages(data.id, pending, compose));
|
||||||
// Refresh the beep in the DOM to show uploaded images
|
}
|
||||||
reloadFeed(feed, 'recent');
|
if (pendingVoice && data.id) {
|
||||||
});
|
tasks.push(uploadPendingVoice(data.id, pendingVoice, compose));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tasks.length) {
|
||||||
|
Promise.all(tasks).then(uploadDone);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.catch(function () {
|
.catch(function () {
|
||||||
@@ -341,9 +351,57 @@
|
|||||||
var input = compose.querySelector('[data-beep-media-input]');
|
var input = compose.querySelector('[data-beep-media-input]');
|
||||||
var preview = compose.querySelector('[data-beep-media-preview]');
|
var preview = compose.querySelector('[data-beep-media-preview]');
|
||||||
var counter = compose.querySelector('[data-beep-media-count]');
|
var counter = compose.querySelector('[data-beep-media-count]');
|
||||||
if (!input) return;
|
var voiceInput = compose.querySelector('[data-beep-voice-input]');
|
||||||
|
var voicePreview = compose.querySelector('[data-beep-voice-preview]');
|
||||||
|
if (!input && !voiceInput) return;
|
||||||
|
|
||||||
var pendingImages = [];
|
var pendingImages = [];
|
||||||
|
var pendingVoice = null; // { file, id }
|
||||||
|
|
||||||
|
// Voice note input
|
||||||
|
if (voiceInput) {
|
||||||
|
voiceInput.addEventListener('change', function (e) {
|
||||||
|
var files = e.target.files;
|
||||||
|
if (!files || !files.length) return;
|
||||||
|
var file = files[0];
|
||||||
|
if (file.size > 20 * 1024 * 1024) {
|
||||||
|
window.alert('Voice note must be under 20 MB.');
|
||||||
|
voiceInput.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var accepted = ['audio/mpeg','audio/ogg','audio/wav','audio/webm','audio/mp4','audio/x-m4a'];
|
||||||
|
if (accepted.indexOf(file.type) === -1) {
|
||||||
|
window.alert('Only MP3, OGG, WAV, WebM, and M4A audio are allowed.');
|
||||||
|
voiceInput.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (pendingVoice) {
|
||||||
|
window.alert('Only one voice note per beep.');
|
||||||
|
voiceInput.value = '';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var reader = new FileReader();
|
||||||
|
reader.onload = function (ev) {
|
||||||
|
var id = 'voice-' + Date.now();
|
||||||
|
pendingVoice = { file: file, id: id };
|
||||||
|
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</span><button class="beep-voice-remove" data-beep-voice-remove type="button" title="Remove">×</button></div>';
|
||||||
|
voicePreview.hidden = false;
|
||||||
|
};
|
||||||
|
reader.readAsDataURL(file);
|
||||||
|
voiceInput.value = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Voice remove button
|
||||||
|
if (voicePreview) {
|
||||||
|
voicePreview.addEventListener('click', function (e) {
|
||||||
|
var btn = e.target.closest('[data-beep-voice-remove]');
|
||||||
|
if (!btn) return;
|
||||||
|
pendingVoice = null;
|
||||||
|
voicePreview.innerHTML = '';
|
||||||
|
voicePreview.hidden = true;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
input.addEventListener('change', function (e) {
|
input.addEventListener('change', function (e) {
|
||||||
var files = Array.prototype.slice.call(e.target.files);
|
var files = Array.prototype.slice.call(e.target.files);
|
||||||
@@ -397,6 +455,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
compose._beepPendingImages = pendingImages;
|
compose._beepPendingImages = pendingImages;
|
||||||
|
compose._beepPendingVoice = pendingVoice;
|
||||||
}
|
}
|
||||||
|
|
||||||
function uploadPendingImages(postId, pendingImages, compose) {
|
function uploadPendingImages(postId, pendingImages, compose) {
|
||||||
@@ -426,6 +485,29 @@
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function uploadPendingVoice(postId, pendingVoice, compose) {
|
||||||
|
if (!pendingVoice) return Promise.resolve();
|
||||||
|
var formData = new FormData();
|
||||||
|
formData.append('file', pendingVoice.file);
|
||||||
|
return fetch(config.restUrl + 'voice/' + postId, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'X-WP-Nonce': config.nonce },
|
||||||
|
credentials: 'same-origin',
|
||||||
|
body: formData
|
||||||
|
})
|
||||||
|
.then(handleResponse)
|
||||||
|
.then(function () {
|
||||||
|
pendingVoice = null;
|
||||||
|
if (compose) {
|
||||||
|
var vp = compose.querySelector('[data-beep-voice-preview]');
|
||||||
|
if (vp) { vp.innerHTML = ''; vp.hidden = true; }
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch(function (err) {
|
||||||
|
console.warn('Voice upload failed:', err);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
function handleResponse(res) {
|
function handleResponse(res) {
|
||||||
if (!res.ok) return res.json().then(function (j) { throw j; }, function () { throw res; });
|
if (!res.ok) return res.json().then(function (j) { throw j; }, function () { throw res; });
|
||||||
return res.json();
|
return res.json();
|
||||||
|
|||||||
@@ -217,4 +217,98 @@ class Beep_Media {
|
|||||||
delete_post_meta($post_id, self::META_KEY_IMAGES);
|
delete_post_meta($post_id, self::META_KEY_IMAGES);
|
||||||
delete_post_meta($post_id, self::META_KEY_VIDEO);
|
delete_post_meta($post_id, self::META_KEY_VIDEO);
|
||||||
}
|
}
|
||||||
}
|
// Voice note support
|
||||||
|
private static $audio_types = ['audio/mpeg', 'audio/ogg', 'audio/wav', 'audio/webm', 'audio/mp4', 'audio/x-m4a'];
|
||||||
|
private static $max_audio_size = 20 * 1024 * 1024; // 20 MB
|
||||||
|
|
||||||
|
public static function handle_voice_upload($post_id, $file) {
|
||||||
|
if (!is_array($file) || $file['error'] !== UPLOAD_ERR_OK) {
|
||||||
|
return new WP_Error('upload_error', 'Upload failed.');
|
||||||
|
}
|
||||||
|
if ($file['size'] > self::$max_audio_size) {
|
||||||
|
return new WP_Error('file_too_large', 'Voice note exceeds 20 MB limit.');
|
||||||
|
}
|
||||||
|
$mime = mime_content_type($file['tmp_name']);
|
||||||
|
if (!in_array($mime, self::$audio_types, true)) {
|
||||||
|
return new WP_Error('invalid_type', 'Only MP3, OGG, WAV, WebM, and M4A audio are allowed.');
|
||||||
|
}
|
||||||
|
|
||||||
|
require_once ABSPATH . 'wp-admin/includes/file.php';
|
||||||
|
require_once ABSPATH . 'wp-admin/includes/media.php';
|
||||||
|
|
||||||
|
$file_return = wp_handle_upload($file, [
|
||||||
|
'test_form' => false,
|
||||||
|
'mimes' => [
|
||||||
|
'mp3' => 'audio/mpeg',
|
||||||
|
'ogg' => 'audio/ogg',
|
||||||
|
'wav' => 'audio/wav',
|
||||||
|
'webm' => 'audio/webm',
|
||||||
|
'm4a' => 'audio/mp4',
|
||||||
|
],
|
||||||
|
]);
|
||||||
|
|
||||||
|
if (isset($file_return['error'])) {
|
||||||
|
return new WP_Error('upload_error', $file_return['error']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$attachment = [
|
||||||
|
'post_mime_type' => $file_return['type'],
|
||||||
|
'post_title' => preg_replace('/\.[^.]+$/', '', basename($file_return['file'])),
|
||||||
|
'post_content' => '',
|
||||||
|
'post_status' => 'inherit',
|
||||||
|
'guid' => $file_return['url'],
|
||||||
|
];
|
||||||
|
|
||||||
|
$attachment_id = wp_insert_attachment($attachment, $file_return['file'], $post_id);
|
||||||
|
if (is_wp_error($attachment_id)) {
|
||||||
|
return $attachment_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
$attach_data = wp_generate_attachment_metadata($attachment_id, $file_return['file']);
|
||||||
|
wp_update_attachment_metadata($attachment_id, $attach_data);
|
||||||
|
|
||||||
|
update_post_meta($post_id, 'beep_voice_url', wp_get_attachment_url($attachment_id));
|
||||||
|
update_post_meta($post_id, 'beep_voice_id', $attachment_id);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $attachment_id,
|
||||||
|
'url' => wp_get_attachment_url($attachment_id),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function get_voice_url($post_id) {
|
||||||
|
return esc_url_raw(get_post_meta($post_id, 'beep_voice_url', true));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function remove_voice($post_id) {
|
||||||
|
$id = (int) get_post_meta($post_id, 'beep_voice_id', true);
|
||||||
|
if ($id) {
|
||||||
|
wp_delete_attachment($id, true);
|
||||||
|
}
|
||||||
|
delete_post_meta($post_id, 'beep_voice_url');
|
||||||
|
delete_post_meta($post_id, 'beep_voice_id');
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function render_voice_note($post_id) {
|
||||||
|
$url = self::get_voice_url($post_id);
|
||||||
|
if (!$url) return '';
|
||||||
|
$duration = '';
|
||||||
|
$meta = get_post_meta($post_id, 'beep_voice_id', true);
|
||||||
|
if ($meta) {
|
||||||
|
$metadata = wp_get_attachment_metadata($meta);
|
||||||
|
if ($metadata && isset($metadata['length_formatted'])) {
|
||||||
|
$duration = $metadata['length_formatted'];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$dur_html = $duration ? '<span class="beep-voice-duration">' . esc_html($duration) . '</span>' : '';
|
||||||
|
return '<div class="beep-voice-note">' .
|
||||||
|
'<audio controls preload="none">' .
|
||||||
|
'<source src="' . esc_url($url) . '">' .
|
||||||
|
'Your browser does not support audio playback.' .
|
||||||
|
'</audio>' .
|
||||||
|
'<div class="beep-voice-label"><svg viewBox="0 0 24 24" width="16" height="16" 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>Voice note</div>' .
|
||||||
|
$dur_html .
|
||||||
|
'</div>';
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -150,6 +150,13 @@ class Beep_Shortcode {
|
|||||||
return is_user_logged_in() && !beep_user_is_banned(get_current_user_id());
|
return is_user_logged_in() && !beep_user_is_banned(get_current_user_id());
|
||||||
},
|
},
|
||||||
]);
|
]);
|
||||||
|
register_rest_route('beep/v1', '/voice/(?P<post_id>\d+)', [
|
||||||
|
'methods' => 'POST',
|
||||||
|
'callback' => [__CLASS__, 'upload_voice'],
|
||||||
|
'permission_callback' => function () {
|
||||||
|
return is_user_logged_in() && !beep_user_is_banned(get_current_user_id());
|
||||||
|
},
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static function upload_media($request) {
|
public static function upload_media($request) {
|
||||||
@@ -188,4 +195,25 @@ class Beep_Shortcode {
|
|||||||
Beep_Media::remove_image($post_id, $attachment_id);
|
Beep_Media::remove_image($post_id, $attachment_id);
|
||||||
return rest_ensure_response(['ok' => true]);
|
return rest_ensure_response(['ok' => true]);
|
||||||
}
|
}
|
||||||
}
|
public static function upload_voice($request) {
|
||||||
|
$post_id = (int) $request->get_param('post_id');
|
||||||
|
$post = get_post($post_id);
|
||||||
|
|
||||||
|
if (!$post || $post->post_type !== Beep_CPT::POST_TYPE) {
|
||||||
|
return new WP_Error('not_found', 'Beep not found.', 404);
|
||||||
|
}
|
||||||
|
if (!current_user_can('edit_post', $post_id)) {
|
||||||
|
return new WP_Error('forbidden', 'Cannot edit this beep.', 403);
|
||||||
|
}
|
||||||
|
if (empty($_FILES['file'])) {
|
||||||
|
return new WP_Error('no_file', 'No file uploaded.');
|
||||||
|
}
|
||||||
|
|
||||||
|
$result = Beep_Media::handle_voice_upload($post_id, $_FILES['file']);
|
||||||
|
if (is_wp_error($result)) {
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
return rest_ensure_response($result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
+18
-1
@@ -46,12 +46,23 @@ function beep_render_composer() {
|
|||||||
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
|
<svg viewBox="0 0 24 24" width="20" height="20" fill="currentColor"><path d="M21 19V5c0-1.1-.9-2-2-2H5c-1.1 0-2 .9-2 2v14c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2zM8.5 13.5l2.5 3.01L14.5 12l4.5 6H5l3.5-4.5z"/></svg>
|
||||||
</label>
|
</label>
|
||||||
<span class="beep-media-count" data-beep-media-count hidden>0/4</span>
|
<span class="beep-media-count" data-beep-media-count hidden>0/4</span>
|
||||||
|
<label class="beep-voice-btn" title="Add voice note">
|
||||||
|
<input type="file" accept="audio/mpeg,audio/ogg,audio/wav,audio/webm,audio/mp4,audio/x-m4a" data-beep-voice-input hidden>
|
||||||
|
<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>
|
||||||
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<span class="beep-char-counter" data-beep-counter><?php echo (int) BEEP_CHAR_LIMIT; ?></span>
|
<span class="beep-char-counter" data-beep-counter><?php echo (int) BEEP_CHAR_LIMIT; ?></span>
|
||||||
<button class="beep-button beep-post-button" data-beep-submit disabled>Beep</button>
|
<button class="beep-button beep-post-button" data-beep-submit disabled>Beep</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="beep-compose-media-preview" data-beep-media-preview hidden></div> <div class="beep-compose-footer">
|
<div class="beep-compose-media-preview" data-beep-media-preview hidden></div>
|
||||||
|
<div class="beep-compose-voice-preview" data-beep-voice-preview hidden>
|
||||||
|
<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</span>
|
||||||
|
<button class="beep-voice-remove" data-beep-voice-remove type="button" title="Remove">×</button>
|
||||||
|
</div>
|
||||||
|
</div> <div class="beep-compose-footer">
|
||||||
<span class="beep-char-counter" data-beep-counter><?php echo (int) BEEP_CHAR_LIMIT; ?></span>
|
<span class="beep-char-counter" data-beep-counter><?php echo (int) BEEP_CHAR_LIMIT; ?></span>
|
||||||
<button class="beep-button beep-post-button" data-beep-submit disabled>Beep</button>
|
<button class="beep-button beep-post-button" data-beep-submit disabled>Beep</button>
|
||||||
</div>
|
</div>
|
||||||
@@ -88,6 +99,7 @@ function beep_render_post($post) {
|
|||||||
$can_interact = is_user_logged_in() && !beep_user_is_banned(get_current_user_id());
|
$can_interact = is_user_logged_in() && !beep_user_is_banned(get_current_user_id());
|
||||||
$beep_images = Beep_Media::get_images($post->ID);
|
$beep_images = Beep_Media::get_images($post->ID);
|
||||||
$beep_video = Beep_Media::get_video_url($post->ID);
|
$beep_video = Beep_Media::get_video_url($post->ID);
|
||||||
|
$beep_voice = Beep_Media::get_voice_url($post->ID);
|
||||||
|
|
||||||
ob_start();
|
ob_start();
|
||||||
?>
|
?>
|
||||||
@@ -117,6 +129,11 @@ function beep_render_post($post) {
|
|||||||
<?php echo Beep_Media::render_video_embed($beep_video); ?>
|
<?php echo Beep_Media::render_video_embed($beep_video); ?>
|
||||||
</div>
|
</div>
|
||||||
<?php endif; ?>
|
<?php endif; ?>
|
||||||
|
<?php if ($beep_voice) : ?>
|
||||||
|
<div class="beep-media-attachments">
|
||||||
|
<?php echo Beep_Media::render_voice_note($post->ID); ?>
|
||||||
|
</div>
|
||||||
|
<?php endif; ?>
|
||||||
<div class="beep-actions">
|
<div class="beep-actions">
|
||||||
<button class="beep-action beep-action-reply"
|
<button class="beep-action beep-action-reply"
|
||||||
data-beep-toggle-reply
|
data-beep-toggle-reply
|
||||||
|
|||||||
Reference in New Issue
Block a user