Merge pull request #238 from electerious/v2.6.3

v2.6.3
This commit is contained in:
Tobias Reich 2014-10-10 22:41:59 +02:00
commit 056842ba8f
21 changed files with 260 additions and 101 deletions

View File

@ -50,6 +50,7 @@ Here's a list of all available Plugins and Extensions:
| Name | Description | |
|:-----------|:------------|:------------|
| lycheesync | Sync Lychee with any directory containing photos | [More »](https://github.com/GustavePate/lycheesync) |
| lycheeupload | Upload photos to Lychee via SSH | [More »](https://github.com/r0x0r/lycheeupload) |
| Jekyll | Liquid tag for Jekyll sites that allows embedding Lychee albums | [More »](https://gist.github.com/tobru/9171700) |
| lychee-redirect | Redirect from an album-name to a Lychee-album | [More »](https://github.com/electerious/lychee-redirect) |
| lychee-watermark | Adds a second watermarked photo when uploading images | [More »](https://github.com/electerious/lychee-watermark) |

View File

@ -113,8 +113,12 @@ album = {
if (data===true) data = 1; // Avoid first album to be true
if (data!==false&&isNumber(data)) lychee.goto(data);
else lychee.error(null, params, data);
if (data!==false&&isNumber(data)) {
albums.refresh();
lychee.goto(data);
} else {
lychee.error(null, params, data);
}
});
@ -146,9 +150,15 @@ album = {
albumIDs.forEach(function(id) {
albums.json.num--;
view.albums.content.delete(id);
delete albums.json.content[id];
});
} else lychee.goto("");
} else {
albums.refresh();
lychee.goto("");
}
if (data!==true) lychee.error(null, params, data);
@ -222,6 +232,11 @@ album = {
album.json.title = newTitle;
view.album.title();
if (albums.json) {
var id = albumIDs[0];
albums.json.content[id].title = newTitle;
}
} else if (visible.albums()) {
albumIDs.forEach(function(id) {
@ -290,6 +305,8 @@ album = {
listed = false,
downloadable = false;
albums.refresh();
if (!visible.message()&&album.json.public==0) {
modal.show("Share Album", "This album will be shared with the following properties:</p><form><div class='choice'><input type='checkbox' name='listed' value='listed' checked><h2>Visible</h2><p>Listed to visitors of your Lychee.</p></div><div class='choice'><input type='checkbox' name='downloadable' value='downloadable'><h2>Downloadable</h2><p>Visitors of your Lychee can download this album.</p></div><div class='choice'><input type='checkbox' name='password' value='password'><h2>Password protected</h2><p>Only accessible with a valid password.<input class='text' type='password' placeholder='password' value='' style='display: none;'></p></div></form><p style='display: none;'>", [["Share Album", function() { album.setPublic(album.getID(), e) }], ["Cancel", function() {}]], -170);

View File

@ -20,6 +20,8 @@ albums = {
startTime = new Date().getTime();
if(albums.json===null) {
lychee.api("getAlbums", function(data) {
/* Smart Albums */
@ -71,15 +73,21 @@ albums = {
if (visible.album()&&lychee.content.html()==="") waitTime = 0;
setTimeout(function() {
view.header.mode("albums");
view.albums.init();
lychee.animate(".album:nth-child(-n+50), .photo:nth-child(-n+50)", "contentZoomIn");
}, waitTime);
});
} else {
setTimeout(function() {
view.header.mode("albums");
view.albums.init();
lychee.animate(".album:nth-child(-n+50), .photo:nth-child(-n+50)", "contentZoomIn");
}, 300);
}
},
parse: function(album) {
@ -94,6 +102,12 @@ albums = {
if (!album.thumb2) album.thumb2 = "assets/img/no_images.svg";
}
},
refresh: function() {
albums.json = null;
}
};

View File

@ -34,7 +34,7 @@ build = {
title = albumJSON.title,
typeThumb = "";
if (title.length>18) {
if (title!==null&&title.length>18) {
title = albumJSON.title.substr(0, 18) + "...";
longTitle = albumJSON.title;
}
@ -76,7 +76,7 @@ build = {
longTitle = "",
title = photoJSON.title;
if (title.length>18) {
if (title!==null&&title.length>18) {
title = photoJSON.title.substr(0, 18) + "...";
longTitle = photoJSON.title;
}
@ -195,8 +195,8 @@ build = {
modal += "<h1><a class='icon-lock'></a> Sign In</h1>";
modal += "<a class='close icon-remove-sign'></a>";
modal += "<div class='sign_in'>";
modal += "<input id='username' type='text' name='' value='' placeholder='username'>";
modal += "<input id='password' type='password' name='' value='' placeholder='password'>";
modal += "<input id='username' type='text' value='' placeholder='username' autocapitalize='off' autocorrect='off'>";
modal += "<input id='password' type='password' value='' placeholder='password'>";
modal += "</div>";
modal += "<div id='version'>Version " + lychee.version + "<span> &#8211; <a target='_blank' href='" + lychee.updateURL + "'>Update available!</a><span></div>";
modal += "<a onclick='lychee.login()' class='button active'>Sign in</a>";

View File

@ -99,6 +99,7 @@ $(document).ready(function(){
})
.bind(['i', 'ctrl+i'], function() {
if (visible.infobox()) view.infobox.hide();
else if (visible.multiselect()) return false;
else if (visible.infoboxbutton()) view.infobox.show();
})
.bind(['command+backspace', 'ctrl+backspace'], function() {
@ -182,11 +183,20 @@ $(document).ready(function(){
.on(event_name, ".upload_message a.close", upload.close)
.on("dragover", function(e) { e.preventDefault(); }, false)
.on("drop", function(e) {
e.stopPropagation();
e.preventDefault();
// Close open overlays or views which are correlating with the upload
if (visible.photo()) lychee.goto(album.getID());
if (visible.contextMenu()) contextMenu.close();
// Detect if dropped item is a file or a link
if (e.originalEvent.dataTransfer.files.length>0) upload.start.local(e.originalEvent.dataTransfer.files);
else if (e.originalEvent.dataTransfer.getData('Text').length>3) upload.start.url(e.originalEvent.dataTransfer.getData('Text'));
return true;
});
/* Init */

View File

@ -8,8 +8,8 @@
var lychee = {
title: "",
version: "2.6.2",
version_code: "020602",
version: "2.6.3",
version_code: "020603",
api_path: "php/api.php",
update_path: "http://lychee.electerious.com/version/index.php",
@ -119,13 +119,23 @@ var lychee = {
params = "login&user=" + user + "&password=" + password;
lychee.api(params, function(data) {
if (data===true) {
localStorage.setItem("lychee_username", user);
// Use 'try' to catch a thrown error when Safari is in private mode
try { localStorage.setItem("lychee_username", user); }
catch (err) {}
window.location.reload();
} else {
// Show error and reactive button
$("#password").val("").addClass("error").focus();
$(".message .button.active").removeClass("pressed");
}
});
},
@ -181,7 +191,6 @@ var lychee = {
if (albumID&&photoID) {
// Trash data
albums.json = null;
photo.json = null;
// Show Photo
@ -194,7 +203,6 @@ var lychee = {
} else if (albumID) {
// Trash data
albums.json = null;
photo.json = null;
// Show Album
@ -205,7 +213,6 @@ var lychee = {
} else {
// Trash data
albums.json = null;
album.json = null;
photo.json = null;
search.code = "";

View File

@ -8,6 +8,7 @@
photo = {
json: null,
cache: null,
getID: function() {
@ -43,12 +44,41 @@ photo = {
view.photo.init();
lychee.imageview.show();
setTimeout(function() { lychee.content.show() }, 300);
setTimeout(function() {
lychee.content.show();
//photo.preloadNext(photoID, albumID);
}, 300);
});
},
//preload the next photo for better response time
preloadNext: function(photoID) {
var nextPhoto,
url;
// Never preload on mobile devices with bare RAM and
// mostly mobile internet
if (mobileBrowser()) return false;
if (album.json &&
album.json.content &&
album.json.content[photoID] &&
album.json.content[photoID].nextPhoto!="") {
nextPhoto = album.json.content[photoID].nextPhoto;
url = album.json.content[nextPhoto].url;
photo.cache = new Image();
photo.cache.src = url;
photo.cache.onload = function() { photo.cache = null };
}
},
parse: function() {
if (!photo.json.title) photo.json.title = "Untitled";
@ -124,6 +154,8 @@ photo = {
if (!photoIDs) return false;
if (photoIDs instanceof Array===false) photoIDs = [photoIDs];
albums.refresh();
params = "duplicatePhoto&photoIDs=" + photoIDs;
lychee.api(params, function(data) {
@ -177,6 +209,8 @@ photo = {
// Only when search is not active
if (!visible.albums()) lychee.goto(album.getID());
albums.refresh();
params = "deletePhoto&photoIDs=" + photoIDs;
lychee.api(params, function(data) {
@ -286,6 +320,8 @@ photo = {
});
albums.refresh();
params = "setPhotoAlbum&photoIDs=" + photoIDs + "&albumID=" + albumID;
lychee.api(params, function(data) {
@ -310,6 +346,8 @@ photo = {
view.album.content.star(id);
});
albums.refresh();
params = "setPhotoStar&photoIDs=" + photoIDs;
lychee.api(params, function(data) {
@ -341,6 +379,8 @@ photo = {
album.json.content[photoID].public = (album.json.content[photoID].public==0) ? 1 : 0;
view.album.content.public(photoID);
albums.refresh();
params = "setPhotoPublic&photoID=" + photoID;
lychee.api(params, function(data) {

View File

@ -215,6 +215,8 @@ var settings = {
sorting[0] = $("select#settings_type").val();
sorting[1] = $("select#settings_order").val();
albums.refresh();
params = "setSorting&type=" + sorting[0] + "&order=" + sorting[1];
lychee.api(params, function(data) {

View File

@ -65,6 +65,8 @@ upload = {
}
albums.refresh();
if (album.getID()===false) lychee.goto("0");
else album.load(albumID);
@ -259,6 +261,8 @@ upload = {
upload.close();
upload.notify("Import complete");
albums.refresh();
if (album.getID()===false) lychee.goto("0");
else album.load(albumID);
@ -306,6 +310,8 @@ upload = {
upload.close();
upload.notify("Import complete");
albums.refresh();
if (data==="Notice: Import only contains albums!") {
if (visible.albums()) lychee.load();
else lychee.goto("");
@ -365,6 +371,8 @@ upload = {
upload.close();
upload.notify("Import complete");
albums.refresh();
if (album.getID()===false) lychee.goto("0");
else album.load(albumID);

View File

@ -54,15 +54,21 @@ view = {
var albumID = album.getID();
switch (mode) {
case "albums":
lychee.header.removeClass("view");
$("#tools_album, #tools_photo").hide();
$("#tools_albums").show();
break;
case "album":
lychee.header.removeClass("view");
$("#tools_albums, #tools_photo").hide();
$("#tools_album").show();
album.json.content === false ? $("#button_archive").hide() : $("#button_archive").show();
if (lychee.publicMode&&album.json.downloadable==="0") $("#button_archive").hide();
if (albumID==="s"||albumID==="f"||albumID==="r") {
@ -73,11 +79,15 @@ view = {
} else {
$("#button_info_album, #button_trash_album, #button_share_album").show();
}
break;
case "photo":
lychee.header.addClass("view");
$("#tools_albums, #tools_album").hide();
$("#tools_photo").show();
break;
}
@ -122,6 +132,8 @@ view = {
content: {
scrollPosition: 0,
init: function() {
var smartData = "",
@ -137,12 +149,15 @@ view = {
/* Albums */
if (albums.json.content) {
if (!lychee.publicMode) albumsData = build.divider("Albums");
$.each(albums.json.content, function() {
albums.parse(this);
albumsData += build.album(this);
//display albums in reverse order
albumsData = build.album(this) + albumsData;
});
if (!lychee.publicMode) albumsData = build.divider("Albums") + albumsData;
}
if (smartData===""&&albumsData==="") {
@ -154,6 +169,11 @@ view = {
$("img[data-type!='nonretina']").retina();
/* Restore scroll position */
if (view.albums.content.scrollPosition!==null) {
$("html, body").scrollTop(view.albums.content.scrollPosition);
}
},
title: function(albumID) {
@ -163,7 +183,7 @@ view = {
title = albums.json.content[albumID].title;
if (albums.json.content[albumID].password) prefix = "<span class='icon-lock'></span> ";
if (title.length>18) {
if (title!==null&&title.length>18) {
longTitle = title;
title = title.substr(0, 18) + "...";
}
@ -251,6 +271,10 @@ view = {
$("img[data-type!='svg']").retina();
/* Save and reset scroll position */
view.albums.content.scrollPosition = $(document).scrollTop();
$("html, body").scrollTop(0);
},
title: function(photoID) {
@ -258,7 +282,7 @@ view = {
var longTitle = "",
title = album.json.content[photoID].title;
if (title.length>18) {
if (title!==null&&title.length>18) {
longTitle = title;
title = title.substr(0, 18) + "...";
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,7 +1,7 @@
var gulp = require('gulp'),
plugins = require("gulp-load-plugins")();
paths = {
var paths = {
view: [
'bower_components/jQuery/dist/jquery.min.js',
'bower_components/js-md5/js/md5.min.js',
@ -23,7 +23,14 @@ paths = {
]
}
gulp.task('view', function () {
var catchError = function(err) {
console.log(err.toString());
this.emit('end');
}
gulp.task('view', function() {
gulp.src(paths.view)
.pipe(plugins.concat('view.js', {newLine: "\n"}))
@ -32,19 +39,21 @@ gulp.task('view', function () {
});
gulp.task('js', function () {
gulp.task('js', function() {
gulp.src(paths.js)
.pipe(plugins.concat('main.js', {newLine: "\n"}))
.pipe(plugins.uglify())
.on('error', catchError)
.pipe(gulp.dest('../assets/min/'));
});
gulp.task('css', function () {
gulp.task('css', function() {
gulp.src(paths.css)
.pipe(plugins.sass())
.on('error', catchError)
.pipe(plugins.concat('main.css', {newLine: "\n"}))
.pipe(plugins.autoprefixer('last 4 versions', '> 5%'))
.pipe(plugins.minifyCss())

View File

@ -1,6 +1,6 @@
{
"name": "Lychee",
"version": "2.6.2",
"version": "2.6.3",
"description": "Self-hosted photo-management done right.",
"authors": "Tobias Reich <tobias.reich.ich@gmail.com>",
"license": "MIT",
@ -10,11 +10,11 @@
},
"devDependencies": {
"gulp": "^3.8.8",
"gulp-autoprefixer": "1.0.0",
"gulp-concat": "^2.4.0",
"gulp-load-plugins": "^0.6.0",
"gulp-minify-css": "^0.3.8",
"gulp-sass": "^0.7.3",
"gulp-autoprefixer": "1.0.1",
"gulp-concat": "^2.4.1",
"gulp-load-plugins": "^0.7.0",
"gulp-minify-css": "^0.3.10",
"gulp-sass": "^1.0.0",
"gulp-uglify": "^1.0.1"
}
}

View File

@ -1,3 +1,16 @@
## v2.6.3
Released ??, 2014
- `New` Caching for albums (Thanks @r0x0r, #232)
- `New` Save scroll position of albums (Thanks @r0x0r, #232)
- `New` Added Dockerfile (@renfredxh, #236)
- `Improved` Newest album on the top (Thanks @r0x0r, #232)
- `Fixed` Login in private mode (Safari)
- `Fixed` Drag & Drop with open photo
- `Fixed` Wrong modified date of the photo files
- `Fixed` Search function always returned all photos (Thanks @powentan, #234)
## v2.6.2
Released September 12, 2014

View File

@ -16,7 +16,7 @@
<link rel="apple-touch-icon" href="assets/img/apple-touch-icon-iphone.png" sizes="120x120">
<link rel="apple-touch-icon" href="assets/img/apple-touch-icon-ipad.png" sizes="152x152">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0, minimal-ui">
<meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1.0, maximum-scale=1.0">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-capable" content="yes">

View File

@ -10,6 +10,9 @@ if (!defined('LYCHEE')) exit('Error: Direct access is not allowed!');
function lycheeAutoloaderModules($class_name) {
$modules = array('Album', 'Database', 'Import', 'Log', 'Module', 'Photo', 'Plugins', 'Session', 'Settings');
if (!in_array($class_name, $modules)) return false;
$file = LYCHEE . 'php/modules/' . $class_name . '.php';
if (file_exists($file)!==false) require $file;
@ -17,6 +20,9 @@ function lycheeAutoloaderModules($class_name) {
function lycheeAutoloaderAccess($class_name) {
$access = array('Access', 'Admin', 'Guest', 'Installation');
if (!in_array($class_name, $access)) return false;
$file = LYCHEE . 'php/access/' . $class_name . '.php';
if (file_exists($file)!==false) require $file;

View File

@ -65,19 +65,19 @@ class Album extends Module {
switch ($this->albumIDs) {
case 'f': $return['public'] = false;
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp FROM ? WHERE star = 1 " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE star = 1 " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
break;
case 's': $return['public'] = false;
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp FROM ? WHERE public = 1 " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE public = 1 " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
break;
case 'r': $return['public'] = false;
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE LEFT(id, 10) >= unix_timestamp(DATE_SUB(NOW(), INTERVAL 1 DAY)) " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
break;
case '0': $return['public'] = false;
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp FROM ? WHERE album = 0 " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = 0 " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS));
break;
default: $query = Database::prepare($this->database, "SELECT * FROM ? WHERE id = '?' LIMIT 1", array(LYCHEE_TABLE_ALBUMS, $this->albumIDs));
@ -85,7 +85,7 @@ class Album extends Module {
$return = $albums->fetch_assoc();
$return['sysdate'] = date('d M. Y', $return['sysstamp']);
$return['password'] = ($return['password']=='' ? false : true);
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp FROM ? WHERE album = '?' " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
$query = Database::prepare($this->database, "SELECT id, title, tags, public, star, album, thumbUrl, takestamp, url FROM ? WHERE album = '?' " . $this->settings['sorting'], array(LYCHEE_TABLE_PHOTOS, $this->albumIDs));
break;
}
@ -101,6 +101,9 @@ class Album extends Module {
$photo['nextPhoto'] = '';
$photo['thumbUrl'] = LYCHEE_URL_UPLOADS_THUMB . $photo['thumbUrl'];
# Parse url
$photo['url'] = LYCHEE_URL_UPLOADS_BIG . $photo['url'];
if (isset($photo['takestamp'])&&$photo['takestamp']!=='0') {
$photo['cameraDate'] = 1;
$photo['sysdate'] = date('d F Y', $photo['takestamp']);

View File

@ -24,6 +24,9 @@ class Database extends Module {
if ($database->server_version<50500) $database->set_charset('GBK');
else $database->set_charset("utf8");
# Set unicode
$database->query('SET NAMES utf8;');
# Check database
if (!$database->select_db($name))
if (!Database::createDatabase($database, $name)) exit('Error: Could not create database!');
@ -41,6 +44,7 @@ class Database extends Module {
# Check dependencies
Module::dependencies(isset($database, $dbName));
if (!isset($version)) return true;
# List of updates
$updates = array(
@ -56,7 +60,7 @@ class Database extends Module {
# For each update
foreach ($updates as $update) {
if (isset($version)&&$update<=$version) continue;
if ($update<=$version) continue;
# Load update
include(__DIR__ . '/../database/update_' . $update . '.php');

View File

@ -161,7 +161,7 @@ class Photo extends Module {
}
# Set original date
if ($info['takestamp']!=='') @touch($path, $info['takestamp']);
if ($info['takestamp']!==''&&$info['takestamp']!==0) @touch($path, $info['takestamp']);
# Create Thumb
if (!$this->createThumb($path, $photo_name)) {

View File

@ -99,7 +99,8 @@ $imagick = extension_loaded('imagick');
if ($imagick===false) $imagick = '-';
if ($imagick===true) $imagickVersion = @Imagick::getVersion();
if (!isset($imagickVersion)||$imagickVersion==='') $imagickVersion = '-';
if (!isset($imagickVersion, $imagickVersion['versionNumber'])||$imagickVersion==='') $imagickVersion = '-';
else $imagickVersion = $imagickVersion['versionNumber'];
$gdVersion = gd_info();
@ -111,7 +112,7 @@ echo('PHP Version: ' . floatval(phpversion()) . PHP_EOL);
echo('MySQL Version: ' . $database->server_version . PHP_EOL);
echo('Imagick: ' . $imagick . PHP_EOL);
echo('Imagick Active: ' . $settings['imagick'] . PHP_EOL);
echo('Imagick Version: ' . $imagickVersion['versionNumber'] . PHP_EOL);
echo('Imagick Version: ' . $imagickVersion . PHP_EOL);
echo('GD Version: ' . $gdVersion['GD Version'] . PHP_EOL);
?>