- Share > Direct Link
- Download individual images (Issue #43)
- ContextMenu stays within the window (Issue #41)
- Prevent default ContextMenu (Issue #45)
- Small ContextMenu improvements
- Small security improvements
This commit is contained in:
Tobias Reich 2014-01-24 13:49:01 +01:00
parent f9f4afe7db
commit 79607485fb
20 changed files with 139 additions and 63 deletions

File diff suppressed because one or more lines are too long

View File

@ -12,8 +12,8 @@
}
.contextmenu {
position: fixed;
top: 110%;
left: 110%;
top: 0px;
left: 0px;
padding: 5px 0px 6px 0px;
background-color: #393939;
background-image: -webkit-linear-gradient(top, #444, #2d2d2d);
@ -24,8 +24,12 @@
border-bottom: 1px solid rgba(0,0,0,.9);
border-radius: 5px;
box-shadow: 0px 4px 5px rgba(0,0,0,0.3), inset 0px 1px 0px rgba(255,255,255,0.15), inset 1px 0px 0px rgba(255,255,255,0.05), inset -1px 0px 0px rgba(255,255,255,0.05);
opacity: .98;
opacity: 0;
z-index: 1001;
-webkit-transition: none;
-moz-transition: none;
transition: none;
}
/* Items ------------------------------------------------*/

File diff suppressed because one or more lines are too long

View File

@ -128,7 +128,7 @@ album = {
buttons = [
["Delete Album and Photos", function() {
params = "deleteAlbum&albumID=" + albumID + "&delAll=true";
params = "deleteAlbum&albumID=" + albumID;
lychee.api(params, function(data) {
if (visible.albums()) {

View File

@ -197,12 +197,12 @@ build = {
},
contextMenu: function(items, orientation) {
contextMenu: function(items) {
var menu = "";
menu += "<div class='contextmenu_bg'></div>";
menu += "<div class='contextmenu " + orientation + "'>";
menu += "<div class='contextmenu'>";
menu += "<table>";
menu += "<tbody>";

View File

@ -11,11 +11,14 @@ contextMenu = {
show: function(items, mouse_x, mouse_y, orientation) {
contextMenu.close();
if (visible.contextMenu()) contextMenu.close();
$("body")
.css("overflow", "hidden")
.append(build.contextMenu(items, orientation));
.append(build.contextMenu(items));
if ((mouse_x+$(".contextmenu").outerWidth(true))>$("html").width()) orientation = "left";
if ((mouse_y+$(".contextmenu").outerHeight(true))>$("html").height()) mouse_y -= (mouse_y+$(".contextmenu").outerHeight(true)-$("html").height())
if (orientation==="left") mouse_x -= $(".contextmenu").outerWidth(true);
@ -26,7 +29,8 @@ contextMenu = {
$(".contextmenu").css({
"top": mouse_y,
"left": mouse_x
"left": mouse_x,
"opacity": .98
});
},
@ -90,7 +94,6 @@ contextMenu = {
album: function(albumID, e) {
e.preventDefault();
var mouse_x = e.pageX,
mouse_y = e.pageY,
items;
@ -117,7 +120,6 @@ contextMenu = {
photo: function(photoID, e) {
e.preventDefault();
var mouse_x = e.pageX,
mouse_y = e.pageY,
items;
@ -152,14 +154,6 @@ contextMenu = {
items = [];
contextMenu.fns = [];
mouse_y -= $(document).scrollTop();
if (orientation===undefined) orientation = "left";
if (!mouse_x||!mouse_y) {
mouse_x = "10px";
mouse_y = "10px";
}
if (album.getID()!=="0") {
items = [
@ -179,15 +173,11 @@ contextMenu = {
}
contextMenu.close();
$(".photo[data-id='" + photoID + "']").addClass("active");
$("body")
.css("overflow", "hidden")
.append(build.contextMenu(items, orientation));
if (!visible.photo()) mouse_x += $(".contextmenu").width();
$(".contextmenu").css({
"top": mouse_y,
"left": mouse_x-$(".contextmenu").width()
});
if (!visible.photo()) contextMenu.show(items, mouse_x, mouse_y, "right");
else contextMenu.show(items, mouse_x, mouse_y, "left");
});
@ -206,18 +196,23 @@ contextMenu = {
function() { photo.share(photoID, 0) },
function() { photo.share(photoID, 1) },
function() { photo.share(photoID, 2) },
function() { photo.share(photoID, 3) }
function() { photo.share(photoID, 3) },
function() { window.open(photo.getDirectLink(),"_newtab") }
];
link = photo.getViewLink(photoID);
if (photo.json.public==="2") link = location.href;
items = [
["<input readonly id='link' value='" + photo.getViewLink(photoID) + "'>", -1],
["<input readonly id='link' value='" + link + "'>", -1],
["separator", -1],
["<a class='icon-eye-close'></a> Make Private", 0],
["separator", -1],
["<a class='icon-twitter'></a> Twitter", 1],
["<a class='icon-facebook'></a> Facebook", 2],
["<a class='icon-envelope'></a> Mail", 3],
["<a class='icon-hdd'></a> Dropbox", 4]
["<a class='icon-hdd'></a> Dropbox", 4],
["<a class='icon-link'></a> Direct Link", 5]
];
contextMenu.show(items, mouse_x, mouse_y, "left");

View File

@ -11,6 +11,9 @@ $(document).ready(function(){
/* Notifications */
if (window.webkitNotifications) window.webkitNotifications.requestPermission();
/* Disable ContextMenu */
$(document).bind("contextmenu", function(e) { e.preventDefault() });
/* Tooltips */
if (!mobileBrowser()) $(".tools").tipsy({gravity: 'n', fade: false, delayIn: 0, opacity: 1});
@ -27,7 +30,7 @@ $(document).ready(function(){
if (album.json.public==1) contextMenu.shareAlbum(album.getID(), e);
else modal.show("Share Album", "All photos inside this album will be public and visible for everyone. Existing public photos will have the same sharing permission as this album. Are your sure you want to share this album? <input class='text' type='password' placeholder='password (optional)' value=''>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]]);
});
$("#button_download").on(event_name, function() { window.open(photo.getDirectLink(),"_newtab") });
$("#button_download").on(event_name, function() { photo.getArchive(photo.getID()) });
$("#button_trash_album").on(event_name, function() { album.delete(album.getID()) });
$("#button_move").on(event_name, function(e) { contextMenu.move(photo.getID(), e) });
$("#button_trash").on(event_name, function() { photo.delete(photo.getID()) });
@ -64,7 +67,6 @@ $(document).ready(function(){
Mousetrap
.bind('u', function() { $("#upload_files").click() })
.bind('s', function() { if (visible.photo()) $("#button_star").click() })
.bind('f', function() { if (visible.photo()) $("#button_download").click() })
.bind('command+backspace', function() { if (visible.photo()&&!visible.message()) photo.delete(photo.getID()) })
.bind('left', function() { if (visible.photo()) $("#imageview a#previous").click() })
.bind('right', function() { if (visible.photo()) $("#imageview a#next").click() })
@ -118,6 +120,7 @@ $(document).ready(function(){
.on("contextmenu", ".photo", function(e) { contextMenu.photo(photo.getID(), e) })
.on("contextmenu", ".album", function(e) { contextMenu.album(album.getID(), e) })
.on(event_name, ".contextmenu_bg", contextMenu.close)
.on("contextmenu", ".contextmenu_bg", contextMenu.close)
/* Infobox */
.on(event_name, "#infobox_overlay", view.infobox.hide)

View File

@ -7,7 +7,7 @@
var lychee = {
version: "2.0",
version: "2.0.1",
api_path: "php/api.php",
update_path: "http://lychee.electerious.com/version/index.php",

View File

@ -310,6 +310,19 @@ photo = {
},
getArchive: function(photoID) {
var link;
if (location.href.indexOf("index.html")>0) link = location.href.replace(location.hash, "").replace("index.html", "php/api.php?function=getPhotoArchive&photoID=" + photoID);
else link = location.href.replace(location.hash, "") + "php/api.php?function=getPhotoArchive&photoID=" + photoID;
if (lychee.publicMode) link += "&password=" + password.value;
location.href = link;
},
getDirectLink: function() {
return $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "");

View File

@ -35,7 +35,7 @@ view = {
hide: function() {
if (visible.photo()&&!visible.infobox()) {
if (visible.photo()&&!visible.infobox()&&!visible.contextMenu()&&!visible.message()) {
clearTimeout($(window).data("timeout"));
$(window).data("timeout", setTimeout(function() {
lychee.imageview.addClass("full");

View File

@ -25,10 +25,12 @@ $(document).ready(function(){
$(document).on(event_name, "#infobox_overlay", function() { hideInfobox() });
$("#button_info").on(event_name, function() { showInfobox() });
/* Download */
$("#button_download").on(event_name, function() {
/* Direct Link */
$("#button_direct").on(event_name, function() {
link = $("#imageview #image").css("background-image").replace(/"/g,"").replace(/url\(|\)$/ig, "");
window.open(link,"_newtab");
});
loadPhotoInfo(gup("p"));

View File

@ -1,6 +1,6 @@
#!/bin/sh
VERSION='1.3.2'
VERSION='2.0'
echo 'Press ENTER to continue or any other key to abort'
read -s -n 1 key

View File

@ -1,11 +1,25 @@
### v2.0
## v2.0.1
Released January 24, 2014
- Share > Direct Link
- Download individual images (Issue #43)
- ContextMenu stays within the window (Issue #41)
- Prevent default ContextMenu (Issue #45)
- Small ContextMenu improvements
- Small security improvements
## v2.0
Released January 22, 2014
- All new redefined interface
- Faster animations and transitions
- Import from Dropbox
- Import from Server
- Download public albums
- Several sorting options
- Installation assistent
- Installation assistant
- Infobox and description for albums
- Faster loading and improved performance
- Better file handling and upload

View File

@ -18,7 +18,7 @@ If possible, change these settings directly in your `php.ini`. We recommend to i
Lychee supports the latest versions of Google Chrome, Apple Safari, Mozilla Firefox and Opera. Photos you share with others can be viewed from every browser.
#### How can I set thumbnails for my albums?
Thumbnails are choosen automatically by the photos you have starred and in the order you uploaded them. Star a photo inside a album to set it as an thumbnail.
Thumbnails are chosen automatically by the photos you have starred and in the order you uploaded them. Star a photo inside a album to set it as an thumbnail.
#### What is new?
Take a look at the [Changelog](Changelog.md) to see whats new.

View File

@ -11,7 +11,6 @@
|:-----------|:------------|
| `s` | Star photo |
| `i` | Show information |
| `f` | Show photo in new tab
| `cmd`+`backspace` | Delete photo
| `left` | Previous photo
| `right` | Next photo

View File

@ -70,7 +70,7 @@
<div class="tools" id="button_trash" title="Delete"><a class="icon-trash"></a></div>
<div class="tools" id="button_move" title="Move"><a class="icon-folder-open"></a></div>
<a class="button_divider"></a>
<div class="tools" id="button_download" title="Full Photo"><a class="icon-resize-full"></a></div>
<div class="tools" id="button_download" title="Download"><a class="icon-circle-arrow-down"></a></div>
<div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div>
<a class="button_divider"></a>
<div class="tools" id="button_share" title="Share Photo"><a class="icon-share"></a></div>
@ -92,7 +92,7 @@
<!-- Upload -->
<div id="upload">
<input id="upload_files" type="file" name="fileElem[]" multiple="true" accept="image/*">
<input id="upload_files" type="file" name="fileElem[]" multiple accept="image/*">
</div>
<!-- JS -->

View File

@ -56,9 +56,10 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
$settings = getSettings();
// Security
if (isset($_POST['albumID'])&&($_POST['albumID']==''||$_POST['albumID']<0)) exit('Error: Wrong parameter type for albumID!');
if (isset($_POST['albumID'])&&($_POST['albumID']==''||$_POST['albumID']<0||$_POST['albumID']>10000)) exit('Error: Wrong parameter type for albumID!');
if (isset($_POST['photoID'])&&$_POST['photoID']=='') exit('Error: Wrong parameter type for photoID!');
foreach(array_keys($_POST) as $key) $_POST[$key] = mysqli_real_escape_string($database, urldecode($_POST[$key]));
foreach(array_keys($_GET) as $key) $_GET[$key] = mysqli_real_escape_string($database, urldecode($_GET[$key]));
if (isset($_SESSION['login'])&&$_SESSION['login']==true) {
@ -98,8 +99,8 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
echo setAlbumPassword($_POST['albumID'], $_POST['password']);
break;
case 'deleteAlbum': if (isset($_POST['albumID'])&&isset($_POST['delAll']))
echo deleteAlbum($_POST['albumID'], $_POST['delAll']);
case 'deleteAlbum': if (isset($_POST['albumID']))
echo deleteAlbum($_POST['albumID']);
break;
// Photo Functions
@ -179,13 +180,25 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
case 'update': echo update();
default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID']))
// Album Archive
// Album Download
getAlbumArchive($_GET['albumID']);
else if (isset($_GET['function'])&&$_GET['function']=='getPhotoArchive'&&isset($_GET['photoID']))
// Photo Download
getPhotoArchive($_GET['photoID']);
else if (isset($_GET['function'])&&$_GET['function']=='update')
// Update Lychee
echo update();
else
// Function unknown
exit('Error: Function not found! Please check the spelling of the called function.');
break;
}
@ -254,18 +267,34 @@ if (!empty($_POST['function'])||!empty($_GET['function'])) {
// Miscellaneous
default: if (isset($_GET['function'])&&$_GET['function']=='getAlbumArchive'&&isset($_GET['albumID'])&&isset($_GET['password'])) {
// Album Download
if (isAlbumPublic($_GET['albumID'])) {
// Album Public
if (checkAlbumPassword($_GET['albumID'], $_GET['password']))
getAlbumArchive($_GET['albumID']);
else
echo 'Warning: Wrong password!';
exit('Warning: Wrong password!');
} else {
// Album Private
echo 'Warning: Album private or not downloadable!';
exit('Warning: Album private or not downloadable!');
}
} else if (isset($_GET['function'])&&$_GET['function']=='getPhotoArchive'&&isset($_GET['photoID'])&&isset($_GET['password'])) {
// Photo Download
if (isPhotoPublic($_GET['photoID'], $_GET['password']))
// Photo Public
getPhotoArchive($_GET['photoID']);
else
// Photo Private
exit('Warning: Photo private or not downloadable!');
} else {
// Function unknown
exit('Error: Function not found! Please check the spelling of the called function.');
}
break;

16
php/modules/album.php Executable file → Normal file
View File

@ -213,19 +213,15 @@ function setAlbumDescription($albumID, $description) {
}
function deleteAlbum($albumID, $delAll) {
function deleteAlbum($albumID) {
global $database;
if ($delAll=="true") {
$result = $database->query("SELECT id FROM lychee_photos WHERE album = '$albumID';");
$error = false;
while($row = $result->fetch_object()) {
if (!deletePhoto($row->id)) $error = true;
}
} else {
$result = $database->query("UPDATE lychee_photos SET album = '0' WHERE album = '$albumID';");
if (!$result) return false;
$error = false;
$result = $database->query("SELECT id FROM lychee_photos WHERE album = '$albumID';");
while($row = $result->fetch_object()) {
if (!deletePhoto($row->id)) $error = true;
}
if ($albumID!=0) {

21
php/modules/photo.php Executable file → Normal file
View File

@ -164,4 +164,25 @@ function isPhotoPublic($photoID, $password) {
}
function getPhotoArchive($photoID) {
global $database;
$result = $database->query("SELECT * FROM lychee_photos WHERE id = '$photoID';");
$row = $result->fetch_object();
$extension = array_reverse(explode('.', $row->url));
if ($row->title=='') $row->title = 'Untitled';
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=\"$row->title.$extension[0]\"");
header("Content-Length: " . filesize("../uploads/big/$row->url"));
readfile("../uploads/big/$row->url");
return true;
}
?>

View File

@ -43,7 +43,7 @@
<header class="view">
<!-- Buttons -->
<div class="tools" id="button_download" title="Full Photo"><a class="icon-resize-full"></a></div>
<div class="tools" id="button_direct" title="Direct Link"><a class="icon-link"></a></div>
<div class="tools" id="button_info" title="Show Info"><a class="icon-info-sign"></a></div>
<a id="title" class="view"></a>