Archived
1
0

Implement video upload to posts

This commit is contained in:
Marcel 2018-12-30 18:52:30 +01:00
parent 1f3e0243cf
commit ebb5c473f6
11 changed files with 1063 additions and 571 deletions

View File

@ -63,6 +63,8 @@
$route['user/getComments'] = 'user/getComments'; $route['user/getComments'] = 'user/getComments';
$route['user/getBlogPosts'] = 'user/getBlogPosts'; $route['user/getBlogPosts'] = 'user/getBlogPosts';
$route['user/publishPost'] = 'user/publishPost'; $route['user/publishPost'] = 'user/publishPost';
$route['user/uploadPostMedia'] = 'user/uploadPostMedia';
$route['user/deletePostMedia'] = 'user/deletePostMedia';
$route['user/switchFollowing'] = 'user/switchFollowing'; $route['user/switchFollowing'] = 'user/switchFollowing';
$route['user/getReportModal'] = 'user/getReportModal'; $route['user/getReportModal'] = 'user/getReportModal';
$route['user/(:any)'] = 'user/index/$1'; $route['user/(:any)'] = 'user/index/$1';

File diff suppressed because it is too large Load Diff

View File

@ -52,5 +52,5 @@
$lang['header_post'] = 'Post'; $lang['header_post'] = 'Post';
$lang['header_post_title'] = 'Post verfassen'; $lang['header_post_title'] = 'Post verfassen';
$lang['header_post_content'] = 'Inhalt'; $lang['header_post_content'] = 'Inhalt';
$lang['header_post_notice'] = 'Es wird an einer Funktion zum Uploaden von Fotos, Videos und anderen Medien gearbeitet. In hoffentlich naher Zukunft wirst du auch die Möglichkeit haben, diese zu deinen Posts hinzuzufügen!'; $lang['header_post_notice'] = 'Derzeit arbeiten wir intensiv daran, dir die Möglichkeit zu bieten, neben Bildern und Videos auch Audio-Aufnahmen hinzuzufügen und vor allem mithilfe von unter anderem einer direkten Kamera-Integration das Nutzererlebnis deutlich besser zu gestalten. Auch möchten wir die Text-Eingabe deutlich komfortabler gestalten. Also, stay tuned!';
$lang['header_post_publish'] = 'Veröffentlichen'; $lang['header_post_publish'] = 'Veröffentlichen';

View File

@ -61,3 +61,27 @@
$lang['post_copy_link'] = 'Link zum Post kopieren'; $lang['post_copy_link'] = 'Link zum Post kopieren';
$lang['post_report'] = 'Post melden'; $lang['post_report'] = 'Post melden';
$lang['post_delete'] = 'Post löschen'; $lang['post_delete'] = 'Post löschen';
$lang['post_error_login_title'] = 'Veröffentlichung des Posts nicht möglich!';
$lang['post_error_login_lines'] = [
'Du musst in deinen Account eingeloggt sein, um Posts erstellen zu können.',
'Bitte erstelle dir entweder <a href="' . base_url('login') . '">kostenlos einen neuen Account</a> oder <a href="' . base_url('login') . '">melde dich an</a>.'
];
$lang['post_error_too_long_title'] = 'Veröffentlichung des Posts fehlgeschlagen!';
$lang['post_error_too_long_lines'] = [
'Dein Post ist leider zu lang. Er darf maximal 10.000 Zeichen umfassen.',
];
$lang['post_error_reply_title'] = 'Veröffentlichung des Posts fehlgeschlagen!';
$lang['post_error_reply_lines'] = [
'Der Post, an den du deine Antwort richten willst, existiert nicht (mehr).',
'Solltest du dies für einen Fehler halten, versuche es später erneut oder kontaktiere uns.',
];
$lang['post_error_no_conent_title'] = 'Veröffentlichung des Posts nicht möglich!';
$lang['post_error_no_conent_lines'] = [
'Du hast uns leider keinen Inhalt angegeben, den wir veröffentlichen können.',
'Sollte es sich dabei um ein Irrtum handeln, so kontaktiere uns bitte über das Kontakt-Formular.',
];
$lang['post_success_title'] = '';
$lang['post_success_lines'] = [
'',
];

View File

@ -11,8 +11,24 @@ class FileModel extends CI_Model
parent::__construct(); parent::__construct();
} }
private function getPath($fileName, $userContent) { private function getPath($fileName, $user) {
return 'files/' . ($userContent ? 'userContent/' : '') . $fileName; return 'files/' . ($user != null ? 'userContent/' . $user . '/' : '') . $fileName;
}
private function addToDatabase($name, $originalName, $type, $size, $path, $user) {
$userID = NULL;
if(is_string($user)) {
$user = $this->db->query('SELECT ID FROM users WHERE username = lower(?)', [$user])->result_array();
if(!empty($user)) {
$userID = $user[0]['ID'];
}
} else if(is_integer($user)) {
$userID = $user;
}
$this->db->query('INSERT INTO files (name, original_name, type, size, path, user) VALUES (?, ?, ?, ?, ?, ?)', [$name, $originalName, $type, $size, $path, $userID]);
$this->db->cache_delete('admin', 'files');
} }
public function uploadFile($original_name, $tmpname, $size, $type, $userContent = true) public function uploadFile($original_name, $tmpname, $size, $type, $userContent = true)
@ -28,20 +44,51 @@ class FileModel extends CI_Model
$target_file = str_replace('\\', '/', $target_file); $target_file = str_replace('\\', '/', $target_file);
$this->db->query('INSERT INTO files (name, original_name, type, size, path, isUserData) VALUES (?, ?, ?, ?, ?, ?)', [$name, $original_name, $type, $size, $target_file, $userContent]); $this->addToDatabase($name, $original_name, $type, $size, $target_file, $userContent);
$this->db->cache_delete('admin', 'files');
echo shell_exec('python /var/www/codeigniter/duplicates.py'); echo shell_exec('python /var/www/codeigniter/duplicates.py');
return "/f/" . $name; return "/f/" . $name;
} }
public function uploadImage($name, $max_size, $originalname, $max_width, $userContent = true) { public function uploadVideo($name, $max_size, $originalName, $max_width, $user = null) {
$config['upload_path'] = '.' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR . ($userContent ? 'userContent' . DIRECTORY_SEPARATOR : ''); $path = '.' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR;
if($user !== null) {
$path .= 'userContent' . DIRECTORY_SEPARATOR . $user . DIRECTORY_SEPARATOR;
}
$config['upload_path'] = $path;
if(!file_exists($path)) {
mkdir($path, 0777);
}
$config['allowed_types'] = 'mp4';
$config['max_size'] = $max_size;
$config['file_name'] = $this->generateName() . '.' . pathinfo(basename($originalName), PATHINFO_EXTENSION);
$this->load->library('upload', $config);
if(!$this->upload->do_upload($name)) {
return null;
} else {
$data = $this->upload->data();
$this->upload->display_errors();
$this->addToDatabase($data['raw_name'], $originalName, $data['file_type'], $data['file_size'] * 1024, $this->getPath($data['file_name'], $user), $user);
return '/f/' . $data['raw_name'];
}
}
public function uploadImage($name, $max_size, $originalName, $max_width, $user = null) {
$config['upload_path'] = '.' . DIRECTORY_SEPARATOR . 'files' . DIRECTORY_SEPARATOR;
if($user != null) {
$config['upload_path'] .= 'userContent' . DIRECTORY_SEPARATOR . $user . DIRECTORY_SEPARATOR;
}
$config['allowed_types'] = 'gif|jpg|png'; $config['allowed_types'] = 'gif|jpg|png';
$config['max_size'] = $max_size; $config['max_size'] = $max_size;
$config['file_name'] = $this->generateName() . "." . pathinfo(basename($originalname), PATHINFO_EXTENSION); $config['file_name'] = $this->generateName() . "." . pathinfo(basename($originalName), PATHINFO_EXTENSION);
$this->load->library('upload', $config); $this->load->library('upload', $config);
@ -60,9 +107,7 @@ class FileModel extends CI_Model
$this->image_lib->resize(); $this->image_lib->resize();
$this->db->query('INSERT INTO files (name, original_name, type, size, path, isUserData) VALUES (?, ?, ?, ?, ?, ?)', [$data['raw_name'], $originalname, $data['file_type'], $data['file_size'] * 1024, $this->getPath($data['file_name'], $userContent), $userContent]); $this->addToDatabase($data['raw_name'], $originalName, $data['file_type'], $data['file_size'] * 1024, $this->getPath($data['file_name'], $user), $user);
$this->db->cache_delete('admin', 'files');
echo shell_exec('python /var/www/codeigniter/duplicates.py'); echo shell_exec('python /var/www/codeigniter/duplicates.py');
@ -164,6 +209,16 @@ class FileModel extends CI_Model
return $result; return $result;
} }
public function getFileID($name, $userID = null) {
$result = $this->db->query('SELECT ID FROM files WHERE name = ? AND user = ?', [$name, $userID])->result_array();
return $result;
}
public function getFilePath($name, $userID = null) {
$result = $this->db->query('SELECT path FROM files WHERE name = ? AND user = ?', [$name, $userID])->result_array();
return !empty($result) ? $result[0]['path'] : null;
}
public function delete($id) { public function delete($id) {
$filePath = $this->db->query('SELECT path FROM files WHERE ID = ? LIMIT 1', [$id])->result_array()[0]; $filePath = $this->db->query('SELECT path FROM files WHERE ID = ? LIMIT 1', [$id])->result_array()[0];
unlink($filePath['path']); unlink($filePath['path']);

View File

@ -48,8 +48,8 @@
$this->db->query('DELETE FROM user_posts_media WHERE postID = ?', [$postID]); $this->db->query('DELETE FROM user_posts_media WHERE postID = ?', [$postID]);
} }
public function addImageToPost($postID, $imageUrl) { public function addMediaToPost($postID, $type, $fileID) {
$this->db->query('INSERT INTO user_posts_media (postID, mediaType, mediaUrl) VALUES (?, ?, ?)', [$postID, 'image', $imageUrl]); $this->db->query('INSERT INTO user_posts_media (postID, mediaType, fileID) VALUES (?, ?, ?)', [$postID, $type, $fileID]);
} }
public function preparePostContent($content) public function preparePostContent($content)
@ -149,7 +149,7 @@
} }
public function getPostMedia($postID) { public function getPostMedia($postID) {
$result = $this->db->query('SELECT * FROM user_posts_media WHERE postID = ?', [$postID])->result_array(); $result = $this->db->query('SELECT m.mediaType type, f.name name FROM user_posts_media m LEFT JOIN files f ON f.ID = m.fileID WHERE postID = ?', [$postID])->result_array();
return $result; return $result;
} }

View File

@ -110,7 +110,8 @@
'lib/jquery.PageScroll2id.min.js', 'lib/jquery.PageScroll2id.min.js',
'lib/jquery.mobile.custom.min.js', 'lib/jquery.mobile.custom.min.js',
'post-create.js', 'post-create.js',
'post-item.js' 'post-item.js',
'video-controls.js',
]; ];
if (isset($additionalScripts)) { if (isset($additionalScripts)) {
$scripts = array_merge($scripts, $additionalScripts); $scripts = array_merge($scripts, $additionalScripts);

View File

@ -35,11 +35,46 @@
<?php if (!empty($media)): ?> <?php if (!empty($media)): ?>
<div class="post-media-list row"> <div class="post-media-list row">
<?php foreach ($media as $item): ?> <?php foreach ($media as $item) {
<div class="col"> $url = '/f/' . $item['name'];
<div class="post-media" data-full-image="<?= $item['mediaUrl'] ?>" style="background-image: url(<?= $item['mediaUrl'] ?>?w=500"></div> switch ($item['type']) {
</div> case 'image':
<?php endforeach; ?> ?>
<div class="col">
<div class="post-media post-image" data-full-image="<?= $url ?>" style="background-image: url('<?= $url ?>?w=500')"></div>
</div>
<?php
break;
case 'video':
?>
<div class="col">
<div class="video-container">
<video class="video" src="<?= $url ?>" muted></video>
<div class="video-controls">
<button type="button" class="video-control-btn video-toggle-play">
<i class="fa fa-play"></i>
</button>
<div class="video-volume-container">
<button type="button" class="video-control-btn video-mute">
<i class="fa fa-volume-muted"></i>
</button>
<input type="range" class="video-volume" min="0" max="1" step="0.1" value="1">
</div>
<output class="video-time">0:00</output>
<input type="range" class="video-seek-bar" value="0">
<output class="video-length">0:00</output>
<button type="button" class="video-control-btn video-fullscreen">
<i class="fa fa-expand"></i>
</button>
</div>
</div>
</div>
<?php
break;
case 'audio':
break;
}
} ?>
</div> </div>
<?php endif; ?> <?php endif; ?>
</div> </div>

View File

@ -30,8 +30,6 @@ $('#contentField').on('keyup', function (e) {
return `<span class="hashtag">${match}</span>`; return `<span class="hashtag">${match}</span>`;
}); });
console.log(html);
if (!/&nbsp;$/.test($(this).html())) { if (!/&nbsp;$/.test($(this).html())) {
filter += '&nbsp;'; filter += '&nbsp;';
} }
@ -102,7 +100,7 @@ function set_range(start, end, element) {
$.fn.selectRange = function (start, end) { $.fn.selectRange = function (start, end) {
var e = document.getElementById($(this).attr('id')); var e = document.getElementById($(this).attr('id'));
if (!e) return; if (!e)
else if (e.setSelectionRange) { else if (e.setSelectionRange) {
e.focus(); e.focus();
e.setSelectionRange(start, end); e.setSelectionRange(start, end);
@ -120,12 +118,12 @@ $.fn.selectRange = function (start, end) {
} }
}; };
let postMedia = {}; let postMedia = [];
function publishPost() { function publishPost() {
let isFilled = true; let isFilled = true;
let content = $('#contentField').text(); let content = $('#contentField').text();
console.log(content); if (postMedia.length === 0 && content === "") {
if (content === "") {
$('#postModal #content').addClass('has-error'); $('#postModal #content').addClass('has-error');
isFilled = false; isFilled = false;
} else { } else {
@ -135,46 +133,231 @@ function publishPost() {
if (isFilled) { if (isFilled) {
const replyTo = $('#postModal #replyTo').val(); const replyTo = $('#postModal #replyTo').val();
submitPost(content, replyTo); submitPost(content, replyTo);
} else {
addSnackbar('primary', 'Wir haben leider noch nicht erlernt, wie man leere Posts veröffentlicht.');
} }
} }
$('#postFiles').on('change', function() { let uploadingFiles = [];
console.log(this.files);
const match = ['image/jpeg', 'image/jpg', 'image/png'];
const mediaCount = Object.keys(postMedia).length;
if(mediaCount < 4) {
for (let i = 0; i < this.files.length && i < 4 - mediaCount; i++) {
const file = this.files[i];
if (match.indexOf(file.type) === -1)
continue;
const reader = new FileReader(); (function () {
reader.addEventListener('load', () => { // file drag hover
$('.post-images').append(`<div class="post-image" style="background-image: url(${reader.result})"></div>`); function fileDragHover(e) {
postMedia[mediaCount + i] = { e.stopPropagation();
image: reader.result, e.preventDefault();
type: file.type, e.target.className = (e.type == "dragover" ? "hover" : "");
size: file.size, }
name: file.name
}; // file selection
}); function fileSelectHandler(e) {
reader.readAsDataURL(file);
// cancel event and hover styling
fileDragHover(e);
// fetch FileList object
const files = e.target.files || e.dataTransfer.files;
// process all File objects
let i = 0;
for (let f of files) {
const generalType = f.type.split('/')[0];
if (postMedia.length + i > 4 || postMedia.find(media => media.type !== 'image' || media.type !== generalType)) {
addSnackbar('warning', 'Du kannst maximal vier Bilder zu einem Post hinzufügen.');
continue;
}
parseFile(f);
uploadFile(f);
i++;
} }
} }
if(Object.keys(postMedia).length >= 4) {
$('.postImageUpload').hide();
}
});
$('#postModal').on('hidden.bs.modal', () => { // output file information
$('#postModal #replyTo').val(-1); function parseFile(file) {
}); $('#postModalPublish').addClass('disabled').attr('disabled', true);
uploadingFiles.push(file);
const thumbnailEl = $('<div class="post-image"></div>');
$('.post-images').append(thumbnailEl);
switch (file.type.split('/')[0]) {
case 'image':
const reader = new FileReader();
reader.addEventListener('load', () => {
thumbnailEl.css('background-image', `url(${reader.result})`);
});
break;
if (postMedia.length >= 4)
$('.postImageUpload').hide();
case 'video':
const video = document.createElement('video');
video.src = URL.createObjectURL(file);
video.addEventListener('loadeddata', () => {
const width = video.videoWidth;
const height = video.videoHeight;
const canvas = document.createElement('canvas');
canvas.width = width;
canvas.height = height;
canvas.getContext('2d').drawImage(video, 0, 0, width, height);
thumbnailEl.css('background-image', `url(${canvas.toDataURL()})`);
});
$('.postImageUpload').hide();
break;
case 'audio':
break;
}
}
// upload JPEG files
function uploadFile(file) {
var xhr = new XMLHttpRequest();
const allowedTypes = ['image/jpg', 'image/jpeg', 'image/gif', 'image/png', 'video/mp4'];
if (xhr.upload && allowedTypes.includes(file.type) && file.size <= 100000000) {
const formData = new FormData();
formData.append('postMedia', file);
$.ajax({
url: '/user/uploadPostMedia',
method: 'POST',
data: formData,
processData: false,
contentType: false,
success: (data) => {
postMedia.push({
type: data.type,
path: data.path,
});
uploadingFiles.splice(uploadingFiles.indexOf(file), 1);
if(uploadingFiles.length === 0) {
$('#postModalPublish').removeClass('disabled').attr('disabled', false);
}
},
});
}
}
// initialize
function init() {
var fileselect = $('#postFiles')[0],
filedrag = $('#postFiles')[0];
// submitbutton = $id("submitbutton");
if (!fileselect)
return;
// file select
fileselect.addEventListener("change", fileSelectHandler, false);
// is XHR2 available?
var xhr = new XMLHttpRequest();
if (xhr.upload) {
// file drop
filedrag.addEventListener("dragover", fileDragHover, false);
filedrag.addEventListener("dragleave", fileDragHover, false);
filedrag.addEventListener("drop", fileSelectHandler, false);
filedrag.style.display = "block";
}
}
// call initialization file
if (window.File && window.FileList && window.FileReader) {
init();
}
})();
$('#postModal')
.on('hide.bs.modal', function (e) {
if (!this.forceQuit && (postMedia.length > 0 || $('#contentField').text().trim().length > 0)) {
e.preventDefault();
let allowClosing = false;
const confirmModal = $(`
<div class="modal fade" role="dialog">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Post verwerfen?</h4>
</div>
<div class="modal-footer">
<button class="btn btn-sm btn-outline btn-red dismiss" type="button" data-dismiss="modal">Ja, Post verwerfen</button>
<button class="btn btn-sm btn-primary continue" type="submit" data-dismiss="modal">Nein, Post behalten</button>
</div>
</div>
</div>
</div>
`);
confirmModal.modal('show');
$('.dismiss', confirmModal).click(() => {
allowClosing = true;
this.forceQuit = true;
$(this).modal('hide');
});
$('.continue', confirmModal).click(() => {
allowClosing = true;
});
confirmModal
.on('hide.bs.modal', function (e) {
if (!allowClosing)
e.preventDefault();
})
.on('hidden.bs.modal', function () {
$(this).remove();
});
} else {
this.forceQuit = false;
}
})
.on('hidden.bs.modal', () => {
$('#postModal #replyTo').val(-1);
if(postMedia.length > 0) {
postMedia.forEach(media => {
$.ajax({
url: '/user/deletePostMedia',
method: 'POST',
data: {
path: media.path
}
});
});
}
resetPostForm();
$('#postModalBody > *:not(#postForm)').remove();
$('#postForm').show();
$('#postModal .modal-footer').show();
});
function resetPostForm() {
uploadingFiles = [];
postMedia = [];
$('.post-images').empty();
$('.postImageUpload').show();
$('#contentField').text('');
}
function submitPost(content, replyTo) { function submitPost(content, replyTo) {
if(postMedia.length > 4) { if (postMedia.length > 4) {
return; return;
} }
const body = $('#postModalBody');
$.ajax({ $.ajax({
url: "/user/publishPost", url: "/user/publishPost",
method: 'POST', method: 'POST',
@ -184,14 +367,15 @@ function submitPost(content, replyTo) {
postMedia postMedia
}, },
beforeSend: function () { beforeSend: function () {
$('#postModalBody').empty().append("<i class='fa fa-cog fa-spin fa-5x'></i>"); body.children().hide().parent().append('<div class="loadingSpinner"></div>');
$('#postModalPublish').button('loading'); $('#postModal .modal-footer').hide();
resetPostForm();
}, },
success: function (data) { success: function (data) {
$('#postModalBody').empty().append(data); $('.loadingSpinner', body).remove();
body.append(data);
}, },
error: function (data) { error: function (data) {
console.log(data);
} }
}); });
} }

View File

@ -68,7 +68,6 @@ function registerPostEvents() {
$('.action-btn.reply-button').click((e) => { $('.action-btn.reply-button').click((e) => {
e.preventDefault(); e.preventDefault();
const target = $(e.currentTarget); const target = $(e.currentTarget);
console.log(target, $('.postFullviewModal'));
$('.postFullviewModal').modal('hide'); $('.postFullviewModal').modal('hide');
$('#postModal #replyTo').val(target.data('uuid')); $('#postModal #replyTo').val(target.data('uuid'));
$('#postModal').modal('show'); $('#postModal').modal('show');
@ -82,7 +81,7 @@ function registerPostEvents() {
$('.post-item').click(function (e) { $('.post-item').click(function (e) {
const target = e.target; const target = e.target;
if(target.tagName !== 'A' && target.tagName !== 'IMG' && target.tagName !== 'I' && !target.classList.contains('post-media')) { if(target.tagName !== 'BUTTON' && target.tagName !== 'INPUT' && target.tagName !== 'A' && target.tagName !== 'IMG' && target.tagName !== 'I' && !target.classList.contains('post-media')) {
e.preventDefault(); e.preventDefault();
const uuid = $(this).data('uuid'); const uuid = $(this).data('uuid');
const username = $(this).data('username'); const username = $(this).data('username');
@ -94,6 +93,23 @@ function registerPostEvents() {
$('.post-media').click(function () { $('.post-media').click(function () {
showFullscreenImage($(this).data('full-image')); showFullscreenImage($(this).data('full-image'));
}); });
addVideoListeners();
$(window).scroll(() => {
const pageOffsetTop = $(window).scrollTop();
const pageOffsetBottom = pageOffsetTop + $(window).height();
$('.post-media.post-video').each(function () {
const elemTop = $(this).offset().top;
const elemBottom = elemTop + $(this).height();
if(elemBottom <= pageOffsetBottom || elemTop >= pageOffsetTop) {
$(this)[0].play();
} else {
$(this)[0].pause();
}
});
});
} }
registerPostEvents(); registerPostEvents();
@ -101,7 +117,6 @@ const pendingRequests = [];
function addPostLike(el) { function addPostLike(el) {
const uuid = el.data('uuid'); const uuid = el.data('uuid');
console.log(el, uuid);
if(pendingRequests.indexOf(uuid) !== -1) if(pendingRequests.indexOf(uuid) !== -1)
return; return;
@ -115,7 +130,6 @@ function addPostLike(el) {
postUUID: uuid postUUID: uuid
}, },
success: (result) => { success: (result) => {
console.log(result);
if(result.success) { if(result.success) {
text.text(result.likeCount); text.text(result.likeCount);
if(result.isLiked) { if(result.isLiked) {
@ -150,7 +164,6 @@ function addPostLike(el) {
icon.toggleClass('far').toggleClass('fas'); icon.toggleClass('far').toggleClass('fas');
icon.parent().toggleClass('active'); icon.parent().toggleClass('active');
}, },
error: console.log
}); });
} }
@ -225,7 +238,6 @@ function submitReportForm(postUuid, reportReason, reportText) {
setTimeout(() => { setTimeout(() => {
$('#postReportBody').find('.fa').fadeOut(); $('#postReportBody').find('.fa').fadeOut();
}, 500); }, 500);
console.log(data);
if(data.success) { if(data.success) {
$('#postReportBody').append(`<div class="alert alert-success" role="alert" style="display: none;">${data.message}</div>`); $('#postReportBody').append(`<div class="alert alert-success" role="alert" style="display: none;">${data.message}</div>`);
} else { } else {
@ -311,4 +323,7 @@ function deletePost(uuid) {
}, 2000); }, 2000);
} }
}) })
}
function addScrollListener() {
} }

114
assets/js/video-controls.js Normal file
View File

@ -0,0 +1,114 @@
function getVideo(el) {
return $(el).parent().prev('.video')[0];
}
function updateMuteBtn(video) {
const muteBtn = $(video).next('.video-controls').find('.video-mute i.fa');
muteBtn.removeClass('fa-volume-up fa-volume-down fa-volume-mute');
if (video.muted) {
muteBtn.addClass('fa-volume-mute');
} else {
if (video.volume > .5) {
muteBtn.addClass('fa-volume-up');
} else {
muteBtn.addClass('fa-volume-down');
}
}
}
function formatTime(time) {
const minutes = Math.floor(time / 60);
let seconds = Math.round(time) % 60;
if(seconds < 10)
seconds = "0" + seconds;
return `${minutes}:${seconds}`
}
function addVideoListeners() {
$('.video-controls .video-toggle-play').click(function () {
getVideo(this).toggle();
});
$('.video-controls .video-mute').click(function () {
const video = getVideo(this);
video.toggleMuted();
updateMuteBtn(video);
});
$('.video-controls .video-volume').change(function () {
const video = getVideo(this);
video.volume = $(this).val();
if (video.volume > 0)
video.muted = false;
updateMuteBtn(video);
});
$('.video-seek-bar')
.on('mousedown', function () {
getVideo(this).pause();
})
.on('mouseup', function () {
getVideo(this).play();
})
.on('change', function () {
const video = getVideo(this);
video.currentTime = video.duration * (this.value / 100);
});
$('.video-fullscreen').on('click', function () {
const video = getVideo(this);
if(video.requestFullscreen) {
video.requestFullscreen();
} else if(video.mozRequestFullScreen) {
video.mozRequestFullScreen();
} else if(video.webkitRequestFullScreen) {
video.webkitRequestFullScreen();
}
});
$('.video')
.on('loadeddata', function () {
const duration = formatTime(this.duration);
$(this).next('.video-controls').find('.video-length').text(duration);
})
.on('play pause', function () {
const togglePlay = $(this).next('.video-controls').find('.video-toggle-play').find('i.fa');
if (this.paused) {
togglePlay.removeClass('fa-pause').addClass('fa-play');
} else {
togglePlay.removeClass('fa-play').addClass('fa-pause');
}
})
.on('timeupdate', function () {
const value = (100 / this.duration) * this.currentTime;
$(this).next('.video-controls').find('.video-seek-bar').val(value)
.prev('.video-time').text(formatTime(this.currentTime));
})
.on('click', function () {
if(!this.startedManually) {
this.play();
this.muted = false;
updateMuteBtn(this);
this.startedManually = true;
} else {
this.toggle();
}
});
}
Node.prototype.toggle = function () {
if (this.paused)
this.play();
else
this.pause();
};
Node.prototype.toggleMuted = function () {
this.muted = !this.muted;
};