Add some things

pull/37/head
Varun Patil 2022-08-13 03:34:05 +00:00
parent 6458abd0b4
commit 365b71b5bf
13 changed files with 249 additions and 41 deletions

View File

@ -1,15 +1,11 @@
<?php <?php
/**
* Create your routes in here. The name is the lowercase name of the controller
* without the controller part, the stuff after the hash is the method.
* e.g. page#index -> OCA\BetterPhotos\Controller\PageController->index()
*
* The controller class has to be registered in the application.php file since
* it's instantiated in there
*/
return [ return [
'routes' => [ 'routes' => [
['name' => 'page#index', 'url' => '/', 'verb' => 'GET'], ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
['name' => 'page#do_echo', 'url' => '/echo', 'verb' => 'POST'],
// API
['name' => 'api#list', 'url' => '/api/list', 'verb' => 'GET'],
['name' => 'api#listafter', 'url' => '/api/list/after/{time}', 'verb' => 'GET'],
['name' => 'api#listbefore', 'url' => '/api/list/before/{time}', 'verb' => 'GET'],
] ]
]; ];

View File

@ -1,3 +1,21 @@
#hello { #hello {
color: red; color: red;
} }
#photos {
width: 100%;
height: 100%;
overflow: auto;
display: grid;
grid-template-columns: auto auto auto auto auto auto;
column-gap: 3px;
row-gap: 3px;
}
img.photo {
height: 100%;
width: 100%;
margin: 0 0;
object-fit: cover;
display: inline-block;
}

View File

@ -0,0 +1,11 @@
(async () => {
const res = await fetch('/apps/betterphotos/api/list');
const data = await res.json();
for (const p of data) {
const img = document.createElement('img');
img.classList = 'photo';
img.src = `/core/preview?fileId=${p.file_id}&x=250&y=250`;
document.getElementById('photos').appendChild(img);
}
})();

View File

@ -60,7 +60,7 @@ class Index extends Command {
protected OutputInterface $output; protected OutputInterface $output;
protected IManager $encryptionManager; protected IManager $encryptionManager;
protected IDBConnection $connection; protected IDBConnection $connection;
protected \OCA\BetterPhotos\Util $util; protected \OCA\BetterPhotos\Db\Util $util;
public function __construct(IRootFolder $rootFolder, public function __construct(IRootFolder $rootFolder,
IUserManager $userManager, IUserManager $userManager,
@ -77,7 +77,7 @@ class Index extends Command {
$this->config = $config; $this->config = $config;
$this->encryptionManager = $encryptionManager; $this->encryptionManager = $encryptionManager;
$this->connection = $connection; $this->connection = $connection;
$this->util = new \OCA\BetterPhotos\Util($previewGenerator, $connection); $this->util = new \OCA\BetterPhotos\Db\Util($previewGenerator, $connection);
try { try {
$this->globalService = $container->get(GlobalStoragesService::class); $this->globalService = $container->get(GlobalStoragesService::class);

View File

@ -0,0 +1,150 @@
<?php
declare(strict_types=1);
/**
* @copyright Copyright (c) 2020 John Molakvoæ <skjnldsv@protonmail.com>
*
* @author John Molakvoæ <skjnldsv@protonmail.com>
*
* @license AGPL-3.0-or-later
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
namespace OCA\BetterPhotos\Controller;
use OCA\BetterPhotos\AppInfo\Application;
use OCP\AppFramework\Controller;
use OCP\AppFramework\Http;
use OCP\AppFramework\Http\JSONResponse;
use OCP\AppFramework\Http\StreamResponse;
use OCP\AppFramework\Http\ContentSecurityPolicy;
use OCP\IConfig;
use OCP\IDBConnection;
use OCP\IRequest;
use OCP\IUserSession;
class ApiController extends Controller {
private IConfig $config;
private IUserSession $userSession;
private IDBConnection $connection;
public function __construct(
IRequest $request,
IConfig $config,
IUserSession $userSession,
IDBConnection $connection
) {
parent::__construct(Application::APPNAME, $request);
$this->config = $config;
$this->userSession = $userSession;
$this->connection = $connection;
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* @return JSONResponse
*/
public function list(): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
$list = \OCA\BetterPhotos\Db\Util::getList($this->connection, $user->getUID());
return new JSONResponse($list, Http::STATUS_OK);
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* @return JSONResponse
*/
public function listafter(string $time): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
if (!is_numeric($time)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
$list = \OCA\BetterPhotos\Db\Util::getAfter($this->connection, $user->getUID(), intval($time));
return new JSONResponse($list, Http::STATUS_OK);
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*
* @return JSONResponse
*/
public function listbefore(string $time): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
if (!is_numeric($time)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
$list = \OCA\BetterPhotos\Db\Util::getBefore($this->connection, $user->getUID(), intval($time));
return new JSONResponse($list, Http::STATUS_OK);
}
/**
* @NoAdminRequired
*
* update preferences (user setting)
*
* @param string key the identifier to change
* @param string value the value to set
*
* @return JSONResponse an empty JSONResponse with respective http status code
*/
public function setUserConfig(string $key, string $value): JSONResponse {
$user = $this->userSession->getUser();
if (is_null($user)) {
return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED);
}
$userId = $user->getUid();
$this->config->setUserValue($userId, Application::APPNAME, $key, $value);
return new JSONResponse([], Http::STATUS_OK);
}
/**
* @NoAdminRequired
* @NoCSRFRequired
*/
public function serviceWorker(): StreamResponse {
$response = new StreamResponse(__DIR__.'/../../js/photos-service-worker.js');
$response->setHeaders([
'Content-Type' => 'application/javascript',
'Service-Worker-Allowed' => '/'
]);
$policy = new ContentSecurityPolicy();
$policy->addAllowedWorkerSrcDomain("'self'");
$policy->addAllowedScriptDomain("'self'");
$policy->addAllowedConnectDomain("'self'");
$response->setContentSecurityPolicy($policy);
return $response;
}
}

View File

@ -15,17 +15,11 @@ class PageController extends Controller {
} }
/** /**
* CAUTION: the @Stuff turns off security checks; for this page no admin is
* required and no CSRF check. If you don't know what CSRF is, read
* it up in the docs or you might create a security hole. This is
* basically the only required method to add this exemption, don't
* add it to any other method if you don't exactly know what it does
*
* @NoAdminRequired * @NoAdminRequired
* @NoCSRFRequired * @NoCSRFRequired
*/ */
public function index() { public function index() {
return new TemplateResponse('betterphotos', 'index'); // templates/index.php return new TemplateResponse('betterphotos', 'index');
} }
} }

View File

@ -1,7 +1,7 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace OCA\BetterPhotos; namespace OCA\BetterPhotos\Db;
use OCP\Files\File; use OCP\Files\File;
use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\DB\QueryBuilder\IQueryBuilder;
@ -23,10 +23,7 @@ class Util {
if ($dateTaken == 0) { if ($dateTaken == 0) {
$dateTaken = $file->getMtime(); $dateTaken = $file->getMtime();
} }
return $dateTaken;
$dateTakenDT = new \DateTime();
$dateTakenDT->setTimestamp($dateTaken);
return $dateTakenDT;
} }
public function processFile(string $user, File $file, bool $update): void { public function processFile(string $user, File $file, bool $update): void {
@ -52,7 +49,7 @@ class Util {
if ($update) { if ($update) {
$qb = $this->connection->getQueryBuilder(); $qb = $this->connection->getQueryBuilder();
$qb->update('betterphotos') $qb->update('betterphotos')
->set('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_DATE)) ->set('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_INT))
->where($qb->expr()->eq('id', $qb->createNamedParameter($row['id']))); ->where($qb->expr()->eq('id', $qb->createNamedParameter($row['id'])));
$qb->executeStatement(); $qb->executeStatement();
} }
@ -63,7 +60,7 @@ class Util {
$qb->insert('betterphotos') $qb->insert('betterphotos')
->setValue('user_id', $qb->createNamedParameter($user)) ->setValue('user_id', $qb->createNamedParameter($user))
->setValue('file_id', $qb->createNamedParameter($file->getId())) ->setValue('file_id', $qb->createNamedParameter($file->getId()))
->setValue('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_DATE)); ->setValue('date_taken', $qb->createNamedParameter($this->getDateTaken($file), IQueryBuilder::PARAM_INT));
$qb->executeStatement(); $qb->executeStatement();
} }
@ -73,4 +70,51 @@ class Util {
->where($qb->expr()->eq('file_id', $qb->createNamedParameter($file->getId()))); ->where($qb->expr()->eq('file_id', $qb->createNamedParameter($file->getId())));
$qb->executeStatement(); $qb->executeStatement();
} }
private static function getListQuery(
IDBConnection $connection,
string $user,
) {
$qb = $connection->getQueryBuilder();
$qb->select('file_id', 'date_taken')
->from('betterphotos')
->where($qb->expr()->eq('user_id', $qb->createNamedParameter($user)))
->orderBy('date_taken', 'DESC')
->setMaxResults(100);
return $qb;
}
public static function getList(
IDBConnection $connection,
string $user,
): array {
$qb = self::getListQuery($connection, $user);
$result = $qb->executeQuery();
$rows = $result->fetchAll();
return $rows;
}
public static function getAfter(
IDBConnection $connection,
string $user,
int $time,
): array {
$qb = self::getListQuery($connection, $user);
$qb->andWhere($qb->expr()->gte('date_taken', $qb->createNamedParameter($time, IQueryBuilder::PARAM_INT)));
$result = $qb->executeQuery();
$rows = $result->fetchAll();
return $rows;
}
public static function getBefore(
IDBConnection $connection,
string $user,
int $time,
): array {
$qb = self::getListQuery($connection, $user);
$qb->andWhere($qb->expr()->lte('date_taken', $qb->createNamedParameter($time, IQueryBuilder::PARAM_INT)));
$result = $qb->executeQuery();
$rows = $result->fetchAll();
return $rows;
}
} }

View File

@ -31,11 +31,11 @@ use OCP\IPreview;
use OCP\IDBConnection; use OCP\IDBConnection;
class PostDeleteListener implements IEventListener { class PostDeleteListener implements IEventListener {
private \OCA\BetterPhotos\Util $util; private \OCA\BetterPhotos\Db\Util $util;
public function __construct(IDBConnection $connection, public function __construct(IDBConnection $connection,
IPreview $previewGenerator) { IPreview $previewGenerator) {
$this->util = new \OCA\BetterPhotos\Util($previewGenerator, $connection); $this->util = new \OCA\BetterPhotos\Db\Util($previewGenerator, $connection);
} }
public function handle(Event $event): void { public function handle(Event $event): void {

View File

@ -34,13 +34,13 @@ use OCP\IUserManager;
class PostWriteListener implements IEventListener { class PostWriteListener implements IEventListener {
private IUserManager $userManager; private IUserManager $userManager;
private \OCA\BetterPhotos\Util $util; private \OCA\BetterPhotos\Db\Util $util;
public function __construct(IDBConnection $connection, public function __construct(IDBConnection $connection,
IUserManager $userManager, IUserManager $userManager,
IPreview $previewGenerator) { IPreview $previewGenerator) {
$this->userManager = $userManager; $this->userManager = $userManager;
$this->util = new \OCA\BetterPhotos\Util($previewGenerator, $connection); $this->util = new \OCA\BetterPhotos\Db\Util($previewGenerator, $connection);
} }
public function handle(Event $event): void { public function handle(Event $event): void {

View File

@ -30,7 +30,7 @@
'notnull' => true, 'notnull' => true,
'length' => 200, 'length' => 200,
]); ]);
$table->addColumn('date_taken', Types::DATETIME, [ $table->addColumn('date_taken', Types::INTEGER, [
'notnull' => false, 'notnull' => false,
]); ]);
$table->addColumn('file_id', Types::BIGINT, [ $table->addColumn('file_id', Types::BIGINT, [

View File

@ -1 +1,3 @@
<h1>Hello world</h1> <div id="photos">
<div style="grid-column: 1 / -1;">efef</div>
</div>

View File

@ -1,6 +1,6 @@
<?php <?php
script('betterphotos', 'script'); \OCP\Util::addScript('betterphotos', 'script');
style('betterphotos', 'style'); \OCP\Util::addStyle('betterphotos', 'style');
?> ?>
<div id="app"> <div id="app">

View File

@ -1,10 +1,3 @@
<ul> <ul>
<li><a href="#">First level entry</a></li> <li><a href="#">Timeline</a></li>
<li>
<a href="#">First level container</a>
<ul>
<li><a href="#">Second level entry</a></li>
<li><a href="#">Second level entry</a></li>
</ul>
</li>
</ul> </ul>