diff --git a/img/error.svg b/img/error.svg new file mode 100644 index 00000000..413b63de --- /dev/null +++ b/img/error.svg @@ -0,0 +1,285 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + + + + + + + + + + diff --git a/lib/AppInfo/Application.php b/lib/AppInfo/Application.php index 48645697..b2a6f7b1 100644 --- a/lib/AppInfo/Application.php +++ b/lib/AppInfo/Application.php @@ -39,6 +39,26 @@ use OCP\Files\Events\Node\NodeTouchedEvent; class Application extends App implements IBootstrap { public const APPNAME = 'betterphotos'; + public const IMAGE_MIMES = [ + 'image/png', + 'image/jpeg', + 'image/heic', + // 'image/gif', // too rarely used for photos + // 'image/x-xbitmap', // too rarely used for photos + // 'image/bmp', // too rarely used for photos + // 'image/svg+xml', // too rarely used for photos + ]; + + public const VIDEO_MIMES = [ + // 'video/mpeg', // too rarely used for photos + // 'video/ogg', // too rarely used for photos + // 'video/webm', // too rarely used for photos + 'video/mp4', + // 'video/x-m4v', // too rarely used for photos + 'video/quicktime', + // 'video/x-matroska' // too rarely used for photos + ]; + public function __construct() { parent::__construct(self::APPNAME); } diff --git a/lib/Command/Index.php b/lib/Command/Index.php index 3b5fd951..9a70d7fe 100644 --- a/lib/Command/Index.php +++ b/lib/Command/Index.php @@ -77,7 +77,7 @@ class Index extends Command { $this->config = $config; $this->encryptionManager = $encryptionManager; $this->connection = $connection; - $this->util = new \OCA\BetterPhotos\Db\Util($previewGenerator, $connection); + $this->util = new \OCA\BetterPhotos\Db\Util($connection); try { $this->globalService = $container->get(GlobalStoragesService::class); diff --git a/lib/Controller/ApiController.php b/lib/Controller/ApiController.php index f8f3b409..cc105964 100644 --- a/lib/Controller/ApiController.php +++ b/lib/Controller/ApiController.php @@ -40,6 +40,7 @@ class ApiController extends Controller { private IConfig $config; private IUserSession $userSession; private IDBConnection $connection; + private \OCA\BetterPhotos\Db\Util $util; public function __construct( IRequest $request, @@ -52,6 +53,7 @@ class ApiController extends Controller { $this->config = $config; $this->userSession = $userSession; $this->connection = $connection; + $this->util = new \OCA\BetterPhotos\Db\Util($this->connection); } /** @@ -66,7 +68,7 @@ class ApiController extends Controller { return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); } - $list = \OCA\BetterPhotos\Db\Util::getDays($this->connection, $user->getUID()); + $list = $this->util->getDays($user->getUID()); return new JSONResponse($list, Http::STATUS_OK); } @@ -82,7 +84,7 @@ class ApiController extends Controller { return new JSONResponse([], Http::STATUS_PRECONDITION_FAILED); } - $list = \OCA\BetterPhotos\Db\Util::getDay($this->connection, $user->getUID(), intval($id)); + $list = $this->util->getDay($user->getUID(), intval($id)); return new JSONResponse($list, Http::STATUS_OK); } diff --git a/lib/Db/Util.php b/lib/Db/Util.php index 898f7ffd..78b11eb3 100644 --- a/lib/Db/Util.php +++ b/lib/Db/Util.php @@ -3,31 +3,29 @@ declare(strict_types=1); namespace OCA\BetterPhotos\Db; +use OCA\BetterPhotos\AppInfo\Application; use OCP\Files\File; -use OCP\DB\QueryBuilder\IQueryBuilder; use OCP\IDBConnection; -use OCP\IPreview; class Util { - protected IPreview $previewGenerator; protected IDBConnection $connection; - public function __construct(IPreview $previewGenerator, - IDBConnection $connection) { - $this->previewGenerator = $previewGenerator; + public function __construct(IDBConnection $connection) { $this->connection = $connection; } public static function getDateTaken($file) { // Attempt to read exif data - $exif = exif_read_data($file->fopen('rb')); - $dt = $exif['DateTimeOriginal']; - if ($dt) { - $dt = \DateTime::createFromFormat('Y:m:d H:i:s', $dt); - if ($dt) { - return $dt->getTimestamp(); - } - } + if (in_array($file->getMimeType(), Application::IMAGE_MIMES)) { + $exif = exif_read_data($file->fopen('rb')); + $dt = $exif['DateTimeOriginal']; + if ($dt) { + $dt = \DateTime::createFromFormat('Y:m:d H:i:s', $dt); + if ($dt) { + return $dt->getTimestamp(); + } + } + } // Fall back to creation time $dateTaken = $file->getCreationTime(); @@ -41,11 +39,7 @@ class Util { public function processFile(string $user, File $file, bool $update): void { $mime = $file->getMimeType(); - if (!str_starts_with($mime, 'image/')) { - return; - } - - if (!$this->previewGenerator->isMimeSupported($file->getMimeType())) { + if (!in_array($mime, Application::IMAGE_MIMES) && !in_array($mime, Application::VIDEO_MIMES)) { return; } @@ -96,11 +90,10 @@ class Util { } } - public static function getDays( - IDBConnection $connection, + public function getDays( string $user, ): array { - $qb = $connection->getQueryBuilder(); + $qb = $this->connection->getQueryBuilder(); $qb->select('day_id', 'count') ->from('betterphotos_day') ->where($qb->expr()->eq('user_id', $qb->createNamedParameter($user))) @@ -110,8 +103,7 @@ class Util { return $rows; } - public static function getDay( - IDBConnection $connection, + public function getDay( string $user, int $dayId, ): array { @@ -121,7 +113,7 @@ class Util { ON oc_filecache.fileid = oc_betterphotos.file_id WHERE user_id = ? AND day_id = ? ORDER BY date_taken DESC'; - $rows = $connection->executeQuery($sql, [$user, $dayId], [ + $rows = $this->connection->executeQuery($sql, [$user, $dayId], [ \PDO::PARAM_STR, \PDO::PARAM_INT, ]); return $rows->fetchAll(); diff --git a/src/App.vue b/src/App.vue index e0cf04f6..2cd87250 100644 --- a/src/App.vue +++ b/src/App.vue @@ -27,7 +27,7 @@ import Content from '@nextcloud/vue/dist/Components/Content' import AppContent from '@nextcloud/vue/dist/Components/AppContent' import AppNavigation from '@nextcloud/vue/dist/Components/AppNavigation' import AppNavigationItem from '@nextcloud/vue/dist/Components/AppNavigationItem' -import Timeline from './Timeline.vue' +import Timeline from './components/Timeline.vue' export default { name: 'App', diff --git a/src/Timeline.vue b/src/components/Timeline.vue similarity index 99% rename from src/Timeline.vue rename to src/components/Timeline.vue index d976f324..24561bca 100644 --- a/src/Timeline.vue +++ b/src/components/Timeline.vue @@ -25,6 +25,7 @@ @click="openFile(img, item)" :src="img.src" :key="img.file_id" @load = "img.l = Math.random()" + @error="(e)=>e.target.src='img/error.svg'" v-bind:style="{ width: rowHeight + 'px', height: rowHeight + 'px', @@ -53,7 +54,7 @@