Completed partial content implementation

videojs layout fixes
Added translations
This commit is contained in:
Sergio Brighenti 2019-01-30 23:19:33 +01:00
parent edd9895684
commit c60e3d059e
8 changed files with 62 additions and 63 deletions

View file

@ -1,7 +1,8 @@
## v2.5 ## v2.5
+ Updated project license to <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU AGPLv3</a>. + Updated project license to <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU AGPLv3</a>.
+ Added self update feature. + Added self update feature.
+ Working on partial content implementation (streaming seek con chromium based browsers). + Added partial content implementation (stream seeking on chromium based browsers).
+ Improved video.js alignment with large videos.
## v2.4.1 ## v2.4.1
+ Fixed error message when the file is too large. (#15) + Fixed error message when the file is too large. (#15)

View file

@ -159,11 +159,16 @@ location / {
<img src="https://i.imgur.com/2ZRd27y.png" width="400" title="Public image upload view"> <img src="https://i.imgur.com/2ZRd27y.png" width="400" title="Public image upload view">
</p> </p>
## License
This software is licensed under the <a href="https://choosealicense.com/licenses/agpl-3.0/">GNU Affero General Public License v3.0</a>, available in this repository.
As a "copyright notice" it is sufficient to keep the small footer at the bottom of the page, also to help other people to learn about this project!
## Built with ## Built with
+ Slim 3, since `v2.0` (https://www.slimframework.com/) + Slim 3, since `v2.0` (https://www.slimframework.com/) and some great PHP packages (Flysystem, Intervention Image, Twig, etc)
+ FlightPHP, up to `v1.x` (http://flightphp.com/) + FlightPHP, up to `v1.x` (http://flightphp.com/)
+ Bootstrap 4 (https://getbootstrap.com/) + Bootstrap 4 (https://getbootstrap.com/)
+ Font Awesome 5 (http://fontawesome.com) + Font Awesome 5 (http://fontawesome.com)
+ ClipboardJS (https://clipboardjs.com/) + ClipboardJS (https://clipboardjs.com/)
+ HighlightJS (https://highlightjs.org/) + HighlightJS (https://highlightjs.org/)
+ JQuery (https://jquery.com/) + JQuery (https://jquery.com/)
+ video.js (https://videojs.com/)

View file

@ -101,10 +101,10 @@ class UpgradeController extends Controller
$jsonResponse['status'] = 'OK'; $jsonResponse['status'] = 'OK';
if (version_compare($json[0]->tag_name, PLATFORM_VERSION, '>')) { if (version_compare($json[0]->tag_name, PLATFORM_VERSION, '>')) {
$jsonResponse['message'] = lang('new_version_available', $json[0]->tag_name); //"New version {$json[0]->tag_name} available!"; $jsonResponse['message'] = lang('new_version_available', $json[0]->tag_name);
$jsonResponse['upgrade'] = true; $jsonResponse['upgrade'] = true;
} else { } else {
$jsonResponse['message'] = lang('already_latest_version');//'You have already the latest version.'; $jsonResponse['message'] = lang('already_latest_version');
$jsonResponse['upgrade'] = false; $jsonResponse['upgrade'] = false;
} }
return $response->withJson($jsonResponse, 200); return $response->withJson($jsonResponse, 200);

View file

@ -107,13 +107,6 @@ class UploadController extends Controller
$type = explode('/', $media->mimetype)[0]; $type = explode('/', $media->mimetype)[0];
if ($type === 'text') { if ($type === 'text') {
$media->text = $filesystem->read($media->storage_path); $media->text = $filesystem->read($media->storage_path);
} else if (in_array($type, ['image', 'video'])) {
$url = urlFor("/$args[userCode]/$args[mediaCode]/raw");
$header = "<{$url}>; rel=preload; as={$type}";
if ($this->session->get('logged', false)) {
$header .= '; nopush';
}
$response = $response->withHeader('Link', $header);
} }
} catch (FileNotFoundException $e) { } catch (FileNotFoundException $e) {
@ -316,6 +309,7 @@ class UploadController extends Controller
*/ */
protected function streamMedia(Request $request, Response $response, Filesystem $storage, $media, string $disposition = 'inline'): Response protected function streamMedia(Request $request, Response $response, Filesystem $storage, $media, string $disposition = 'inline'): Response
{ {
set_time_limit(0);
$mime = $storage->getMimetype($media->storage_path); $mime = $storage->getMimetype($media->storage_path);
if ($request->getParam('width') !== null && explode('/', $mime)[0] === 'image') { if ($request->getParam('width') !== null && explode('/', $mime)[0] === 'image') {
@ -332,60 +326,63 @@ class UploadController extends Controller
->withHeader('Content-Disposition', $disposition . ';filename="scaled-' . pathinfo($media->filename)['filename'] . '.png"') ->withHeader('Content-Disposition', $disposition . ';filename="scaled-' . pathinfo($media->filename)['filename'] . '.png"')
->write($image); ->write($image);
} else { } else {
$stream = new Stream($storage->readStream($media->storage_path)); $stream = new Stream($storage->readStream($media->storage_path));
$start = 0;
$end = $stream->getSize(); if (!in_array(explode('/', $mime)[0], ['image', 'video', 'audio']) || $disposition === 'attachment') {
return $response->withHeader('Content-Type', $mime)
->withHeader('Content-Disposition', $disposition . '; filename="' . $media->filename . '"')
->withHeader('Content-Length', $stream->getSize())
->withBody($stream);
}
$end = $stream->getSize() - 1;
if ($request->getServerParam('HTTP_RANGE') !== null) { if ($request->getServerParam('HTTP_RANGE') !== null) {
list(, $range) = explode('=', $_SERVER['HTTP_RANGE'], 2); list(, $range) = explode('=', $request->getServerParam('HTTP_RANGE'), 2);
if (strpos($range, ',') !== false) { if (strpos($range, ',') !== false) {
return $response->withHeader('Content-Type', $mime) return $response->withHeader('Content-Type', $mime)
->withHeader('Content-Disposition', $disposition . '; filename="' . $media->filename . '"') ->withHeader('Content-Disposition', $disposition . '; filename="' . $media->filename . '"')
->withHeader('Content-Length', $storage->getSize($media->storage_path)) ->withHeader('Content-Length', $stream->getSize())
->withHeader('Accept-Ranges', 'bytes') ->withHeader('Accept-Ranges', 'bytes')
->withHeader('Content-Range', "0,{$stream->getSize()}") ->withHeader('Content-Range', "0,{$stream->getSize()}")
->withStatus(416) ->withStatus(416)
->withBody($stream); ->withBody($stream);
} }
if ($range == '-') { if ($range === '-') {
$start = $stream->getSize() - substr($range, 1); $start = $stream->getSize() - (int)substr($range, 1);
} else { } else {
$range = explode('-', $range); $range = explode('-', $range);
$start = $range[0]; $start = (int)$range[0];
$end = (isset($range[1]) && is_numeric($range[1])) ? $range[1] : $end; $end = (isset($range[1]) && is_numeric($range[1])) ? (int)$range[1] : $stream->getSize();
} }
$end = ($end > $stream->getSize() - 1) ? $stream->getSize() - 1 : $end; $end = ($end > $stream->getSize() - 1) ? $stream->getSize() - 1 : $end;
$stream->seek($start);
if ($start > $end || $start > $stream->getSize() - 1 || $end >= $stream->getSize()) { $buffer = 16384;
return $response->withHeader('Content-Type', $mime) $readed = $start;
->withHeader('Content-Disposition', $disposition . '; filename="' . $media->filename . '"') while ($readed < $end) {
->withHeader('Content-Length', $storage->getSize($media->storage_path)) if ($readed + $buffer > $end) {
->withHeader('Accept-Ranges', 'bytes') $buffer = $end - $readed + 1;
->withHeader('Content-Range', "0,{$stream->getSize()}") }
->withStatus(416) echo $stream->read($buffer);
->withBody($stream); $readed += $buffer;
} }
$stream->seek($start); return $response->withHeader('Content-Type', $mime)
->withHeader('Content-Length', $end - $start + 1)
->withHeader('Accept-Ranges', 'bytes')
->withHeader('Content-Range', "bytes $start-$end/{$stream->getSize()}")
->withStatus(206);
} }
$response->getBody()->write($stream->getContents());
return $response->withHeader('Content-Type', $mime) return $response->withHeader('Content-Type', $mime)
->withHeader('Content-Disposition', $disposition . '; filename="' . $media->filename . '"')
->withHeader('Content-Length', $stream->getSize()) ->withHeader('Content-Length', $stream->getSize())
->withHeader('Accept-Ranges', 'bytes') ->withHeader('Accept-Ranges', 'bytes')
->withHeader('Content-Range', "bytes $start-$end/{$stream->getSize()}") ->withStatus(200)
->withStatus(206); ->withBody($stream);
// return $response
// ->withHeader('Content-Type', $mime)
// ->withHeader('Content-Disposition', $disposition . '; filename="' . $media->filename . '"')
// ->withHeader('Content-Length', $storage->getSize($media->storage_path))
// ->withBody(new Stream($storage->readStream($media->storage_path)));
} }
} }
} }

View file

@ -1,32 +1,25 @@
<?php <?php
return [ return [
'lang' => 'English', 'lang' => 'English',
'yes' => 'Yes', 'yes' => 'Yes',
'no' => 'No', 'no' => 'No',
'send' => 'Send', 'send' => 'Send',
'no_media' => 'No media found.', 'no_media' => 'No media found.',
'login.username' => 'Username or E-Mail', 'login.username' => 'Username or E-Mail',
'password' => 'Password', 'password' => 'Password',
'login' => 'Login', 'login' => 'Login',
'username' => 'Username', 'username' => 'Username',
'home' => 'Home', 'home' => 'Home',
'users' => 'Users', 'users' => 'Users',
'system' => 'System', 'system' => 'System',
'profile' => 'Profile', 'profile' => 'Profile',
'logout' => 'Logout', 'logout' => 'Logout',
'pager.next' => 'Next', 'pager.next' => 'Next',
'pager.previous' => 'Previous', 'pager.previous' => 'Previous',
'copy_link' => 'Copy link', 'copy_link' => 'Copy link',
'public.telegram' => 'Share on Telegram', 'public.telegram' => 'Share on Telegram',
'public.delete_text' => 'Are you sure you want to delete this item? It will be gone forever!', 'public.delete_text' => 'Are you sure you want to delete this item? It will be gone forever!',
'preview' => 'Preview', 'preview' => 'Preview',
'filename' => 'Filename', 'filename' => 'Filename',
'size' => 'Size', 'size' => 'Size',
@ -38,7 +31,6 @@ return [
'delete' => 'Delete', 'delete' => 'Delete',
'publish' => 'Publish', 'publish' => 'Publish',
'hide' => 'Hide', 'hide' => 'Hide',
'files' => 'Files', 'files' => 'Files',
'orphaned_files' => 'Orphaned Files', 'orphaned_files' => 'Orphaned Files',
'theme' => 'Theme', 'theme' => 'Theme',
@ -47,7 +39,6 @@ return [
'save' => 'Save', 'save' => 'Save',
'used' => 'Used', 'used' => 'Used',
'system_info' => 'System Information', 'system_info' => 'System Information',
'user.create' => 'Create User', 'user.create' => 'Create User',
'user.edit' => 'Edit User', 'user.edit' => 'Edit User',
'is_active' => 'Is active', 'is_active' => 'Is active',
@ -66,7 +57,6 @@ return [
'open' => 'Open', 'open' => 'Open',
'confirm' => 'Confirmation', 'confirm' => 'Confirmation',
'confirm_string' => 'Are you sure?', 'confirm_string' => 'Are you sure?',
'installed' => 'Installation completed successfully!', 'installed' => 'Installation completed successfully!',
'bad_login' => 'Wrong credentials.', 'bad_login' => 'Wrong credentials.',
'account_disabled' => 'Your account is disabled.', 'account_disabled' => 'Your account is disabled.',
@ -95,4 +85,12 @@ return [
'name' => 'Name', 'name' => 'Name',
'maintenance' => 'Maintenance', 'maintenance' => 'Maintenance',
'clean_orphaned_uploads' => 'Clean Orphaned Uploads', 'clean_orphaned_uploads' => 'Clean Orphaned Uploads',
'path_not_writable' => 'The output path is not writable.',
'already_latest_version' => 'You already have the latest version.',
'new_version_available' => 'New version %s available!',
'cannot_retrieve_file' => 'Cannot retrieve the file.',
'file_size_no_match' => 'The downloaded file doesn\'t match the correct file size.',
'check_for_updates' => 'Check for updates',
'upgrade' => 'Upgrade',
'updates' => 'Updates',
]; ];

View file

@ -1,32 +1,25 @@
<?php <?php
return [ return [
'lang' => 'Italiano', 'lang' => 'Italiano',
'yes' => 'Sì', 'yes' => 'Sì',
'no' => 'No', 'no' => 'No',
'send' => 'Invia', 'send' => 'Invia',
'no_media' => 'Nessun media trovato.', 'no_media' => 'Nessun media trovato.',
'login.username' => 'Username o E-Mail', 'login.username' => 'Username o E-Mail',
'password' => 'Password', 'password' => 'Password',
'login' => 'Accedi', 'login' => 'Accedi',
'username' => 'Username', 'username' => 'Username',
'home' => 'Home', 'home' => 'Home',
'users' => 'Utenti', 'users' => 'Utenti',
'system' => 'Sistema', 'system' => 'Sistema',
'profile' => 'Profilo', 'profile' => 'Profilo',
'logout' => 'Esci', 'logout' => 'Esci',
'pager.next' => 'Avanti', 'pager.next' => 'Avanti',
'pager.previous' => 'Indietro', 'pager.previous' => 'Indietro',
'copy_link' => 'Copia link', 'copy_link' => 'Copia link',
'public.telegram' => 'Condividi su Telegram', 'public.telegram' => 'Condividi su Telegram',
'public.delete_text' => 'Sei sicuro di voler eliminare questo elemento? Andrà perso per sempre!', 'public.delete_text' => 'Sei sicuro di voler eliminare questo elemento? Andrà perso per sempre!',
'preview' => 'Anteprima', 'preview' => 'Anteprima',
'filename' => 'Nome file', 'filename' => 'Nome file',
'size' => 'Dimensione', 'size' => 'Dimensione',
@ -38,7 +31,6 @@ return [
'delete' => 'Elimina', 'delete' => 'Elimina',
'publish' => 'Pubblica', 'publish' => 'Pubblica',
'hide' => 'Nascondi', 'hide' => 'Nascondi',
'files' => 'File', 'files' => 'File',
'orphaned_files' => 'File orfani', 'orphaned_files' => 'File orfani',
'theme' => 'Tema', 'theme' => 'Tema',
@ -47,7 +39,6 @@ return [
'save' => 'Salva', 'save' => 'Salva',
'used' => 'Usato', 'used' => 'Usato',
'system_info' => 'Informazioni di Sistema', 'system_info' => 'Informazioni di Sistema',
'user.create' => 'Crea Utente', 'user.create' => 'Crea Utente',
'user.edit' => 'Modifica Utente', 'user.edit' => 'Modifica Utente',
'is_active' => 'Attivo', 'is_active' => 'Attivo',
@ -66,7 +57,6 @@ return [
'open' => 'Apri', 'open' => 'Apri',
'confirm' => 'Conferma', 'confirm' => 'Conferma',
'confirm_string' => 'Sei sicuro?', 'confirm_string' => 'Sei sicuro?',
'installed' => 'Installazione completata!', 'installed' => 'Installazione completata!',
'bad_login' => 'Credenziali errate.', 'bad_login' => 'Credenziali errate.',
'account_disabled' => 'Il tuo account è disattivato.', 'account_disabled' => 'Il tuo account è disattivato.',
@ -95,4 +85,12 @@ return [
'name' => 'Nome', 'name' => 'Nome',
'maintenance' => 'Manutenzione', 'maintenance' => 'Manutenzione',
'clean_orphaned_uploads' => 'Pulisci upload orfani', 'clean_orphaned_uploads' => 'Pulisci upload orfani',
'path_not_writable' => 'Il percorso di output non è scrivibile.',
'already_latest_version' => 'Hai già l\'ultima versione disponibile.',
'new_version_available' => 'Nuova versione disponibile: %s',
'cannot_retrieve_file' => 'Impossibile scaricare il file.',
'file_size_no_match' => 'La dimensione del file scaricato non è corretta.',
'check_for_updates' => 'Controllo aggiornamenti',
'upgrade' => 'Upgrade',
'updates' => 'Aggiornamenti',
]; ];

View file

@ -86,7 +86,7 @@
<div class="col"> <div class="col">
<form method="post" action="{{ route('system.upgrade') }}"> <form method="post" action="{{ route('system.upgrade') }}">
<button type="submit" id="doUpgradeButton" class="btn btn-block btn-outline-success"><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('update_now') }}</button> <button type="submit" id="doUpgradeButton" class="btn btn-block btn-outline-success" disabled><i class="fas fa-cloud-download-alt fa-fw"></i> {{ lang('upgrade') }}</button>
</form> </form>
</div> </div>
</div> </div>

View file

@ -61,14 +61,14 @@
</div> </div>
{% elseif media.mimetype starts with 'video' %} {% elseif media.mimetype starts with 'video' %}
<div class="media-player"> <div class="media-player">
<video id="player" class="video-js vjs-fluid vjs-big-play-centered" autoplay controls loop preload="auto" data-setup='{"responsive": true }'> <video id="player" class="video-js vjs-big-play-centered vjs-16-9" autoplay controls loop preload="auto" data-setup='{"responsive": true }'>
<source src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" type="{{ media.mimetype }}"> <source src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" type="{{ media.mimetype }}">
Your browser does not support HTML5 video. Your browser does not support HTML5 video.
</video> </video>
</div> </div>
{% elseif media.mimetype starts with 'audio' %} {% elseif media.mimetype starts with 'audio' %}
<div class="media-player"> <div class="media-player">
<audio id="player" class="video-js vjs-fluid vjs-big-play-centered" autoplay controls loop preload="auto" data-setup='{"responsive": true }'> <audio id="player" class="video-js vjs-big-play-centered vjs-16-9" autoplay controls loop preload="auto" data-setup='{"responsive": true }'>
<source src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" type="{{ media.mimetype }}"> <source src="{{ urlFor('/' ~ media.user_code ~ '/' ~ media.code ~ '.' ~ extension ~ '/raw') }}" type="{{ media.mimetype }}">
Your browser does not support HTML5 audio. Your browser does not support HTML5 audio.
</audio> </audio>