Rework file picker UI, add Unsplash integration (close #23)
This commit is contained in:
parent
9160105136
commit
4fc40bb9f5
10
action.php
10
action.php
@ -322,6 +322,16 @@ switch ($VARS['action']) {
|
|||||||
}
|
}
|
||||||
returnToSender("file_deleted");
|
returnToSender("file_deleted");
|
||||||
break;
|
break;
|
||||||
|
case "unsplash_download":
|
||||||
|
Crew\Unsplash\HttpClient::init([
|
||||||
|
'applicationId' => UNSPLASH_ACCESSKEY,
|
||||||
|
'secret' => UNSPLASH_SECRETKEY,
|
||||||
|
'utmSource' => UNSPLASH_UTMSOURCE
|
||||||
|
]);
|
||||||
|
Crew\Unsplash\Photo::find($VARS['imageid'])->download();
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
exit(json_encode(["status" => "OK"]));
|
||||||
|
break;
|
||||||
case "signout":
|
case "signout":
|
||||||
session_destroy();
|
session_destroy();
|
||||||
header('Location: index.php');
|
header('Location: index.php');
|
||||||
|
@ -5,7 +5,8 @@
|
|||||||
"require": {
|
"require": {
|
||||||
"catfan/medoo": "^1.5",
|
"catfan/medoo": "^1.5",
|
||||||
"guzzlehttp/guzzle": "^6.2",
|
"guzzlehttp/guzzle": "^6.2",
|
||||||
"geoip2/geoip2": "~2.0"
|
"geoip2/geoip2": "~2.0",
|
||||||
|
"unsplash/unsplash": "^2.4"
|
||||||
},
|
},
|
||||||
"license": "MPL-2.0",
|
"license": "MPL-2.0",
|
||||||
"authors": [
|
"authors": [
|
||||||
|
230
composer.lock
generated
230
composer.lock
generated
@ -4,8 +4,8 @@
|
|||||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||||
"This file is @generated automatically"
|
"This file is @generated automatically"
|
||||||
],
|
],
|
||||||
"hash": "a05b32c4ba7d59c1fa2dc87ef59b238d",
|
"hash": "14eefa1d98fa62ca2f2fe52de606868c",
|
||||||
"content-hash": "2b47ec7e64412178507c9e9362debc56",
|
"content-hash": "e9f318b9d8bd1dfa6c7fb56c820d1910",
|
||||||
"packages": [
|
"packages": [
|
||||||
{
|
{
|
||||||
"name": "catfan/medoo",
|
"name": "catfan/medoo",
|
||||||
@ -355,6 +355,125 @@
|
|||||||
],
|
],
|
||||||
"time": "2017-03-20 17:10:46"
|
"time": "2017-03-20 17:10:46"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "hughbertd/oauth2-unsplash",
|
||||||
|
"version": "1.0.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/HughbertD/oauth2-unsplash.git",
|
||||||
|
"reference": "f451f4a49dca4027f6edaa850d2fccdfa8721bfe"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/HughbertD/oauth2-unsplash/zipball/f451f4a49dca4027f6edaa850d2fccdfa8721bfe",
|
||||||
|
"reference": "f451f4a49dca4027f6edaa850d2fccdfa8721bfe",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"league/oauth2-client": ">=1.0",
|
||||||
|
"php": ">=5.6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "~0.9",
|
||||||
|
"phpunit/phpunit": "~5.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Unsplash\\OAuth2\\Client\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Hugh Downer",
|
||||||
|
"email": "hugh.downer@gmail.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Unsplash OAuth 2.0 Client Provider for The PHP League OAuth2-Client",
|
||||||
|
"keywords": [
|
||||||
|
"Authentication",
|
||||||
|
"SSO",
|
||||||
|
"Unsplash",
|
||||||
|
"authorization",
|
||||||
|
"identity",
|
||||||
|
"idp",
|
||||||
|
"oauth",
|
||||||
|
"oauth2",
|
||||||
|
"single sign on"
|
||||||
|
],
|
||||||
|
"time": "2017-12-14 13:08:42"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "league/oauth2-client",
|
||||||
|
"version": "2.3.0",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/thephpleague/oauth2-client.git",
|
||||||
|
"reference": "aa2e3df188f0bfd87f7880cc880e906e99923580"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/thephpleague/oauth2-client/zipball/aa2e3df188f0bfd87f7880cc880e906e99923580",
|
||||||
|
"reference": "aa2e3df188f0bfd87f7880cc880e906e99923580",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/guzzle": "^6.0",
|
||||||
|
"paragonie/random_compat": "^1|^2",
|
||||||
|
"php": "^5.6|^7.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"eloquent/liberator": "^2.0",
|
||||||
|
"eloquent/phony-phpunit": "^1.0|^3.0",
|
||||||
|
"jakub-onderka/php-parallel-lint": "^0.9.2",
|
||||||
|
"phpunit/phpunit": "^5.7|^6.0",
|
||||||
|
"squizlabs/php_codesniffer": "^2.3|^3.0"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"extra": {
|
||||||
|
"branch-alias": {
|
||||||
|
"dev-2.x": "2.0.x-dev"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"League\\OAuth2\\Client\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Alex Bilbie",
|
||||||
|
"email": "hello@alexbilbie.com",
|
||||||
|
"homepage": "http://www.alexbilbie.com",
|
||||||
|
"role": "Developer"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Woody Gilk",
|
||||||
|
"homepage": "https://github.com/shadowhand",
|
||||||
|
"role": "Contributor"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "OAuth 2.0 Client Library",
|
||||||
|
"keywords": [
|
||||||
|
"Authentication",
|
||||||
|
"SSO",
|
||||||
|
"authorization",
|
||||||
|
"identity",
|
||||||
|
"idp",
|
||||||
|
"oauth",
|
||||||
|
"oauth2",
|
||||||
|
"single sign on"
|
||||||
|
],
|
||||||
|
"time": "2018-01-13 05:27:58"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "maxmind-db/reader",
|
"name": "maxmind-db/reader",
|
||||||
"version": "v1.3.0",
|
"version": "v1.3.0",
|
||||||
@ -457,6 +576,54 @@
|
|||||||
"homepage": "https://github.com/maxmind/web-service-common-php",
|
"homepage": "https://github.com/maxmind/web-service-common-php",
|
||||||
"time": "2018-02-12 22:31:54"
|
"time": "2018-02-12 22:31:54"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "paragonie/random_compat",
|
||||||
|
"version": "v2.0.12",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/paragonie/random_compat.git",
|
||||||
|
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/paragonie/random_compat/zipball/258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
|
||||||
|
"reference": "258c89a6b97de7dfaf5b8c7607d0478e236b04fb",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"php": ">=5.2.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"phpunit/phpunit": "4.*|5.*"
|
||||||
|
},
|
||||||
|
"suggest": {
|
||||||
|
"ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"files": [
|
||||||
|
"lib/random.php"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Paragon Initiative Enterprises",
|
||||||
|
"email": "security@paragonie.com",
|
||||||
|
"homepage": "https://paragonie.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
|
||||||
|
"keywords": [
|
||||||
|
"csprng",
|
||||||
|
"pseudorandom",
|
||||||
|
"random"
|
||||||
|
],
|
||||||
|
"time": "2018-04-04 21:24:14"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "psr/http-message",
|
"name": "psr/http-message",
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
@ -506,6 +673,65 @@
|
|||||||
"response"
|
"response"
|
||||||
],
|
],
|
||||||
"time": "2016-08-06 14:39:51"
|
"time": "2016-08-06 14:39:51"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "unsplash/unsplash",
|
||||||
|
"version": "2.4.3",
|
||||||
|
"source": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/unsplash/unsplash-php.git",
|
||||||
|
"reference": "7c6fed642cf4234545624a1263d57c9cb0970fbf"
|
||||||
|
},
|
||||||
|
"dist": {
|
||||||
|
"type": "zip",
|
||||||
|
"url": "https://api.github.com/repos/unsplash/unsplash-php/zipball/7c6fed642cf4234545624a1263d57c9cb0970fbf",
|
||||||
|
"reference": "7c6fed642cf4234545624a1263d57c9cb0970fbf",
|
||||||
|
"shasum": ""
|
||||||
|
},
|
||||||
|
"require": {
|
||||||
|
"guzzlehttp/guzzle": "^6.3.0",
|
||||||
|
"hughbertd/oauth2-unsplash": ">=1.0.3",
|
||||||
|
"league/oauth2-client": ">=1.4.2",
|
||||||
|
"php": ">=5.6.0"
|
||||||
|
},
|
||||||
|
"require-dev": {
|
||||||
|
"mockery/mockery": "~0.9.0",
|
||||||
|
"php-vcr/php-vcr": "dev-master",
|
||||||
|
"php-vcr/phpunit-testlistener-vcr": "*",
|
||||||
|
"phpunit/phpunit": "~5.1",
|
||||||
|
"satooshi/php-coveralls": "dev-master",
|
||||||
|
"vlucas/phpdotenv": "dev-master"
|
||||||
|
},
|
||||||
|
"type": "library",
|
||||||
|
"autoload": {
|
||||||
|
"psr-4": {
|
||||||
|
"Crew\\Unsplash\\": "src/"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"notification-url": "https://packagist.org/downloads/",
|
||||||
|
"license": [
|
||||||
|
"MIT"
|
||||||
|
],
|
||||||
|
"authors": [
|
||||||
|
{
|
||||||
|
"name": "Charles Lalonde",
|
||||||
|
"email": "charles@pickcrew.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Hugh Downer",
|
||||||
|
"email": "hugh.downer@gmail.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Aaron Klaassen",
|
||||||
|
"email": "aaron@unsplash.com"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "Luke Chesser",
|
||||||
|
"email": "luke@unsplash.com"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"description": "Wrapper to access the Unsplash API and photo library",
|
||||||
|
"time": "2018-03-30 17:45:15"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"packages-dev": [],
|
"packages-dev": [],
|
||||||
|
@ -127,5 +127,10 @@ define("STRINGS", [
|
|||||||
"navbar title" => "Page title for menu",
|
"navbar title" => "Page title for menu",
|
||||||
"navbar position" => "Menu position (drag to change position):",
|
"navbar position" => "Menu position (drag to change position):",
|
||||||
"remove image" => "Remove image",
|
"remove image" => "Remove image",
|
||||||
"site footer links" => "Site Footer Links"
|
"site footer links" => "Site Footer Links",
|
||||||
|
"uploaded files" => "Uploaded Files",
|
||||||
|
"stock photos" => "Free Stock Photos",
|
||||||
|
"load more" => "Load more",
|
||||||
|
"search images" => "Search images",
|
||||||
|
"x results" => "{results} results",
|
||||||
]);
|
]);
|
@ -23,110 +23,60 @@ if (isset($VARS['type']) && $VARS['type'] != "") {
|
|||||||
$type = explode("|", $VARS['type']);
|
$type = explode("|", $VARS['type']);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($folder == "/") {
|
$enableunsplash = ENABLE_UNSPLASH;
|
||||||
$folder = "";
|
if (count($type) > 0 && !in_array("image", $type)) {
|
||||||
|
$enableunsplash = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
$fullpath = $base . $folder;
|
|
||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="mb-2">
|
|
||||||
<nav aria-label="breadcrumb" class="my-auto">
|
|
||||||
<ol class="breadcrumb m-0">
|
|
||||||
<?php
|
<?php
|
||||||
$pathparts = explode("/", "$folder");
|
if ($enableunsplash) {
|
||||||
$pstr = "";
|
?>
|
||||||
for ($i = 0; $i < count($pathparts); $i++) {
|
<ul class="nav nav-tabs" id="fileBrowserTabs" role="tablist">
|
||||||
$p = $pathparts[$i];
|
<li class="nav-item">
|
||||||
$pstr .= "/$p";
|
<a class="nav-link active" id="uploadedFilesTabBtn" data-toggle="tab" href="#uploadedFilesTab">
|
||||||
$pstr = "/" . ltrim($pstr, "/");
|
<i class="fas fa-folder-open"></i> <?php lang('uploaded files'); ?>
|
||||||
if ($i == 0) {
|
</a>
|
||||||
$p = "<span class=\"fas fa-home\"></span>";
|
</li>
|
||||||
}
|
<li class="nav-item">
|
||||||
if ($i == count($pathparts) - 1) {
|
<a class="nav-link" id="unsplashTabBtn" data-toggle="tab" href="#unsplashTab">
|
||||||
echo "\t<li aria-current=\"page\" class=\"breadcrumb-item active\">$p</li>";
|
<i class="fas fa-image"></i> <?php lang('stock photos'); ?>
|
||||||
} else {
|
</a>
|
||||||
echo "\t<li class=\"breadcrumb-item\"><span class=\"filepicker-item\" data-type=\"dir\" data-path=\"$pstr\">$p</a></li>";
|
</li>
|
||||||
}
|
</ul>
|
||||||
echo "\n";
|
<?php
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</ol>
|
<div class="tab-content" id="fileBrowserTabContent">
|
||||||
</nav>
|
<div class="tab-pane fade show active" id="uploadedFilesTab" role="tabpanel" aria-labelledby="uploadedFilesTabBtn">
|
||||||
|
<div class="card" id="uploadedFilesBin">
|
||||||
</div>
|
</div>
|
||||||
<div class="list-group">
|
|
||||||
<?php
|
|
||||||
$files = scandir($fullpath);
|
|
||||||
$count = 0;
|
|
||||||
foreach ($files as $f) {
|
|
||||||
if (strpos($f, '.') !== 0) {
|
|
||||||
$count++;
|
|
||||||
$link = "$folder/$f";
|
|
||||||
$target = "_BLANK";
|
|
||||||
$isdir = false;
|
|
||||||
$icon = "fas fa-file";
|
|
||||||
if (is_dir($fullpath . "/" . $f)) {
|
|
||||||
$isdir = true;
|
|
||||||
$link = "app.php?page=files&path=$folder/$f";
|
|
||||||
$icon = "fas fa-folder";
|
|
||||||
$target = "";
|
|
||||||
} else {
|
|
||||||
$link = "public/file.php?file=$folder/$f";
|
|
||||||
$extension = pathinfo($fullpath . "/" . $f)['extension'];
|
|
||||||
// If we don't have an extension, try using the whole filename
|
|
||||||
if ($extension == "") {
|
|
||||||
$extension = $f;
|
|
||||||
}
|
|
||||||
$mimetype = "application/octet-stream";
|
|
||||||
// Lookup mimetype from extension
|
|
||||||
if (array_key_exists($extension, $EXT2MIME)) {
|
|
||||||
$mimetype = $EXT2MIME[$extension];
|
|
||||||
}
|
|
||||||
|
|
||||||
$found = true;
|
|
||||||
if (count($type) > 0) {
|
|
||||||
$found = false;
|
|
||||||
foreach ($type as $t) {
|
|
||||||
if (strpos($mimetype, $t) === 0) {
|
|
||||||
$found = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!$found) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Lookup icon from mimetype
|
|
||||||
if (array_key_exists($mimetype, $MIMEICONS)) {
|
|
||||||
$icon = $MIMEICONS[$mimetype];
|
|
||||||
} else { // Allow broad generic <format>/other icons
|
|
||||||
$mimefirst = explode("/", $mimetype, 2)[0];
|
|
||||||
if (array_key_exists($mimefirst . "/other", $MIMEICONS)) {
|
|
||||||
$icon = $MIMEICONS[$mimetype];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<div
|
|
||||||
class="list-group-item filepicker-item"
|
|
||||||
data-type="<?php echo $isdir ? "dir" : "file" ?>"
|
|
||||||
data-path="<?php echo "$folder/$f"; ?>"
|
|
||||||
data-file="<?php echo $f; ?>">
|
|
||||||
<span class="<?php echo $icon; ?> fa-fw"></span> <?php echo $f; ?>
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<?php
|
<?php
|
||||||
}
|
if ($enableunsplash) {
|
||||||
}
|
|
||||||
if ($count == 0) {
|
|
||||||
?>
|
?>
|
||||||
<div class="list-group-item text-center">
|
<div class="tab-pane fade" id="unsplashTab" role="tabpanel" aria-labelledby="unsplashTabBtn">
|
||||||
<p class="text-muted">
|
<div class="card">
|
||||||
<i class="far fa-folder-open fa-5x fa-fw"></i>
|
<div class="card-body">
|
||||||
</p>
|
<div class="input-group">
|
||||||
<p class="h5 text-muted">
|
<input type="text" class="form-control" id="unsplashSearch" placeholder="<?php lang("search images"); ?>" />
|
||||||
<?php lang("nothing here"); ?>
|
<div class="input-group-append">
|
||||||
</p>
|
<div class="btn btn-primary" id="unsplashSearchBtn">
|
||||||
|
<i class="fas fa-search"></i> <?php lang("search"); ?>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<span id="unsplashResults"></span> <span>via <a href="https://unsplash.com/?utm_source=<?php echo urlencode(UNSPLASH_UTMSOURCE); ?>&utm_medium=referral">Unsplash</a></span>
|
||||||
|
</div>
|
||||||
|
<div id="unsplashPhotoBin" class="px-2 pr-3">
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<button type="button" class="btn btn-primary btn-block" id="unsplashLoadMoreBtn">
|
||||||
|
<?php lang("load more"); ?>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<?php
|
<?php
|
||||||
}
|
}
|
||||||
|
138
lib/filepicker_local.php
Normal file
138
lib/filepicker_local.php
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
<?php
|
||||||
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../required.php';
|
||||||
|
|
||||||
|
dieifnotloggedin();
|
||||||
|
|
||||||
|
include_once __DIR__ . "/../lib/mimetypes.php";
|
||||||
|
|
||||||
|
$base = FILE_UPLOAD_PATH;
|
||||||
|
|
||||||
|
$folder = "";
|
||||||
|
if (isset($VARS['path']) && file_exists($base . $VARS['path']) && strpos(realpath($base . $VARS['path']), FILE_UPLOAD_PATH) === 0) {
|
||||||
|
$folder = $VARS['path'];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Compared to the start of the file mimetype, if it doesn't match the file is
|
||||||
|
// skipped. A type of "image" will match "image/png", "image/jpeg", etc.
|
||||||
|
$type = [];
|
||||||
|
if (isset($VARS['type']) && $VARS['type'] != "") {
|
||||||
|
$type = explode("|", $VARS['type']);
|
||||||
|
}
|
||||||
|
|
||||||
|
$enableunsplash = ENABLE_UNSPLASH;
|
||||||
|
if (count($type) > 0 && !in_array("image", $type)) {
|
||||||
|
$enableunsplash = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($folder == "/") {
|
||||||
|
$folder = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
$fullpath = $base . $folder;
|
||||||
|
?>
|
||||||
|
<div class="mb-2">
|
||||||
|
<nav aria-label="breadcrumb" class="my-auto">
|
||||||
|
<ol class="breadcrumb m-0">
|
||||||
|
<?php
|
||||||
|
$pathparts = explode("/", "$folder");
|
||||||
|
$pstr = "";
|
||||||
|
for ($i = 0; $i < count($pathparts); $i++) {
|
||||||
|
$p = $pathparts[$i];
|
||||||
|
$pstr .= "/$p";
|
||||||
|
$pstr = "/" . ltrim($pstr, "/");
|
||||||
|
if ($i == 0) {
|
||||||
|
$p = "<span class=\"fas fa-home\"></span>";
|
||||||
|
}
|
||||||
|
if ($i == count($pathparts) - 1) {
|
||||||
|
echo "\t<li aria-current=\"page\" class=\"breadcrumb-item active\">$p</li>";
|
||||||
|
} else {
|
||||||
|
echo "\t<li class=\"breadcrumb-item\"><span class=\"filepicker-item\" data-type=\"dir\" data-path=\"$pstr\">$p</a></li>";
|
||||||
|
}
|
||||||
|
echo "\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
<div class="list-group list-group-flush">
|
||||||
|
<?php
|
||||||
|
$files = scandir($fullpath);
|
||||||
|
$count = 0;
|
||||||
|
foreach ($files as $f) {
|
||||||
|
if (strpos($f, '.') !== 0) {
|
||||||
|
$count++;
|
||||||
|
$link = "$folder/$f";
|
||||||
|
$target = "_BLANK";
|
||||||
|
$isdir = false;
|
||||||
|
$icon = "fas fa-file";
|
||||||
|
if (is_dir($fullpath . "/" . $f)) {
|
||||||
|
$isdir = true;
|
||||||
|
$link = "app.php?page=files&path=$folder/$f";
|
||||||
|
$icon = "fas fa-folder";
|
||||||
|
$target = "";
|
||||||
|
} else {
|
||||||
|
$link = "public/file.php?file=$folder/$f";
|
||||||
|
$extension = pathinfo($fullpath . "/" . $f)['extension'];
|
||||||
|
// If we don't have an extension, try using the whole filename
|
||||||
|
if ($extension == "") {
|
||||||
|
$extension = $f;
|
||||||
|
}
|
||||||
|
$mimetype = "application/octet-stream";
|
||||||
|
// Lookup mimetype from extension
|
||||||
|
if (array_key_exists($extension, $EXT2MIME)) {
|
||||||
|
$mimetype = $EXT2MIME[$extension];
|
||||||
|
}
|
||||||
|
|
||||||
|
$found = true;
|
||||||
|
if (count($type) > 0) {
|
||||||
|
$found = false;
|
||||||
|
foreach ($type as $t) {
|
||||||
|
if (strpos($mimetype, $t) === 0) {
|
||||||
|
$found = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!$found) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Lookup icon from mimetype
|
||||||
|
if (array_key_exists($mimetype, $MIMEICONS)) {
|
||||||
|
$icon = $MIMEICONS[$mimetype];
|
||||||
|
} else { // Allow broad generic <format>/other icons
|
||||||
|
$mimefirst = explode("/", $mimetype, 2)[0];
|
||||||
|
if (array_key_exists($mimefirst . "/other", $MIMEICONS)) {
|
||||||
|
$icon = $MIMEICONS[$mimetype];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<div
|
||||||
|
class="list-group-item filepicker-item"
|
||||||
|
data-type="<?php echo $isdir ? "dir" : "file" ?>"
|
||||||
|
data-path="<?php echo "$folder/$f"; ?>"
|
||||||
|
data-file="<?php echo $f; ?>">
|
||||||
|
<span class="<?php echo $icon; ?> fa-fw"></span> <?php echo $f; ?>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($count == 0) {
|
||||||
|
?>
|
||||||
|
<div class="list-group-item text-center">
|
||||||
|
<p class="text-muted">
|
||||||
|
<i class="far fa-folder-open fa-5x fa-fw"></i>
|
||||||
|
</p>
|
||||||
|
<p class="h5 text-muted">
|
||||||
|
<?php lang("nothing here"); ?>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<?php
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
77
lib/filepicker_unsplash.php
Normal file
77
lib/filepicker_unsplash.php
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require_once __DIR__ . '/../required.php';
|
||||||
|
|
||||||
|
dieifnotloggedin();
|
||||||
|
|
||||||
|
header('Content-Type: application/json');
|
||||||
|
|
||||||
|
Crew\Unsplash\HttpClient::init([
|
||||||
|
'applicationId' => UNSPLASH_ACCESSKEY,
|
||||||
|
'secret' => UNSPLASH_SECRETKEY,
|
||||||
|
'utmSource' => UNSPLASH_UTMSOURCE
|
||||||
|
]);
|
||||||
|
|
||||||
|
$page = 1;
|
||||||
|
if (isset($_GET['page']) && is_numeric($_GET['page'])) {
|
||||||
|
$page = $_GET['page'];
|
||||||
|
}
|
||||||
|
|
||||||
|
$per_page = 15;
|
||||||
|
|
||||||
|
$results = null;
|
||||||
|
|
||||||
|
if (isset($_GET['query']) && $_GET['query'] != "") {
|
||||||
|
$results = Crew\Unsplash\Search::photos($_GET['query'], $page, $per_page, null, null);
|
||||||
|
$images = $results->getArrayObject();
|
||||||
|
} else {
|
||||||
|
$images = Crew\Unsplash\Photo::all($page, $per_page, 'popular');
|
||||||
|
}
|
||||||
|
|
||||||
|
$images->
|
||||||
|
|
||||||
|
$htmlout = "";
|
||||||
|
|
||||||
|
if (count($images) == 0) {
|
||||||
|
$htmlout = "<span>" . lang("no results", false) . "</span>";
|
||||||
|
}
|
||||||
|
|
||||||
|
$htmlout .= '<div class="card-columns">';
|
||||||
|
|
||||||
|
foreach ($images as $img) {
|
||||||
|
$imageid = $img->id;
|
||||||
|
$description = $img->description;
|
||||||
|
$thumb = $img->urls['thumb'];
|
||||||
|
$image = $img->urls['regular'];
|
||||||
|
$attribution = '<a href="' . $img->user['links']['html'] . '" target="_BLANK">' . $img->user['name'] . '</a>';
|
||||||
|
$card = <<<END
|
||||||
|
<div class="card m-1 filepicker-unsplashimg">
|
||||||
|
<img class="card-img-top" src="$thumb" alt="$description" data-path="$image" data-imageid="$imageid" />
|
||||||
|
<div class="card-img-overlay unsplash-attribution">
|
||||||
|
<p class="card-text">By $attribution</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
END;
|
||||||
|
$htmlout .= $card;
|
||||||
|
}
|
||||||
|
$htmlout .= '</div>';
|
||||||
|
|
||||||
|
$jsonout = [
|
||||||
|
'total' => null,
|
||||||
|
'pages' => null,
|
||||||
|
'page' => $page,
|
||||||
|
'html' => $htmlout
|
||||||
|
];
|
||||||
|
|
||||||
|
if (!is_null($results)) {
|
||||||
|
$jsonout['total'] = lang2("x results", ["results" => $results->getTotal()], false);
|
||||||
|
$jsonout['pages'] = $results->getTotalPages();
|
||||||
|
}
|
||||||
|
|
||||||
|
echo json_encode($jsonout);
|
@ -46,6 +46,8 @@ define("PAGES", [
|
|||||||
"scripts" => [
|
"scripts" => [
|
||||||
"static/js/html5sortable.min.js",
|
"static/js/html5sortable.min.js",
|
||||||
"static/js/iconselector.js",
|
"static/js/iconselector.js",
|
||||||
|
"static/js/filepicker_local.js",
|
||||||
|
"static/js/filepicker_unsplash.js",
|
||||||
"static/js/editorparent.js",
|
"static/js/editorparent.js",
|
||||||
]
|
]
|
||||||
],
|
],
|
||||||
|
@ -75,7 +75,7 @@ if (!is_empty($VARS['siteid'])) {
|
|||||||
?>
|
?>
|
||||||
|
|
||||||
<div class="modal fade" id="fileBrowseModal" tabindex="-1" role="dialog" aria-labelledby="fileBrowseLabel" aria-hidden="true">
|
<div class="modal fade" id="fileBrowseModal" tabindex="-1" role="dialog" aria-labelledby="fileBrowseLabel" aria-hidden="true">
|
||||||
<div class="modal-dialog" role="document">
|
<div class="modal-dialog modal-lg" role="document">
|
||||||
<div class="modal-content">
|
<div class="modal-content">
|
||||||
<div class="modal-header">
|
<div class="modal-header">
|
||||||
<h5 class="modal-title" id="fileBrowseLabel"><i class="far fa-folder-open"></i> <?php lang("browse"); ?></h5>
|
<h5 class="modal-title" id="fileBrowseLabel"><i class="far fa-folder-open"></i> <?php lang("browse"); ?></h5>
|
||||||
|
@ -48,6 +48,13 @@ define('PRETTY_URLS', false);
|
|||||||
// http://www.maxmind.com
|
// http://www.maxmind.com
|
||||||
define('GEOIP_DB', __DIR__ . "/GeoLite2-City.mmdb");
|
define('GEOIP_DB', __DIR__ . "/GeoLite2-City.mmdb");
|
||||||
|
|
||||||
|
// Unsplash photo integration
|
||||||
|
define('ENABLE_UNSPLASH', false);
|
||||||
|
define('UNSPLASH_APPID', '');
|
||||||
|
define('UNSPLASH_ACCESSKEY', '');
|
||||||
|
define('UNSPLASH_SECRETKEY', '');
|
||||||
|
define('UNSPLASH_UTMSOURCE', 'SiteWriter');
|
||||||
|
|
||||||
// Use Captcheck on login screen
|
// Use Captcheck on login screen
|
||||||
// https://captcheck.netsyms.com
|
// https://captcheck.netsyms.com
|
||||||
define("CAPTCHA_ENABLED", FALSE);
|
define("CAPTCHA_ENABLED", FALSE);
|
||||||
|
@ -4,6 +4,10 @@ License, v. 2.0. If a copy of the MPL was not distributed with this
|
|||||||
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
Uploaded file picker
|
||||||
|
*/
|
||||||
|
|
||||||
.filepicker-item {
|
.filepicker-item {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
color: #2196F3;
|
color: #2196F3;
|
||||||
@ -13,3 +17,33 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
|||||||
max-height: 200px;
|
max-height: 200px;
|
||||||
max-width: 200px;
|
max-width: 200px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Unsplash image picker
|
||||||
|
*/
|
||||||
|
|
||||||
|
.unsplash-attribution {
|
||||||
|
display: none;
|
||||||
|
background-color: rgba(0,0,0,.5);
|
||||||
|
color: white;
|
||||||
|
position: absolute;
|
||||||
|
left: 0;
|
||||||
|
right: 0;
|
||||||
|
bottom: 100%;
|
||||||
|
max-height: 30%;
|
||||||
|
height: 2rem;
|
||||||
|
padding: 0.25rem 0.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filepicker-unsplashimg .card-img-top {
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
|
.filepicker-unsplashimg .card-img-top:hover + .unsplash-attribution {
|
||||||
|
display: block;
|
||||||
|
}
|
||||||
|
|
||||||
|
.unsplash-attribution p a {
|
||||||
|
color: white;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
@ -68,7 +68,12 @@ function editComplex(json) {
|
|||||||
} else {
|
} else {
|
||||||
$("#imageEdit").data("image", content.image);
|
$("#imageEdit").data("image", content.image);
|
||||||
if (content.image != "") {
|
if (content.image != "") {
|
||||||
$("#imageEdit #selectedimage").attr("src", "public/file.php?file=" + content.image);
|
if (content.image.startsWith("http://") || content.image.startsWith("https://")) {
|
||||||
|
var imgsrc = content.image;
|
||||||
|
} else {
|
||||||
|
var imgsrc = "public/file.php?file=" + content.image;
|
||||||
|
}
|
||||||
|
$("#imageEdit #selectedimage").attr("src", imgsrc);
|
||||||
}
|
}
|
||||||
function loadComplexImageBrowser(path) {
|
function loadComplexImageBrowser(path) {
|
||||||
$.get("lib/filepicker.php", {
|
$.get("lib/filepicker.php", {
|
||||||
@ -76,15 +81,8 @@ function editComplex(json) {
|
|||||||
type: "image"
|
type: "image"
|
||||||
}, function (data) {
|
}, function (data) {
|
||||||
$("#imagepicker").html(data);
|
$("#imagepicker").html(data);
|
||||||
$("#imagepicker .filepicker-item").click(function () {
|
loadFilePickerFolder("/", "image", "complex");
|
||||||
if ($(this).data("type") == "dir") {
|
setupUnsplash("complex");
|
||||||
loadComplexImageBrowser($(this).data("path"));
|
|
||||||
} else {
|
|
||||||
var path = $(this).data("path");
|
|
||||||
$("#imageEdit").data("image", path);
|
|
||||||
$("#imageEdit #selectedimage").attr("src", "public/file.php?file=" + path);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
loadComplexImageBrowser();
|
loadComplexImageBrowser();
|
||||||
@ -112,40 +110,12 @@ function editComplex(json) {
|
|||||||
$("#editModal").modal();
|
$("#editModal").modal();
|
||||||
}
|
}
|
||||||
|
|
||||||
function loadFilePickerFolder(path, type) {
|
|
||||||
var ty = "";
|
|
||||||
switch (type) {
|
|
||||||
case "image":
|
|
||||||
ty = "image";
|
|
||||||
break;
|
|
||||||
case "media":
|
|
||||||
ty = "audio|video";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
$.get("lib/filepicker.php", {
|
|
||||||
path: path,
|
|
||||||
type: ty
|
|
||||||
}, function (data) {
|
|
||||||
$("#fileBrowseModalBody").html(data);
|
|
||||||
$("#fileBrowseModalBody .filepicker-item").click(function () {
|
|
||||||
if ($(this).data("type") == "dir") {
|
|
||||||
loadFilePickerFolder($(this).data("path"), type);
|
|
||||||
} else {
|
|
||||||
var path = "file.php?file=" + $(this).data("path");
|
|
||||||
var data = {
|
|
||||||
path: path,
|
|
||||||
meta: {}
|
|
||||||
};
|
|
||||||
json = JSON.stringify(data);
|
|
||||||
document.getElementById("editorframe").contentWindow.postMessage("picked " + json, "*");
|
|
||||||
$("#fileBrowseModal").modal('hide');
|
|
||||||
}
|
|
||||||
})
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
function openFilePicker(type) {
|
function openFilePicker(type) {
|
||||||
|
$.get("lib/filepicker.php", {}, function (data) {
|
||||||
|
$("#fileBrowseModalBody").html(data);
|
||||||
loadFilePickerFolder("/", type);
|
loadFilePickerFolder("/", type);
|
||||||
|
setupUnsplash();
|
||||||
|
});
|
||||||
$("#fileBrowseModal").modal();
|
$("#fileBrowseModal").modal();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
43
static/js/filepicker_local.js
Normal file
43
static/js/filepicker_local.js
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
function loadFilePickerFolder(path, type, pickertype) {
|
||||||
|
var ty = "";
|
||||||
|
switch (type) {
|
||||||
|
case "image":
|
||||||
|
ty = "image";
|
||||||
|
break;
|
||||||
|
case "media":
|
||||||
|
ty = "audio|video";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
$.get("lib/filepicker_local.php", {
|
||||||
|
path: path,
|
||||||
|
type: ty
|
||||||
|
}, function (data) {
|
||||||
|
$("#uploadedFilesBin").html(data);
|
||||||
|
$("#uploadedFilesBin .filepicker-item").click(function () {
|
||||||
|
if ($(this).data("type") == "dir") {
|
||||||
|
loadFilePickerFolder($(this).data("path"), type, pickertype);
|
||||||
|
} else {
|
||||||
|
var path = $(this).data("path");
|
||||||
|
if (typeof pickertype != 'undefined' && pickertype == 'complex') {
|
||||||
|
$("#imageEdit").data("image", path);
|
||||||
|
$("#imageEdit #selectedimage").attr("src", "public/file.php?file=" + path);
|
||||||
|
} else {
|
||||||
|
var data = {
|
||||||
|
path: path,
|
||||||
|
meta: {}
|
||||||
|
};
|
||||||
|
json = JSON.stringify(data);
|
||||||
|
document.getElementById("editorframe").contentWindow.postMessage("picked " + json, "*");
|
||||||
|
$("#fileBrowseModal").modal('hide');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
110
static/js/filepicker_unsplash.js
Normal file
110
static/js/filepicker_unsplash.js
Normal file
@ -0,0 +1,110 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
||||||
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*$('#fileBrowserTabs a').on('click', function (e) {
|
||||||
|
e.preventDefault();
|
||||||
|
$(this).tab('show');
|
||||||
|
});*/
|
||||||
|
|
||||||
|
var unsplash_page = 1;
|
||||||
|
var unsplash_query = "";
|
||||||
|
var unsplash_pickertype = "image";
|
||||||
|
|
||||||
|
function loadPhotos() {
|
||||||
|
// Disable the "load more" button and the search box
|
||||||
|
$("#unsplashLoadMoreBtn").attr("disabled", true);
|
||||||
|
$("#unsplashSearch").attr("disabled", true);
|
||||||
|
$("#unsplashSearchBtn").attr("disabled", true);
|
||||||
|
$.get("lib/filepicker_unsplash.php", {
|
||||||
|
page: unsplash_page,
|
||||||
|
query: unsplash_query
|
||||||
|
}, function (data) {
|
||||||
|
|
||||||
|
// Display total results
|
||||||
|
if (data.total != null) {
|
||||||
|
$("#unsplashResults").text(data.total);
|
||||||
|
} else {
|
||||||
|
$("#unsplashResults").text("");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the new results to the page
|
||||||
|
$("#unsplashPhotoBin").append(data.html);
|
||||||
|
|
||||||
|
// Re-enable the search box and button
|
||||||
|
$("#unsplashSearch").attr("disabled", false);
|
||||||
|
$("#unsplashSearchBtn").attr("disabled", false);
|
||||||
|
|
||||||
|
// Check if we have more results available or if the "load more" button
|
||||||
|
// should stay disabled
|
||||||
|
if (data.pages != null && data.page >= data.pages) {
|
||||||
|
$("#unsplashLoadMoreBtn").attr("disabled", true);
|
||||||
|
} else {
|
||||||
|
$("#unsplashLoadMoreBtn").attr("disabled", false);
|
||||||
|
}
|
||||||
|
$("#unsplashPhotoBin .filepicker-unsplashimg .card-img-top").click(function () {
|
||||||
|
var path = $(this).data("path");
|
||||||
|
if (typeof unsplash_pickertype != 'undefined' && unsplash_pickertype == 'complex') {
|
||||||
|
$("#imageEdit").data("image", path);
|
||||||
|
$("#imageEdit #selectedimage").attr("src", path);
|
||||||
|
} else {
|
||||||
|
var data = {
|
||||||
|
path: path,
|
||||||
|
meta: {}
|
||||||
|
};
|
||||||
|
json = JSON.stringify(data);
|
||||||
|
document.getElementById("editorframe").contentWindow.postMessage("picked " + json, "*");
|
||||||
|
$("#fileBrowseModal").modal('hide');
|
||||||
|
}
|
||||||
|
$.post("action.php", {
|
||||||
|
action: "unsplash_download",
|
||||||
|
imageid: $(this).data("imageid")
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function searchPhotos(query) {
|
||||||
|
unsplash_page = 1;
|
||||||
|
unsplash_query = query;
|
||||||
|
$("#unsplashPhotoBin").html("");
|
||||||
|
loadPhotos();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reset the photo browser to the default view (page one of popular photos)
|
||||||
|
*/
|
||||||
|
function loadDefaultPhotos() {
|
||||||
|
unsplash_page = 1;
|
||||||
|
unsplash_query = "";
|
||||||
|
$("#unsplashPhotoBin").html("");
|
||||||
|
loadPhotos();
|
||||||
|
}
|
||||||
|
|
||||||
|
function loadMorePhotos() {
|
||||||
|
unsplash_page++;
|
||||||
|
loadPhotos();
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupUnsplash(pickertype) {
|
||||||
|
if (typeof pickertype != 'undefined' && pickertype == 'complex') {
|
||||||
|
unsplash_pickertype = "complex";
|
||||||
|
}
|
||||||
|
$("#unsplashLoadMoreBtn").click(function () {
|
||||||
|
loadMorePhotos();
|
||||||
|
});
|
||||||
|
$("#unsplashSearchBtn").click(function () {
|
||||||
|
searchPhotos($("#unsplashSearch").val());
|
||||||
|
});
|
||||||
|
$('#unsplashSearch').on("keypress", function (e) {
|
||||||
|
if (e.which == 13) {
|
||||||
|
searchPhotos($("#unsplashSearch").val());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#unsplashTab").on("show.bs.tab", function () {
|
||||||
|
loadDefaultPhotos();
|
||||||
|
});
|
||||||
|
loadDefaultPhotos();
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user