Merge branch 'contact_thumbnails' of git://gitorious.org/~tanghus/owncloud/tanghus-owncloud

This commit is contained in:
Bart Visscher 2011-12-29 00:21:34 +01:00
commit ed2ba4e8e4
7 changed files with 484 additions and 0 deletions

View File

@ -1,3 +1,4 @@
#contacts li { padding-left:25px;background:url('../img/person.svg') no-repeat; }
#chooseaddressbook {margin-right: 170px; float: right;}
#contacts_details_name { font-weight:bold;font-size:1.1em;margin-left:25%;}
#contacts_details_photo { margin:.5em 0em .5em 25%; }

Binary file not shown.

After

Width:  |  Height:  |  Size: 978 B

View File

@ -0,0 +1,175 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.0"
width="22"
height="22"
id="svg11300">
<defs
id="defs3">
<linearGradient
id="linearGradient3785">
<stop
id="stop3787"
style="stop-color:#b8b8b8;stop-opacity:1"
offset="0" />
<stop
id="stop3789"
style="stop-color:#878787;stop-opacity:1"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient6954">
<stop
id="stop6960"
style="stop-color:#f5f5f5;stop-opacity:1"
offset="0" />
<stop
id="stop6962"
style="stop-color:#d2d2d2;stop-opacity:1"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient3341">
<stop
id="stop3343"
style="stop-color:#ffffff;stop-opacity:1"
offset="0" />
<stop
id="stop3345"
style="stop-color:#ffffff;stop-opacity:0"
offset="1" />
</linearGradient>
<linearGradient
id="linearGradient5060">
<stop
id="stop5062"
style="stop-color:#000000;stop-opacity:1"
offset="0" />
<stop
id="stop5064"
style="stop-color:#000000;stop-opacity:0"
offset="1" />
</linearGradient>
<radialGradient
cx="24.999998"
cy="28.659998"
r="16"
fx="24.999998"
fy="28.659998"
id="radialGradient2871"
xlink:href="#linearGradient6954"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.67742373,0,0,0.19285627,-5.0162555,9.9977318)" />
<linearGradient
x1="30"
y1="25.084745"
x2="30"
y2="45"
id="linearGradient2873"
xlink:href="#linearGradient3785"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.51613236,0,0,0.51667107,-0.98397254,-0.49180897)" />
<linearGradient
x1="29.996229"
y1="21.440447"
x2="29.996229"
y2="43.531425"
id="linearGradient2875"
xlink:href="#linearGradient3341"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.51613236,0,0,0.51667107,-0.98397254,-0.49180897)" />
<radialGradient
cx="26.375898"
cy="12.31301"
r="8"
fx="26.375898"
fy="12.31301"
id="radialGradient2877"
xlink:href="#linearGradient6954"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.86552039,-0.07102871,0.06760608,0.84907396,-11.038912,-4.204803)" />
<linearGradient
x1="30"
y1="5"
x2="30"
y2="44.678879"
id="linearGradient2879"
xlink:href="#linearGradient3785"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.52770326,0,0,0.53573244,-1.3310981,-1.4043014)" />
<linearGradient
x1="22"
y1="39"
x2="17"
y2="37.4375"
id="linearGradient2881"
xlink:href="#linearGradient5060"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.74999995,0,0,0.43478262,-5.1276295,2.9173914)" />
<radialGradient
cx="30"
cy="33.1875"
r="4.6875"
fx="30"
fy="33.1875"
id="radialGradient2883"
xlink:href="#linearGradient5060"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.81491924,-3.8844793e-7,1.136461e-7,0.25340272,-9.9475804,6.5902095)" />
<linearGradient
x1="22"
y1="39"
x2="17"
y2="37.4375"
id="linearGradient2885"
xlink:href="#linearGradient5060"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(-0.74999995,0,0,0.43478262,34.15,2.9173914)" />
<linearGradient
x1="30.00001"
y1="6.333993"
x2="30.00001"
y2="24.913183"
id="linearGradient2887"
xlink:href="#linearGradient3341"
gradientUnits="userSpaceOnUse"
gradientTransform="matrix(0.52770326,0,0,0.53573244,-1.3310981,-1.4043014)" />
</defs>
<g
transform="translate(-3,-1.0000003)"
id="g3758">
<path
d="m 12.177403,10.099947 c 0.23753,1.124653 0.370116,1.975373 0.177421,3.100026 -1.502303,1.247697 -5.3445034,1.80835 -5.3387447,3.100025 l -0.5161321,3.875036 c 0,1.284073 3.5817448,2.325019 8.0000528,2.325019 4.418307,0 8.000053,-1.040946 8.000053,-2.325019 l -0.516134,-3.875036 c -0.0061,-1.105498 -3.870993,-1.808346 -5.354873,-3.100025 -0.126751,-1.043848 -0.02586,-2.056174 0.193549,-3.100026 l -4.645192,0 z"
id="path3766"
style="fill:url(#radialGradient2871);fill-opacity:1;stroke:url(#linearGradient2873);stroke-width:0.99989432;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
d="m 13.21875,11.09375 c 0.08722,0.856711 0.3354,1.801007 -0.04818,2.615857 -0.642554,0.728465 -1.594602,1.093826 -2.46738,1.472715 C 9.3226847,15.510467 7.7137266,16 7.9252179,16.998373 7.7834779,18.061416 7.641739,19.124458 7.5,20.1875 c 0.3063993,0.160613 1.0809439,0.584904 1.625,0.6875 2.520767,0.666947 5.16785,0.725367 7.754874,0.519516 1.511711,-0.166212 3.088649,-0.352665 4.432626,-1.113266 0.335436,-0.07362 0.107122,-0.316411 0.114936,-0.654915 -0.132062,-1.021278 -0.264124,-2.042557 -0.396186,-3.063835 -0.587648,-0.5027 -1.391296,-0.753519 -2.106391,-1.064577 -1.082782,-0.447299 -2.251468,-0.853003 -3.086912,-1.707994 -0.391617,-0.689558 -0.161473,-1.538743 -0.107324,-2.28649 0.259681,-0.52835 -0.223399,-0.401903 -0.552932,-0.409689 -0.652981,0 -1.305961,0 -1.958941,0 z"
id="path3742"
style="fill:none;stroke:url(#linearGradient2875);stroke-width:0.99989432;stroke-miterlimit:4;stroke-opacity:1" />
<path
d="m 14.5,1.5422262 c -2.185818,0 -3.957774,1.67899 -3.957774,3.7501272 0.01713,0.7664876 0.08155,1.6770462 0.527701,3.750127 0.263852,0.8035986 2.617283,2.9465296 2.638517,3.2143946 0.511701,0.267865 1.319258,0.267865 1.846964,0 0,-0.267865 2.110813,-2.410796 2.374664,-3.2143946 0.502046,-2.1545496 0.500773,-2.9465283 0.527702,-3.750127 0,-2.0711372 -1.771956,-3.7501272 -3.957774,-3.7501272 z"
id="path3764"
style="fill:url(#radialGradient2877);fill-opacity:1;stroke:url(#linearGradient2879);stroke-width:1.08445191;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
<path
d="M 10.62237,21.7 C 8.8506083,20.838176 9.6954668,18.924844 9.8723695,17.7 9.1223696,18.569566 9.5000001,21 8,21 c 1,0.355621 1.6845389,0.59817 2.62237,0.7 z"
id="path3848"
style="opacity:0.5;fill:url(#linearGradient2881);fill-opacity:1;stroke:none" />
<path
d="M 12,13.35048 C 12.366027,14.309818 13.343418,15 14.5,15 c 1.156582,0 2.133972,-0.690182 2.5,-1.64952 l -5,0 z"
id="path3833"
style="opacity:0.3;fill:url(#radialGradient2883);fill-opacity:1;stroke:none" />
<path
d="m 18.4,21.7 c 1.771762,-0.861824 0.926903,-2.775156 0.750001,-4 C 19.9,18.569566 19.52237,21 21.02237,21 c -1,0.355621 -1.684539,0.59817 -2.62237,0.7 z"
id="path3720"
style="opacity:0.5;fill:url(#linearGradient2885);fill-opacity:1;stroke:none" />
<path
d="m 14.5,2.53125 c -1.666616,0 -2.9513,1.2303173 -2.96875,2.71875 1.39e-4,0.00624 -1.45e-4,0.024997 0,0.03125 0.01647,0.7081029 0.08609,1.5272795 0.5,3.46875 -0.0051,-0.03667 0.09671,0.2041393 0.3125,0.46875 0.232433,0.2850235 0.566603,0.6083312 0.875,0.9375 0.308397,0.329169 0.598847,0.668975 0.84375,0.9375 0.09435,0.103448 0.171956,0.186905 0.25,0.28125 0.166811,0.03524 0.415249,0.03212 0.625,0 0.06182,-0.08397 0.114751,-0.159431 0.1875,-0.25 0.218248,-0.271707 0.473896,-0.575993 0.75,-0.90625 0.276104,-0.3302573 0.569207,-0.6813941 0.78125,-0.96875 0.197562,-0.2677316 0.307312,-0.503144 0.3125,-0.5 0.460701,-1.9997828 0.473735,-2.6695721 0.5,-3.46875 0,-0.010182 1.19e-4,-0.021091 0,-0.03125 C 17.4513,3.7615673 16.166616,2.53125 14.5,2.53125 z"
id="path3730"
style="fill:none;stroke:url(#linearGradient2887);stroke-width:1.08445191;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 8.0 KiB

View File

@ -108,6 +108,18 @@ Contacts={
})
$.each(contacts, function(idx, itm) { contactlist.append(itm); });
*/
setTimeout(Contacts.UI.Contacts.lazyupdate(), 500);
},
lazyupdate:function(){
//alert('lazyupdate');
$('#contacts li').live('inview', function(){
if (!$(this).attr('style')) {
//alert($(this).data('id') + ' has background: ' + $(this).attr('style'));
$(this).css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat');
}/* else {
alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url'));
}*/
});
}
}
}
@ -279,4 +291,25 @@ $(document).ready(function(){
});
$('#contacts_addcardform select').chosen();
$('#contacts li').bind('inview', function(event, isInView, visiblePartX, visiblePartY) {
if (isInView) { //NOTE: I've kept all conditions for future reference ;-)
// element is now visible in the viewport
if (visiblePartY == 'top') {
// top part of element is visible
} else if (visiblePartY == 'bottom') {
// bottom part of element is visible
} else {
// whole part of element is visible
if (!$(this).attr('style')) {
//alert($(this).data('id') + ' has background: ' + $(this).attr('style'));
$(this).css('background','url(thumbnail.php?id='+$(this).data('id')+') no-repeat');
}/* else {
alert($(this).data('id') + ' has style ' + $(this).attr('style').match('url'));
}*/
}
} else {
// element has gone out of viewport
}
});
});

View File

@ -0,0 +1,118 @@
/**
* author Christopher Blum
* - based on the idea of Remy Sharp, http://remysharp.com/2009/01/26/element-in-view-event-plugin/
* - forked from http://github.com/zuk/jquery.inview/
*/
(function ($) {
var inviewObjects = {}, viewportSize, viewportOffset,
d = document, w = window, documentElement = d.documentElement, expando = $.expando;
$.event.special.inview = {
add: function(data) {
inviewObjects[data.guid + "-" + this[expando]] = { data: data, $element: $(this) };
},
remove: function(data) {
try { delete inviewObjects[data.guid + "-" + this[expando]]; } catch(e) {}
}
};
function getViewportSize() {
var mode, domObject, size = { height: w.innerHeight, width: w.innerWidth };
// if this is correct then return it. iPad has compat Mode, so will
// go into check clientHeight/clientWidth (which has the wrong value).
if (!size.height) {
mode = d.compatMode;
if (mode || !$.support.boxModel) { // IE, Gecko
domObject = mode === 'CSS1Compat' ?
documentElement : // Standards
d.body; // Quirks
size = {
height: domObject.clientHeight,
width: domObject.clientWidth
};
}
}
return size;
}
function getViewportOffset() {
return {
top: w.pageYOffset || documentElement.scrollTop || d.body.scrollTop,
left: w.pageXOffset || documentElement.scrollLeft || d.body.scrollLeft
};
}
function checkInView() {
var $elements = $(), elementsLength, i = 0;
$.each(inviewObjects, function(i, inviewObject) {
var selector = inviewObject.data.selector,
$element = inviewObject.$element;
$elements = $elements.add(selector ? $element.find(selector) : $element);
});
elementsLength = $elements.length;
if (elementsLength) {
viewportSize = viewportSize || getViewportSize();
viewportOffset = viewportOffset || getViewportOffset();
for (; i<elementsLength; i++) {
// Ignore elements that are not in the DOM tree
if (!$.contains(documentElement, $elements[i])) {
continue;
}
var $element = $($elements[i]),
elementSize = { height: $element.height(), width: $element.width() },
elementOffset = $element.offset(),
inView = $element.data('inview'),
visiblePartX,
visiblePartY,
visiblePartsMerged;
// Don't ask me why because I haven't figured out yet:
// viewportOffset and viewportSize are sometimes suddenly null in Firefox 5.
// Even though it sounds weird:
// It seems that the execution of this function is interferred by the onresize/onscroll event
// where viewportOffset and viewportSize are unset
if (!viewportOffset || !viewportSize) {
return;
}
if (elementOffset.top + elementSize.height > viewportOffset.top &&
elementOffset.top < viewportOffset.top + viewportSize.height &&
elementOffset.left + elementSize.width > viewportOffset.left &&
elementOffset.left < viewportOffset.left + viewportSize.width) {
visiblePartX = (viewportOffset.left > elementOffset.left ?
'right' : (viewportOffset.left + viewportSize.width) < (elementOffset.left + elementSize.width) ?
'left' : 'both');
visiblePartY = (viewportOffset.top > elementOffset.top ?
'bottom' : (viewportOffset.top + viewportSize.height) < (elementOffset.top + elementSize.height) ?
'top' : 'both');
visiblePartsMerged = visiblePartX + "-" + visiblePartY;
if (!inView || inView !== visiblePartsMerged) {
$element.data('inview', visiblePartsMerged).trigger('inview', [true, visiblePartX, visiblePartY]);
}
} else if (inView) {
$element.data('inview', false).trigger('inview', [false]);
}
}
}
}
$(w).bind("scroll resize", function() {
viewportSize = viewportOffset = null;
});
// Use setInterval in order to also make sure this captures elements within
// "overflow:scroll" elements or elements that appeared in the dom tree due to
// dom manipulation and reflow
// old: $(window).scroll(checkInView);
//
// By the way, iOS (iPad, iPhone, ...) seems to not execute, or at least delays
// intervals while the user scrolls. Therefore the inview event might fire a bit late there
setInterval(checkInView, 250);
})(jQuery);

View File

@ -1,3 +1,10 @@
<?php // Include Style and Script
OC_Util::addScript('contacts','interface');
OC_Util::addScript('contacts','jquery.inview');
OC_Util::addStyle('contacts','styles');
OC_Util::addStyle('contacts','formtastic');
?>
<script type='text/javascript'>
var totalurl = '<?php echo OC_Helper::linkTo('contacts', 'carddav.php', null, true); ?>/addressbooks';
</script>

150
apps/contacts/thumbnail.php Normal file
View File

@ -0,0 +1,150 @@
<?php
/**
* ownCloud - Addressbook
*
* @author Jakob Sack
* @copyright 2011 Jakob Sack mail@jakobsack.de
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU AFFERO GENERAL PUBLIC LICENSE
* License as published by the Free Software Foundation; either
* version 3 of the License, or any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU AFFERO GENERAL PUBLIC LICENSE for more details.
*
* You should have received a copy of the GNU Affero General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*
*/
// Init owncloud
require_once('../../lib/base.php');
OC_Util::checkLoggedIn();
OC_Util::checkAppEnabled('contacts');
if(!function_exists('imagecreatefromjpeg')) {
OC_Log::write('contacts','GD module not installed',OC_Log::ERROR);
header('Content-Type: image/png');
// TODO: Check if it works to read the file and echo the content.
return 'img/person.png';
}
function getStandardImage(){
$src_img = imagecreatefrompng('img/person.png');
header('Content-Type: image/png');
imagepng($src_img);
imagedestroy($src_img);
}
$id = $_GET['id'];
$l10n = new OC_L10N('contacts');
$card = OC_Contacts_VCard::find( $id );
if( $card === false ){
echo $l10n->t('Contact could not be found.');
exit();
}
$addressbook = OC_Contacts_Addressbook::find( $card['addressbookid'] );
if( $addressbook === false || $addressbook['userid'] != OC_USER::getUser()){
echo $l10n->t('This is not your contact.'); // This is a weird error, why would it come up? (Better feedback for users?)
exit();
}
$content = OC_VObject::parse($card['carddata']);
// invalid vcard
if( is_null($content)){
echo $l10n->t('This card is not RFC compatible.');
exit();
}
// define the width and height for the thumbnail
// note that theese dimmensions are considered the maximum dimmension and are not fixed,
// because we have to keep the image ratio intact or it will be deformed
$thumbnail_width = 23;
$thumbnail_height = 23;
// Photo :-)
foreach($content->children as $child){
if($child->name == 'PHOTO'){
foreach($child->parameters as $parameter){
if( $parameter->name == 'TYPE' ){
$mime = $parameter->value;
}
}
$data = base64_decode($child->value);
$src_img = imagecreatefromstring($data);
if ($src_img !== false) {
//gets the dimmensions of the image
$width_orig=imageSX($src_img);
$height_orig=imageSY($src_img);
$ratio_orig = $width_orig/$height_orig;
if ($thumbnail_width/$thumbnail_height > $ratio_orig) {
$new_height = $thumbnail_width/$ratio_orig;
$new_width = $thumbnail_width;
} else {
$new_width = $thumbnail_height*$ratio_orig;
$new_height = $thumbnail_height;
}
$x_mid = $new_width/2; //horizontal middle
$y_mid = $new_height/2; //vertical middle
$process = imagecreatetruecolor(round($new_width), round($new_height));
if ($process == false) {
getStandardImage();
//echo 'Error creating process image: '.$new_width.'x'.$new_height;
OC_Log::write('contacts','Error creating process image for '.$id.' '.$new_width.'x'.$new_height,OC_Log::ERROR);
imagedestroy($process);
imagedestroy($src_img);
exit();
}
imagecopyresampled($process, $src_img, 0, 0, 0, 0, $new_width, $new_height, $width_orig, $height_orig);
if ($process == false) {
getStandardImage();
//echo 'Error resampling process image: '.$new_width.'x'.$new_height;
OC_Log::write('contacts','Error resampling process image for '.$id.' '.$new_width.'x'.$new_height,OC_Log::ERROR);
imagedestroy($process);
imagedestroy($src_img);
exit();
}
$thumb = imagecreatetruecolor($thumbnail_width, $thumbnail_height);
if ($process == false) {
getStandardImage();
//echo 'Error creating thumb image: '.$thumbnail_width.'x'.$thumbnail_height;
OC_Log::write('contacts','Error creating thumb image for '.$id.' '.$thumbnail_width.'x'.$thumbnail_height,OC_Log::ERROR);
imagedestroy($process);
imagedestroy($src_img);
exit();
}
imagecopyresampled($thumb, $process, 0, 0, ($x_mid-($thumbnail_width/2)), ($y_mid-($thumbnail_height/2)), $thumbnail_width, $thumbnail_height, $thumbnail_width, $thumbnail_height);
if ($thumb !== false) {
header('Content-Type: image/png');
imagepng($thumb);
} else {
getStandardImage();
OC_Log::write('contacts','Error resampling thumb image for '.$id.' '.$thumbnail_width.'x'.$thumbnail_height,OC_Log::ERROR);
//echo 'An error occurred resampling thumb.';
}
imagedestroy($thumb);
imagedestroy($process);
imagedestroy($src_img);
}
else {
getStandardImage();
}
exit();
}
}
getStandardImage();
// Not found :-(
//echo $l10n->t('This card does not contain a photo.');