Merge pull request #903 from codenift/artwork-upload

Upload artwork using drag and drop or click to browse
This commit is contained in:
Kyle Robbertze 2019-11-05 22:30:31 +02:00 committed by GitHub
commit cb462d494f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 384 additions and 30 deletions

View file

@ -155,20 +155,8 @@ class FileDataHelper {
} else { } else {
$ext = 'jpg'; $ext = 'jpg';
} }
self::resizeGroup($file, $ext);
if (file_exists($file)) {
self::resizeImage($file, $file . '-32.jpg', $ext, 32, 100);
self::resizeImage($file, $file . '-64.jpg', $ext, 64, 100);
self::resizeImage($file, $file . '-128.jpg', $ext, 128, 100);
self::resizeImage($file, $file . '-256.jpg', $ext, 256, 100);
self::resizeImage($file, $file . '-512.jpg', $ext, 512, 100);
self::imgToDataURI($file . '-32.jpg', $file . '-32');
self::imgToDataURI($file . '-64.jpg', $file . '-64');
self::imgToDataURI($file . '-128.jpg', $file . '-128');
self::imgToDataURI($file . '-256.jpg', $file . '-256');
} else {
Logging::error("The file $file does not exist");
}
} else { } else {
$get_img = ''; $get_img = '';
} }
@ -231,26 +219,120 @@ class FileDataHelper {
} else { } else {
$ext = 'jpg'; $ext = 'jpg';
} }
self::resizeGroup($rfile, $ext);
if (file_exists($rfile)) {
self::resizeImage($rfile, $rfile . '-32.jpg', $ext, 32, 100);
self::resizeImage($rfile, $rfile . '-64.jpg', $ext, 64, 100);
self::resizeImage($rfile, $rfile . '-128.jpg', $ext, 128, 100);
self::resizeImage($rfile, $rfile . '-256.jpg', $ext, 256, 100);
self::resizeImage($rfile, $rfile . '-512.jpg', $ext, 512, 100);
self::imgToDataURI($rfile . '-32.jpg', $rfile . '-32');
self::imgToDataURI($rfile . '-64.jpg', $rfile . '-64');
self::imgToDataURI($rfile . '-128.jpg', $rfile . '-128');
self::imgToDataURI($rfile . '-256.jpg', $rfile . '-256');
} else {
Logging::error("The file $rfile does not exist");
}
} else { } else {
$get_img = ""; $get_img = "";
} }
return $get_img; return $get_img;
} }
/**
* Upload artwork
*
* @param string $trackid
* @param string $data
*
* @return string Path to artwork
*/
public static function setArtwork($trackid, $data)
{
$file = Application_Model_StoredFile::RecallById($trackid);
$md = $file->getMetadata();
$storDir = Application_Model_MusicDir::getStorDir();
$fp = $storDir->getDirectory();
$dbAudioPath = $md["MDATA_KEY_FILEPATH"];
$fullpath = $fp . $dbAudioPath;
if ($data == "0") {
$get_img = "";
self::removeArtwork($trackid, $data);
} else {
$base64 = @$data;
$mime = explode(';', $base64)[0];
$audioPath = dirname($fullpath);
$dbPath = dirname($dbAudioPath);
$path_parts = pathinfo($fullpath);
$file = $path_parts['filename'];
//Save Data URI
if (file_put_contents($audioPath . "/" . $file, $base64)) {
$get_img = $dbPath . "/" . $file;
} else {
Logging::error("Could not save Data URI");
}
$rfile = $audioPath . "/" . $file;
if ($mime == "data:image/png") {
$ext = 'png';
} elseif ($mime == "data:image/gif") {
$ext = 'gif';
} elseif ($mime == "data:image/bmp") {
$ext = 'bmp';
} else {
$ext = 'jpg';
}
self::resizeGroup($rfile, $ext);
}
return $get_img;
}
/**
*
* Deletes just the artwork
*/
public static function removeArtwork($trackid)
{
$file = Application_Model_StoredFile::RecallById($trackid);
$md = $file->getMetadata();
$storDir = Application_Model_MusicDir::getStorDir();
$fp = $storDir->getDirectory();
$dbAudioPath = $md["MDATA_KEY_ARTWORK"];
$fullpath = $fp . $dbAudioPath;
if (file_exists($fullpath)) {
foreach (glob("$fullpath*", GLOB_NOSORT) as $filename) {
unlink($filename);
}
} else {
throw new Exception("Could not locate file ".$filepath);
}
return "";
}
/**
* Resize artwork group
*
* @param string $file
* @param string $ext
*/
public static function resizeGroup($file, $ext)
{
if (file_exists($file)) {
self::resizeImage($file, $file . '-32.jpg', $ext, 32, 100);
self::resizeImage($file, $file . '-64.jpg', $ext, 64, 100);
self::resizeImage($file, $file . '-128.jpg', $ext, 128, 100);
self::resizeImage($file, $file . '-256.jpg', $ext, 256, 100);
self::resizeImage($file, $file . '-512.jpg', $ext, 512, 100);
self::imgToDataURI($file . '-32.jpg', $file . '-32');
self::imgToDataURI($file . '-64.jpg', $file . '-64');
self::imgToDataURI($file . '-128.jpg', $file . '-128');
self::imgToDataURI($file . '-256.jpg', $file . '-256');
} else {
Logging::error("The file $file does not exist");
}
}
/** /**
* Render image * Render image
* Used in API to render JPEG * Used in API to render JPEG

View file

@ -395,7 +395,16 @@ class LibraryController extends Zend_Controller_Action
//on edit, if no artwork is set and audiofile has image, automatically add it //on edit, if no artwork is set and audiofile has image, automatically add it
if ($j["name"] == "artwork") { if ($j["name"] == "artwork") {
if ($j["value"] == null || $j["value"] == ''){ if ($j["value"] == null || $j["value"] == ''){
$serialized["artwork"] = FileDataHelper::resetArtwork($file_id); $serialized["artwork"] = FileDataHelper::resetArtwork($file_id);
}
} elseif ($j["name"] == "set_artwork") {
if ($j["value"] != null || $j["value"] != ''){
$serialized["artwork"] = FileDataHelper::setArtwork($file_id, $j["value"] );
}
} elseif ($j["name"] == "remove_artwork") {
if ($j["value"] == 1){
$remove_artwork = true;
$serialized["artwork"] = FileDataHelper::removeArtwork($file_id);
} }
} else { } else {
$serialized[$j["name"]] = $j["value"]; $serialized[$j["name"]] = $j["value"];

View file

@ -20,15 +20,32 @@ class Application_Form_EditAudioMD extends Zend_Form
// Add artwork hidden field // Add artwork hidden field
$artwork = new Zend_Form_Element_Hidden('artwork'); $artwork = new Zend_Form_Element_Hidden('artwork');
$artwork->class = 'input_text artwork_'. $p_id;
$artwork->setFilters(array('StringTrim')) $artwork->setFilters(array('StringTrim'))
->setValidators(array( ->setValidators(array(
new Zend_Validate_StringLength(array('max' => 512)) new Zend_Validate_StringLength(array('max' => 2048))
)); ));
$file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none')); $file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none'));
$file_id->removeDecorator('Label'); $file_id->removeDecorator('Label');
$file_id->setAttrib('class', 'artwork'); $file_id->setAttrib('class', 'artwork');
$this->addElement($artwork); $this->addElement($artwork);
// Set artwork hidden field
$set_artwork = new Zend_Form_Element_Hidden('set_artwork');
$set_artwork->class = 'input_text set_artwork_'. $p_id;
$file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none'));
$file_id->removeDecorator('Label');
$file_id->setAttrib('class', 'set_artwork');
$this->addElement($set_artwork);
// Remove artwork hidden field
$remove_artwork = new Zend_Form_Element_Hidden('remove_artwork');
$remove_artwork->class = 'input_text remove_artwork_'. $p_id;
$file_id->addDecorator('HtmlTag', array('tag' => 'div', 'style' => 'display:none'));
$file_id->removeDecorator('Label');
$file_id->setAttrib('class', 'remove_artwork');
$this->addElement($remove_artwork);
// Add title field // Add title field
$track_title = new Zend_Form_Element_Text('track_title'); $track_title = new Zend_Form_Element_Text('track_title');
$track_title->class = 'input_text'; $track_title->class = 'input_text';

View file

@ -19,7 +19,19 @@
</div> </div>
</div> </div>
<div class="track-edit-left"> <div class="track-edit-left">
<?php echo '<img width="140" height="140" src="' . $get_artwork .'">'; ?> <div class="artwork-upload" data-id="<?php echo($this->id); ?>">
<div class="artwork-edit">
<input type='file' class="artworkUpload artwork-uploaded-<?php echo($this->id); ?>" id="artworkUpload" data-id="<?php echo($this->id); ?>" accept=".png, .jpg, .jpeg" />
<label for="artworkUpload"></label>
</div>
<div id="artwork-preview" class="artwork-preview">
<div class="artwork-preview-<?php echo($this->id); ?>" id="artworkPreview" style="background-image: url(<?php echo $get_artwork; ?>);">
</div>
</div>
</div>
<div>
<a href="#" class="delete-artwork" data-id="<?php echo($this->id); ?>" style="font-size: 11px;">Remove</a>
</div>
</div> </div>
</div> </div>
<div style="height: 160px;"></div> <div style="height: 160px;"></div>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 66 KiB

Before After
Before After

View file

@ -4284,3 +4284,64 @@ li .ui-state-hover {
.track-edit-right { .track-edit-right {
margin-left: 160px; margin-left: 160px;
} }
/* Artwork Upload in Tracks Edit */
.artwork-upload {
position: relative;
max-width: 205px;
}
.artwork-upload .artwork-edit {
position: absolute;
z-index: 1;
top: 0;
}
.artwork-upload .artwork-edit input {
display: none;
}
.artwork-upload .artwork-edit input + label {
display: inline-block;
width: 140px;
height: 140px;
margin: 1px;
border-radius: 1px;
border: 1px solid transparent;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.12);
cursor: pointer;
font-weight: normal;
transition: all 0.2s ease-in-out;
}
.artwork-upload .artwork-edit input + label:hover {
background: rgba(0, 0, 0, 0.40);
border-color: #d6d6d6;
}
.artwork-upload .artwork-edit input + label:after {
color: #757575;
position: absolute;
top: 10px;
left: 0;
right: 0;
text-align: center;
margin: auto;
}
.artwork-upload .artwork-preview {
width: 140px;
height: 140px;
position: relative;
border-radius: 1px;
border: 2px solid #F8F8F8;
box-shadow: 0px 2px 4px 0px rgba(0, 0, 0, 0.1);
}
.artwork-upload .artwork-preview > div {
width: 100%;
height: 100%;
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
/* Drag and Drop Artwork */
body.droppable .artwork-upload .artwork-preview {
border: 2px dashed lightblue;
z-index: 9999;
}

View file

@ -1601,6 +1601,70 @@ var validationTypes = {
}; };
function readArtworkURL(input, id) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('.artwork-preview-'+id).css('background-image', 'url('+e.target.result +')');
$('.artwork-preview-'+id).hide();
$('.artwork-preview-'+id).fadeIn(500);
$('.set_artwork_'+id).val(function() {
return e.target.result;
});
}
reader.readAsDataURL(input.files[0]);
}
}
// Resample Artwork
var resampleImg = (function (canvas) {
function resampleImg(img, width, height, onresample) {
var load = typeof img == "string",
i = load || img;
if (load) {
i = new Image;
i.onload = onload;
i.onerror = onerror;
}
i._onresample = onresample;
i._width = width;
i._height = height;
load ? (i.src = img) : onload.call(img);
}
function onerror() {
throw ("not found: " + this.src);
}
function onload() {
var img = this,
width = img._width,
height = img._height,
onresample = img._onresample;
var minValue = Math.min(img.height, img.width);
width == null && (width = round(img.width * height / img.height));
height == null && (height = round(img.height * width / img.width));
delete img._onresample;
delete img._width;
delete img._height;
canvas.width = width;
canvas.height = height;
context.drawImage(img,0,0,minValue,minValue,0,0,width,height);
onresample(canvas.toDataURL("image/jpeg"));
}
var context = canvas.getContext("2d"),
round = Math.round;
return resampleImg;
}(this.document.createElement("canvas")));
$(document).ready(function() { $(document).ready(function() {
if (window.location.href.indexOf("showbuilder") > -1) { if (window.location.href.indexOf("showbuilder") > -1) {
AIRTIME.library.initPodcastDatatable(); AIRTIME.library.initPodcastDatatable();
@ -1613,5 +1677,114 @@ $(document).ready(function() {
$(window).resize(function() { $(window).resize(function() {
resizeAdvancedSearch(); resizeAdvancedSearch();
}); });
});
// delete artwork
$(document).on('click', '.delete-artwork', function(event) {
event.preventDefault();
event.stopPropagation();
var id = $(this).attr('data-id');
$('.artwork-preview-'+id).css('background-image', 'url('+ baseUrl +'css/images/no-cover.jpg)');
$('.artwork-preview-'+id).hide();
$('.artwork-preview-'+id).fadeIn(500);
$('.artwork_'+id).val(function() {
return "";
});
$('.set_artwork_'+id).val(function() {
return "";
});
$('.remove_artwork_'+id).val(function() {
return 1;
});
});
// image upload by clicking on the artwork container
$(document).on('change', '.artworkUpload', 'input', function(event) {
event.preventDefault();
event.stopPropagation();
var id = $(this).attr('data-id');
readArtworkURL(this, id);
});
// image upload by dragging onto the artwork container
$.event.props.push('dataTransfer');
(function() {
var s;
var Artwork = {
settings: {
body: $("body")
},
init: function() {
s = Artwork.settings;
Artwork.bindUIActions();
},
bindUIActions: function() {
var timer;
s.body.on('dragover', '.artwork-upload', function(event) {
event.preventDefault();
event.stopPropagation();
clearTimeout(timer);
Artwork.showDroppableArea();
return false;
});
s.body.on('dragleave', '.artwork-upload', function(event) {
event.preventDefault();
event.stopPropagation();
timer = setTimeout(function() {
Artwork.hideDroppableArea();
}, 200);
});
s.body.on('drop', '.artwork-upload', function(event) {
event.preventDefault();
event.stopPropagation();
var id = $(this).attr('data-id');
Artwork.handleDrop(event.dataTransfer.files, id);
});
},
showDroppableArea: function() {
s.body.addClass("droppable");
},
hideDroppableArea: function() {
s.body.removeClass("droppable");
},
handleDrop: function(files, id) {
Artwork.hideDroppableArea();
var file = files[0];
if (typeof file !== 'undefined' && file.type.match('image.*')) {
Artwork.resizeImage(file, 512, function(data) {
Artwork.placeImage(data, id);
});
} else {
alert("The file is not an image.");
}
},
resizeImage: function(file, size, callback) {
var fileTracker = new FileReader;
fileTracker.onload = function() {
resampleImg(this.result, size, size, callback);
}
fileTracker.readAsDataURL(file);
fileTracker.onabort = function() {
alert("Upload aborted!");
}
fileTracker.onerror = function() {
alert("File could not be read.");
}
},
placeImage: function(data, id) {
$('.artwork-preview-'+id).css('background-image', 'url('+ data +')');
$('.artwork-preview-'+id).hide();
$('.artwork-preview-'+id).fadeIn(500);
$('.set_artwork_'+id).val(function() {
return data;
});
}
}
Artwork.init();
})();
});