Merge pull request #6 from electerious/develop

Develop
pull/520/head
Quentin Ligier 8 years ago
commit 55577e1c39

2
dist/main.css vendored

File diff suppressed because one or more lines are too long

12
dist/main.js vendored

File diff suppressed because one or more lines are too long

8
dist/view.js vendored

File diff suppressed because one or more lines are too long

@ -1,6 +1,6 @@
## v3.1.0
Released March ??, 2016
Released March 29, 2016
**Warning**: It's no longer possible to update from Lychee versions older than 2.7.
@ -14,7 +14,8 @@ This updates includes a huge rewrite of the back-end. We are now using namespace
- `New` Empty titles for albums
- `New` Share albums as hidden so they are only viewable with a direct link (#27)
- `Improved` Error messages and log output
- `New` Log failed and successful login attempts (Thanks @qligier, #382 #246)
- `Improved` error messages and log output
- `Improved` The search shows albums above photos (#434)
- `Improved` Album id now based on the current microtime (#27)
- `Improved` Back-end modules and plugins
@ -22,6 +23,10 @@ This updates includes a huge rewrite of the back-end. We are now using namespace
- `Improved` Default photo title now "Untitled"
- `Improved` Move to next photo after after moving a picture (#437)
- `Improved` Return to album overview when canceling album password input
- `Improved` URL import now accepts photo URLs containing "?" and ":" (Thanks @qligier, #482)
- `Improved` Replaced date by strftime to simplify date translations (Thanks @qligier, #461)
- `Fixed` Missing icons in Safari 9.1
- `Fixed` duplicate uploads (Thanks @qligier, #433)
- `Fixed` incorrect escaping when using backslashes
- `Fixed` session_start() after sending headers (#433)
- `Fixed` error when deleting last open photo in album

@ -55,4 +55,7 @@ Yes. Lychee uses ImageMagick when available.
There's a problem with images compressed by ImageOptim. [Read more.](https://github.com/electerious/Lychee/issues/175#issuecomment-47403992)
#### How to change the title of the site?
[#455](https://github.com/electerious/Lychee/issues/455)
[#455](https://github.com/electerious/Lychee/issues/455)
#### How to reset username and password?
Simply delete the whole `lychee_settings` table from the database. Lychee will regenerate it and ask you to enter a new username and password.

@ -93,7 +93,7 @@ final class Admin extends Access {
Validator::required(isset($_POST['title']), __METHOD__);
$album = new Album(null);
Response::json($album->add($_POST['title']));
Response::json($album->add($_POST['title']), JSON_NUMERIC_CHECK);
}
@ -231,7 +231,7 @@ final class Admin extends Access {
Validator::required(isset($_FILES, $_POST['albumID']), __METHOD__);
$photo = new Photo(null);
Response::json($photo->add($_FILES, $_POST['albumID']));
Response::json($photo->add($_FILES, $_POST['albumID']), JSON_NUMERIC_CHECK);
}
@ -249,7 +249,7 @@ final class Admin extends Access {
Validator::required(isset($_POST['albumID'], $_POST['path']), __METHOD__);
$import = new Import();
echo $import->server($_POST['path'], $_POST['albumID']);
Response::json($import->server($_POST['path'], $_POST['albumID']));
}

@ -26,7 +26,7 @@ final class Installation extends Access {
Validator::required(isset($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']), __METHOD__);
echo Config::create($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']);
Response::json(Config::create($_POST['dbHost'], $_POST['dbUser'], $_POST['dbPassword'], $_POST['dbName'], $_POST['dbTablePrefix']));
}

@ -21,7 +21,7 @@ final class Album {
}
/**
* @return integer|false ID of the created album.
* @return string|false ID of the created album.
*/
public function add($title = 'Untitled') {

@ -42,7 +42,7 @@ $config = "<?php
?>";
// Save file
if (file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!';
if (@file_put_contents(LYCHEE_CONFIG_FILE, $config)===false) return 'Warning: Could not create file!';
return true;

@ -56,7 +56,7 @@ final class Database {
$connection = self::connect($host, $user, $password);
// Check if the connection was successful
if ($connection===false) Response::error('' . $connection->connect_error);
if ($connection===false) Response::error($connection->connect_error);
if (self::setCharset($connection)===false) Response::error('Could not set database charset!');
@ -81,7 +81,7 @@ final class Database {
public static function connect($host = 'localhost', $user, $password) {
// Open a new connection to the MySQL server
$connection = new Mysqli($host, $user, $password);
$connection = @new Mysqli($host, $user, $password);
// Check if the connection was successful
if ($connection->connect_errno) return false;

@ -39,7 +39,7 @@ final class Photo {
* Creats new photo(s).
* Exits on error.
* Use $returnOnError if you want to handle errors by your own.
* @return boolean Returns true when successful.
* @return string|false ID of the added photo.
*/
public function add(array $files, $albumID = 0, $returnOnError = false) {
@ -251,7 +251,7 @@ final class Photo {
// Call plugins
Plugins::get()->activate(__METHOD__, 1, func_get_args());
return true;
return $id;
}

@ -6,19 +6,19 @@ final class Response {
public static function warning($msg) {
exit('Warning: ' . $msg);
exit(json_encode('Warning: ' . $msg));
}
public static function error($msg) {
exit('Error: ' . $msg);
exit(json_encode('Error: ' . $msg));
}
public static function json($str) {
public static function json($str, $options = 0) {
exit(json_encode($str));
exit(json_encode($str, $options));
}

@ -14,6 +14,6 @@ $result = Database::execute($connection, $query, 'update_030100', __LINE__);
if ($result===false) Response::error('Could not adjust the length of the album id field!');
// Set version
// if (Database::setVersion($connection, '030100')===false) Response::error('Could not update version of database!');
if (Database::setVersion($connection, '030100')===false) Response::error('Could not update version of database!');
?>

@ -26,7 +26,7 @@ define('LYCHEE_URL_UPLOADS_BIG', 'uploads/big/');
define('LYCHEE_URL_UPLOADS_MEDIUM', 'uploads/medium/');
define('LYCHEE_URL_UPLOADS_THUMB', 'uploads/thumb/');
function defineTablePrefix($dbTablePrefix = '') {
function defineTablePrefix($dbTablePrefix) {
// This part is wrapped into a function, because it needs to be called
// after the config-file has been loaded. Other defines are available
@ -34,6 +34,7 @@ function defineTablePrefix($dbTablePrefix = '') {
// Parse table prefix
// Old users do not have the table prefix stored in their config-file
if (isset($dbTablePrefix)===false) $dbTablePrefix = '';
if ($dbTablePrefix!=='') $dbTablePrefix .= '_';
// Define tables

@ -1,5 +1,8 @@
<?php
/**
* @return string Generated ID.
*/
function generateID() {
// Generate id based on the current microtime
@ -8,8 +11,9 @@ function generateID() {
// Ensure that the id has a length of 14 chars
while(strlen($id)<14) $id .= 0;
// Return the integer value of the id
return intval($id);
// Return id as a string. Don't convert the id to an integer
// as 14 digits are too big for 32bit PHP versions.
return $id;
}

@ -28,6 +28,7 @@ paths.view = {
],
scripts: [
'node_modules/jquery/dist/jquery.min.js',
'node_modules/basiccontext/dist/basicContext.min.js',
'../dist/_view--javascript.js'
],
svg: [

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

@ -1 +1 @@
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"><title>Group</title><desc>Created with Sketch.</desc><g sketch:type="MSShapeGroup" fill="none"><path d="M0 0h16v16h-16v-16z" id="Shape" fill="#444"/><path id="Rectangle-path" stroke="#aaa" d="M4 4h5v5h-5z"/><path d="M6 6h8v7h-8v-7z" fill="#444"/><path stroke="#aaa" d="M7 7h5v5h-5z"/></g></svg>
<svg width="16" height="16" viewBox="0 0 16 16" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path d="M0 0h16v16h-16v-16z" fill="#444"/><path stroke="#aaa" d="M4 4h5v5h-5z"/><path d="M6 6h8v7h-8v-7z" fill="#444"/><path stroke="#aaa" d="M7 7h5v5h-5z"/></g></svg>

Before

Width:  |  Height:  |  Size: 432 B

After

Width:  |  Height:  |  Size: 266 B

@ -1 +1 @@
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"><title>Group</title><desc>Created with Sketch.</desc><g sketch:type="MSLayerGroup" fill="none"><path d="M0 0h200v200h-200v-200z" id="Shape" fill="#222" sketch:type="MSShapeGroup"/><g sketch:type="MSShapeGroup"><path id="Rectangle-path" stroke="#B4B4B4" stroke-width="4" d="M68 52h50v42h-50z"/><path d="M79 63h44v36h-44v-36z" fill="#222"/><path stroke="#B4B4B4" stroke-width="4" d="M88 72h50v42h-50z"/></g></g></svg>
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path d="M0 0h200v200h-200v-200z" fill="#222"/><g><path stroke="#B4B4B4" stroke-width="4" d="M68 52h50v42h-50z"/><path d="M79 63h44v36h-44v-36z" fill="#222"/><path stroke="#B4B4B4" stroke-width="4" d="M88 72h50v42h-50z"/></g></g></svg>

Before

Width:  |  Height:  |  Size: 557 B

After

Width:  |  Height:  |  Size: 337 B

@ -1 +1 @@
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns"><title>Group</title><desc>Created with Sketch.</desc><g sketch:type="MSLayerGroup" fill="none"><path d="M0 0h200v200h-200v-200z" id="Shape" fill="#222" sketch:type="MSShapeGroup"/><path d="M100.5 49c-10.45 0-19 8.614-19 19.143v9.571h-9.5v38.286h57v-38.286h-9.5v-9.571c0-10.529-8.55-19.143-19-19.143zm0 9.571c5.32 0 9.5 4.211 9.5 9.571v9.571h-19v-9.571c0-5.36 4.18-9.571 9.5-9.571z" fill="#B4B4B4" sketch:type="MSShapeGroup"/></g></svg>
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg"><g fill="none"><path d="M0 0h200v200h-200v-200z" id="Shape" fill="#222"/><path d="M100.5 49c-10.45 0-19 8.614-19 19.143v9.571h-9.5v38.286h57v-38.286h-9.5v-9.571c0-10.529-8.55-19.143-19-19.143zm0 9.571c5.32 0 9.5 4.211 9.5 9.571v9.571h-19v-9.571c0-5.36 4.18-9.571 9.5-9.571z" fill="#B4B4B4"/></g></svg>

Before

Width:  |  Height:  |  Size: 577 B

After

Width:  |  Height:  |  Size: 388 B

@ -32,6 +32,11 @@
"from": "ansi-styles@>=2.1.0 <3.0.0",
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-2.2.0.tgz"
},
"any-promise": {
"version": "1.1.0",
"from": "any-promise@>=1.1.0 <2.0.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.1.0.tgz"
},
"archy": {
"version": "1.0.0",
"from": "archy@>=1.0.0 <2.0.0",
@ -42,6 +47,11 @@
"from": "are-we-there-yet@>=1.1.2 <1.2.0",
"resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.2.tgz"
},
"arr-flatten": {
"version": "1.0.1",
"from": "arr-flatten@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.0.1.tgz"
},
"array-differ": {
"version": "1.0.0",
"from": "array-differ@>=1.0.0 <2.0.0",
@ -67,6 +77,11 @@
"from": "array-uniq@>=1.0.2 <2.0.0",
"resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.2.tgz"
},
"arrify": {
"version": "1.0.1",
"from": "arrify@>=1.0.1 <2.0.0",
"resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz"
},
"asn1": {
"version": "0.2.3",
"from": "asn1@>=0.2.3 <0.3.0",
@ -341,8 +356,8 @@
"from": "basiccontext@>=3.5.1 <4.0.0"
},
"basicmodal": {
"version": "3.3.3",
"from": "basicmodal@>=3.3.3 <4.0.0"
"version": "3.3.4",
"from": "basicmodal@>=3.3.4 <4.0.0"
},
"beeper": {
"version": "1.1.0",
@ -751,6 +766,18 @@
"from": "get-stdin@>=4.0.1 <5.0.0",
"resolved": "https://registry.npmjs.org/get-stdin/-/get-stdin-4.0.1.tgz"
},
"get-value": {
"version": "1.3.1",
"from": "get-value@>=1.1.5 <2.0.0",
"resolved": "https://registry.npmjs.org/get-value/-/get-value-1.3.1.tgz",
"dependencies": {
"lazy-cache": {
"version": "0.2.7",
"from": "lazy-cache@>=0.2.4 <0.3.0",
"resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-0.2.7.tgz"
}
}
},
"glob": {
"version": "5.0.15",
"from": "glob@>=5.0.0 <5.1.0",
@ -840,6 +867,18 @@
"from": "graceful-readlink@>=1.0.0",
"resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz"
},
"group-array": {
"version": "0.3.0",
"from": "group-array@>=0.3.0 <0.4.0",
"resolved": "https://registry.npmjs.org/group-array/-/group-array-0.3.0.tgz",
"dependencies": {
"kind-of": {
"version": "2.0.1",
"from": "kind-of@>=2.0.0 <3.0.0",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-2.0.1.tgz"
}
}
},
"gulp": {
"version": "3.9.1",
"from": "gulp@>=3.9.1 <4.0.0",
@ -880,9 +919,9 @@
}
},
"gulp-inject": {
"version": "3.0.0",
"from": "gulp-inject@>=3.0.0 <4.0.0",
"resolved": "https://registry.npmjs.org/gulp-inject/-/gulp-inject-3.0.0.tgz"
"version": "4.0.0",
"from": "gulp-inject@>=4.0.0 <5.0.0",
"resolved": "https://registry.npmjs.org/gulp-inject/-/gulp-inject-4.0.0.tgz"
},
"gulp-load-plugins": {
"version": "1.2.0",
@ -1074,6 +1113,11 @@
"from": "is-builtin-module@>=1.0.0 <2.0.0",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz"
},
"is-extendable": {
"version": "0.1.1",
"from": "is-extendable@>=0.1.1 <0.2.0",
"resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz"
},
"is-finite": {
"version": "1.0.1",
"from": "is-finite@>=1.0.0 <2.0.0",
@ -1140,9 +1184,9 @@
"resolved": "https://registry.npmjs.org/jodid25519/-/jodid25519-1.0.2.tgz"
},
"jquery": {
"version": "2.2.1",
"from": "jquery@>=2.2.1 <3.0.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.1.tgz"
"version": "2.2.3",
"from": "jquery@>=2.2.3 <3.0.0",
"resolved": "https://registry.npmjs.org/jquery/-/jquery-2.2.3.tgz"
},
"js-base64": {
"version": "2.1.9",
@ -1466,6 +1510,11 @@
"from": "node-uuid@>=1.4.7 <1.5.0",
"resolved": "https://registry.npmjs.org/node-uuid/-/node-uuid-1.4.7.tgz"
},
"noncharacters": {
"version": "1.1.0",
"from": "noncharacters@>=1.1.0 <2.0.0",
"resolved": "https://registry.npmjs.org/noncharacters/-/noncharacters-1.1.0.tgz"
},
"nopt": {
"version": "3.0.6",
"from": "nopt@>=2.0.0 <3.0.0||>=3.0.0 <4.0.0",
@ -1856,6 +1905,11 @@
"from": "stream-consume@>=0.1.0 <0.2.0",
"resolved": "https://registry.npmjs.org/stream-consume/-/stream-consume-0.1.0.tgz"
},
"stream-to-array": {
"version": "2.3.0",
"from": "stream-to-array@>=2.3.0 <3.0.0",
"resolved": "https://registry.npmjs.org/stream-to-array/-/stream-to-array-2.3.0.tgz"
},
"string_decoder": {
"version": "0.10.31",
"from": "string_decoder@>=0.10.0 <0.11.0",

@ -16,18 +16,18 @@
"dependencies": {
"babel-preset-es2015": "^6.6.0",
"basiccontext": "^3.5.1",
"basicmodal": "^3.3.3",
"basicmodal": "^3.3.4",
"gulp": "^3.9.1",
"gulp-autoprefixer": "3.1.0",
"gulp-babel": "^6.1.2",
"gulp-concat": "^2.6.0",
"gulp-inject": "^3.0.0",
"gulp-inject": "^4.0.0",
"gulp-load-plugins": "^1.2.0",
"gulp-minify-css": "^1.2.4",
"gulp-rimraf": "^0.2.0",
"gulp-sass": "^2.2.0",
"gulp-uglify": "^1.5.3",
"jquery": "^2.2.1",
"jquery": "^2.2.3",
"mousetrap": "^1.5.3"
}
}

@ -116,9 +116,6 @@ album.add = function() {
api.post('Album::add', params, function(data) {
// Avoid first album to be true
if (data===true) data = 1
if (data!==false && isNumber(data)) {
albums.refresh()
lychee.goto(data)
@ -512,26 +509,20 @@ album.setPublic = function(albumID, modal, e) {
album.share = function(service) {
let link = ''
let url = location.href
switch (service) {
case 'twitter':
link = `https://twitter.com/share?url=${ encodeURI(url) }`
window.open(`https://twitter.com/share?url=${ encodeURI(url) }`)
break
case 'facebook':
link = `http://www.facebook.com/sharer.php?u=${ encodeURI(url) }&t=${ encodeURI(album.json.title) }`
window.open(`http://www.facebook.com/sharer.php?u=${ encodeURI(url) }&t=${ encodeURI(album.json.title) }`)
break
case 'mail':
link = `mailto:?subject=${ encodeURI(album.json.title) }&body=${ encodeURI(url) }`
break
default:
link = ''
location.href = `mailto:?subject=${ encodeURI(album.json.title) }&body=${ encodeURI(url) }`
break
}
if (link!=='') location.href = link
}
album.getArchive = function(albumID) {

@ -26,15 +26,6 @@ api.post = function(fn, params, callback) {
return false
}
// Convert 1 to true and an empty string to false
if (data==='true') data = true
else if (data==='false') data = false
// Convert to JSON if string start with '{' and ends with '}'
if (typeof data==='string' && data.substring(0, 1)==='{' && data.substring(data.length - 1, data.length)==='}') {
data = $.parseJSON(data)
}
callback(data)
}
@ -49,7 +40,7 @@ api.post = function(fn, params, callback) {
type: 'POST',
url: api.path,
data: params,
dataType: 'text',
dataType: 'json',
success,
error
})

@ -304,10 +304,10 @@ contextMenu.sharePhoto = function(photoID, e) {
{ title: build.iconic('twitter', iconClass) + 'Twitter', fn: () => photo.share(photoID, 'twitter') },
{ title: build.iconic('facebook', iconClass) + 'Facebook', fn: () => photo.share(photoID, 'facebook') },
{ title: build.iconic('envelope-closed') + 'Mail', fn: () => photo.share(photoID, 'mail') },
{ title: build.iconic('dropbox', iconClass) + 'Dropbox', fn: () => photo.share(photoID, 'dropbox') },
{ title: build.iconic('dropbox', iconClass) + 'Dropbox', visible: lychee.publicMode===false, fn: () => photo.share(photoID, 'dropbox') },
{ title: build.iconic('link-intact') + 'Direct Link', fn: () => window.open(photo.getDirectLink()) },
{ },
{ title: build.iconic('ban') + 'Make Private', fn: () => photo.setPublic(photoID) }
{ visible: lychee.publicMode===false },
{ title: build.iconic('ban') + 'Make Private', visible: lychee.publicMode===false, fn: () => photo.setPublic(photoID) }
]
basicContext.show(items, e.originalEvent)
@ -325,9 +325,9 @@ contextMenu.shareAlbum = function(albumID, e) {
{ title: build.iconic('twitter', iconClass) + 'Twitter', fn: () => album.share('twitter') },
{ title: build.iconic('facebook', iconClass) + 'Facebook', fn: () => album.share('facebook') },
{ title: build.iconic('envelope-closed') + 'Mail', fn: () => album.share('mail') },
{ },
{ title: build.iconic('pencil') + 'Edit Sharing', fn: () => album.setPublic(albumID, true, e) },
{ title: build.iconic('ban') + 'Make Private', fn: () => album.setPublic(albumID, false) }
{ visible: lychee.publicMode===false },
{ title: build.iconic('pencil') + 'Edit Sharing', visible: lychee.publicMode===false, fn: () => album.setPublic(albumID, true, e) },
{ title: build.iconic('ban') + 'Make Private', visible: lychee.publicMode===false, fn: () => album.setPublic(albumID, false) }
]
basicContext.show(items, e.originalEvent)

@ -236,8 +236,14 @@ lychee.setTitle = function(title, editable) {
lychee.setMode = function(mode) {
$('#button_settings, #button_trash_album, #button_share_album, .button_add, .header__divider').remove()
$('#button_trash, #button_move, #button_share, #button_star').remove()
$('#button_settings, #button_trash_album, .button_add, .header__divider').remove()
$('#button_trash, #button_move, #button_star').remove()
$('#button_share, #button_share_album')
.removeClass('button--eye')
.addClass('button--share')
.find('use')
.attr('xlink:href', '#share')
$(document)
.off('click', '.header__title--editable')

@ -610,18 +610,17 @@ photo.deleteTag = function(photoID, index) {
photo.share = function(photoID, service) {
let link = ''
let url = photo.getViewLink(photoID)
switch (service) {
case 'twitter':
link = `https://twitter.com/share?url=${ encodeURI(url) }`
window.open(`https://twitter.com/share?url=${ encodeURI(url) }`)
break
case 'facebook':
link = `http://www.facebook.com/sharer.php?u=${ encodeURI(url) }&t=${ encodeURI(photo.json.title) }`
window.open(`http://www.facebook.com/sharer.php?u=${ encodeURI(url) }&t=${ encodeURI(photo.json.title) }`)
break
case 'mail':
link = `mailto:?subject=${ encodeURI(photo.json.title) }&body=${ encodeURI(url) }`
location.href = `mailto:?subject=${ encodeURI(photo.json.title) }&body=${ encodeURI(url) }`
break
case 'dropbox':
lychee.loadDropbox(function() {
@ -629,13 +628,8 @@ photo.share = function(photoID, service) {
Dropbox.save(photo.getDirectLink(), filename)
})
break
default:
link = ''
break
}
if (link!=='') location.href = link
}
photo.getArchive = function(photoID) {

@ -36,7 +36,7 @@ settings.createConfig = function() {
if (data!==true) {
// Connection failed
if (data.indexOf('Warning: Connection failed!')!==-1) {
if (data==='Warning: Connection failed!') {
basicModal.show({
body: '<p>Unable to connect to host database because access was denied. Double-check your host, username and password and ensure that access from your current location is permitted.</p>',
@ -53,7 +53,7 @@ settings.createConfig = function() {
}
// Creation failed
if (data.indexOf('Warning: Creation failed!')!==-1) {
if (data==='Warning: Creation failed!') {
basicModal.show({
body: '<p>Unable to create the database. Double-check your host, username and password and ensure that the specified user has the rights to modify and add content to the database.</p>',
@ -70,7 +70,7 @@ settings.createConfig = function() {
}
// Could not create file
if (data.indexOf('Warning: Could not create file!')!==-1) {
if (data==='Warning: Could not create file!') {
basicModal.show({
body: "<p>Unable to save this configuration. Permission denied in <b>'data/'</b>. Please set the read, write and execute rights for others in <b>'data/'</b> and <b>'uploads/'</b>. Take a look at the readme for more information.</p>",

@ -93,13 +93,22 @@ upload.start = {
xhr.onload = function() {
let data = null
let wait = false
let errorText = ''
const isNumber = (n) => (!isNaN(parseFloat(n)) && isFinite(n))
try {
data = JSON.parse(xhr.responseText)
} catch(e) {
data = ''
}
file.ready = true
// Set status
if (xhr.status===200 && xhr.responseText==='true') {
if (xhr.status===200 && isNumber(data)) {
// Success
$('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') .status')
@ -108,9 +117,9 @@ upload.start = {
} else {
if (xhr.responseText.substr(0, 6)==='Error:') {
if (data.substr(0, 6)==='Error:') {
errorText = xhr.responseText.substr(6) + ' Please take a look at the console of your browser for further details.'
errorText = data.substr(6) + ' Please take a look at the console of your browser for further details.'
error = true
// Error Status
@ -118,9 +127,12 @@ upload.start = {
.html('Failed')
.addClass('error')
} else if (xhr.responseText.substr(0, 8)==='Warning:') {
// Throw error
if (error===true) lychee.error('Upload failed. Server returned an error!', xhr, data)
} else if (data.substr(0, 8)==='Warning:') {
errorText = xhr.responseText.substr(8)
errorText = data.substr(8)
warning = true
// Warning Status
@ -128,6 +140,9 @@ upload.start = {
.html('Skipped')
.addClass('warning')
// Throw error
if (error===true) lychee.error('Upload failed. Server returned a warning!', xhr, data)
} else {
errorText = 'Server returned an unknown response. Please take a look at the console of your browser for further details.'
@ -138,15 +153,15 @@ upload.start = {
.html('Failed')
.addClass('error')
// Throw error
if (error===true) lychee.error('Upload failed. Server returned an unkown error!', xhr, data)
}
$('.basicModal .rows .row:nth-child(' + (file.num + 1) + ') p.notice')
.html(errorText)
.show()
// Throw error
if (error===true) lychee.error('Upload failed. Server returned the status code ' + xhr.status + '!', xhr, xhr.responseText)
}
// Check if there are file which are not finished
@ -206,8 +221,8 @@ upload.start = {
for (let i = 0; i < files.length; i++) {
files[i].num = i
files[i].ready = false
files[i].num = i
files[i].ready = false
if (i < files.length-1) files[i].next = files[i + 1]
else files[i].next = null
@ -242,7 +257,7 @@ upload.start = {
basicModal.close()
files[0] = {
name : data.link
name: data.link
}
upload.show('Importing URL', files, function() {
@ -321,7 +336,7 @@ upload.start = {
let files = []
files[0] = {
name : data.path
name: data.path
}
upload.show('Importing from server', files, function() {

@ -3,21 +3,12 @@
* @copyright 2015 by Tobias Reich
*/
// Sub-implementation of Lychee -------------------------------------------------------------- //
// Sub-implementation of lychee -------------------------------------------------------------- //
let lychee = {}
lychee.content = $('.content')
lychee.getEventName = function() {
let touchendSupport = (/Android|iPhone|iPad|iPod/i).test(navigator.userAgent || navigator.vendor || window.opera) && ('ontouchend' in document.documentElement)
let eventName = (touchendSupport===true ? 'touchend' : 'click')
return eventName
}
lychee.escapeHTML = function(html = '') {
// Ensure that html is a string
@ -69,31 +60,76 @@ lychee.html = function(literalSections, ...substs) {
}
// Sub-implementation of photo -------------------------------------------------------------- //
let photo = {}
photo.share = function(photoID, service) {
let url = location.toString()
switch (service) {
case 'twitter':
window.open(`https://twitter.com/share?url=${ encodeURI(url) }`)
break
case 'facebook':
window.open(`http://www.facebook.com/sharer.php?u=${ encodeURI(url) }`)
break
case 'mail':
location.href = `mailto:?subject=&body=${ encodeURI(url) }`
break
}
}
photo.getDirectLink = function() {
return $('#imageview img').attr('src').replace(/"/g,'').replace(/url\(|\)$/ig, '')
}
// Sub-implementation of contextMenu -------------------------------------------------------------- //
let contextMenu = {}
contextMenu.sharePhoto = function(photoID, e) {
let iconClass = 'ionicons'
let items = [
{ title: build.iconic('twitter', iconClass) + 'Twitter', fn: () => photo.share(photoID, 'twitter') },
{ title: build.iconic('facebook', iconClass) + 'Facebook', fn: () => photo.share(photoID, 'facebook') },
{ title: build.iconic('envelope-closed') + 'Mail', fn: () => photo.share(photoID, 'mail') },
{ title: build.iconic('link-intact') + 'Direct Link', fn: () => window.open(photo.getDirectLink(), '_newtab') }
]
basicContext.show(items, e.originalEvent)
}
// Main -------------------------------------------------------------- //
let loadingBar = { show() {}, hide() {} },
imageview = $('#imageview')
let loadingBar = { show() {}, hide() {} }
let imageview = $('#imageview')
$(document).ready(function() {
// Event Name
let eventName = lychee.getEventName()
// Save ID of photo
let photoID = gup('p')
// Set API error handler
api.onError = error
// Infobox
header.dom('#button_info').on(eventName, sidebar.toggle)
// Direct Link
header.dom('#button_direct').on(eventName, function() {
let link = $('#imageview img').attr('src').replace(/"/g,'').replace(/url\(|\)$/ig, '')
window.open(link, '_newtab')
// Share
header.dom('#button_share').on('click', function(e) {
contextMenu.sharePhoto(photoID, e)
})
loadPhotoInfo(gup('p'))
// Infobox
header.dom('#button_info').on('click', sidebar.toggle)
// Load photo
loadPhotoInfo(photoID)
})

@ -12,7 +12,6 @@
&__item {
margin-bottom: 2px;
font-size: 14px;
text-shadow: $shadowLight;
&--separator {
margin: 4px 0;

@ -57,10 +57,10 @@
width: 200px;
height: 200px;
background: #222;
color: #222;
box-shadow: 0 2px 5px black(.5);
border: 1px solid white(.5);
transition: opacity .3s ease-out, transform .3s ease-out, border-color .3s ease-out;
will-change: transform;
}
&:hover img,
@ -146,7 +146,6 @@
margin: 0 5px 0 0;
width: 8px;
height: 8px;
filter: drop-shadow(0 1px 3px black(.4));
}
.album img[data-overlay='false'] + .overlay h1,
@ -185,7 +184,6 @@
fill: #fff;
width: 16px;
height: 16px;
filter: drop-shadow($shadowLight);
}
}
@ -225,7 +223,6 @@
left: 50%;
padding-top: 20px;
color: white(.35);
text-shadow: 0 -1px 0 black(.4);
text-align: center;
transform: translateX(-50%) translateY(-50%);
@ -234,7 +231,6 @@
margin: 0 0 10px;
width: 50px;
height: 50px;
filter: drop-shadow(0 -1px 0 black(.4));
}
p {

@ -95,6 +95,8 @@
&--eye.active .iconic { fill: #ff9737; }
&--share .iconic { height: 18px; }
&--info.active .iconic { fill: $colorBlue; }
}

@ -27,7 +27,6 @@
width: auto;
height: auto;
transition: top .3s, right .3s, bottom .3s, left .3s, max-width .3s, max-height .3s;
will-change: transform;
animation-name: zoomIn;
animation-duration: .3s;
@ -105,7 +104,6 @@
.iconic {
fill: white(.8);
filter: drop-shadow(0 1px 0 black(.4));
}
}

@ -26,7 +26,6 @@
color: white(.9);
font-size: 14px;
text-align: left;
text-shadow: $shadow;
line-height: 20px;
b {
@ -56,7 +55,6 @@
padding: 13px 0 15px;
background: black(.02);
color: white(.5);
text-shadow: $shadow;
border-top: 1px solid black(.2);
box-shadow: inset 0 1px 0 white(.02);
cursor: default;
@ -85,7 +83,6 @@
width: 100%;
background-color: transparent;
color: #fff;
text-shadow: $shadow;
border: none;
// Do not use rgba() for border-bottom
// to avoid a blurry line in Safari on non-retina screens
@ -116,7 +113,6 @@
color: white(1);
font-size: 14px;
font-weight: 700;
text-shadow: $shadow;
}
label input {
@ -258,7 +254,6 @@
color: #fff;
font-size: 16px;
font-weight: bold;
text-shadow: $shadow;
text-align: center;
}

@ -92,6 +92,7 @@
table {
float: left;
margin: 10px 0 15px 20px;
width: calc(100% - 20px);
}
table tr td {

@ -12,8 +12,7 @@
}
// Properties -------------------------------------------------------------- //
$shadowLight : 0 -1px 0 black(.1);
$shadow : 0 -1px 0 black(.2);
$shadow: 0 -1px 0 black(.2);
// Colors ------------------------------------------------------------------ //
$colorBlue : #2293EC;

@ -48,12 +48,12 @@
<a class="header__title"></a>
<a class="button button--share" id="button_share" title="Share Photo">
<svg class="iconic"><use xlink:href="#share"></use></svg>
</a>
<a class="button button--info" id="button_info" title="About Photo">
<svg class="iconic"><use xlink:href="#info"></use></svg>
</a>
<a class="button" id="button_direct" title="Direct Link">
<svg class="iconic"><use xlink:href="#link-intact"></use></svg>
</a>
</div>

Loading…
Cancel
Save